2010-11-17 10 views

Respuesta

0

Supongo que quiere decir sin permitir usuarios para recorrer el directorio si?

Si está tratando de evitar que su propio PHP atraviese el directorio, debe hacer que el php funcione correctamente en primer lugar.

Lo que hay que evitar que los usuarios es un archivo .htaccess modificado ...

Options -Indexes 

(Todo esto supone que se está hablando de usuarios)

+0

MainMa entendió lo que estoy tratando de lograr. – Johnny

+0

Presenta '$ _GET', está claro que está tratando de evitar un ataque transversal de directorio por parte de hackers, así que no digas" solo debes hacer que el php funcione correctamente en primer lugar ". – FluorescentGreen5

93

Bueno, una opción sería comparar el verdadero caminos:

$basepath = '/foo/bar/baz/'; 
$realBase = realpath($basepath); 

$userpath = $basepath . $_GET['path']; 
$realUserPath = realpath($userpath); 

if ($realUserPath === false || strpos($realUserPath, $realBase) !== 0) { 
    //Directory Traversal! 
} else { 
    //Good path! 
} 

Básicamente, realpath() resolverán la ruta proporcionada a una ruta real físico duro (la resolución de enlaces simbólicos, .., ., /, //, etc.) ... Entonces, si la ruta de usuario real no comienza con la ruta base real, está intentando hacer un recorrido. Tenga en cuenta que la salida de realpath se no tiene ningún "directorios virtuales", como . o .. ...

+2

La única forma correcta de hacerlo ... –

+0

Editor: Strpos ya es seguro para varios bytes. La introducción de la alternativa mb puede introducir otras vulnerabilidades ... – ircmaxell

+1

¿Qué pasa con los enlaces simbólicos? ¿O qué sucede si el archivo que queremos verificar aún no existe? (es decir, crear un nuevo archivo en una ruta prospectiva). – Petah

4

no es suficiente para comprobar si hay patrones como ../ o los gustos. Tome "../" por ejemplo, qué URI codifica a "% 2e% 2e% 2f". Si su verificación de patrón ocurre antes de una decodificación, se perderá este intento de cruce. Hay otros trucos que los hackers pueden hacer para eludir un verificador de patrones, especialmente cuando usan cadenas codificadas.

He tenido el mayor éxito deteniendo esto canonicalizando cualquier cadena de ruta a su ruta absoluta usando algo como realpath() como sugiere ircmaxwell. Solo entonces empiezo a buscar ataques cruzados al compararlos con una ruta base que he predefinido.

12

La respuesta de ircmaxell no era del todo correcta. He visto esa solución en varios fragmentos pero tiene un error relacionado con la salida realpath(). La función realpath() elimina el separador de directorio de arrastre, así que imaginar dos directorios contiguos tales como:

/foo/bar/baz/ 

/foo/bar/baz_baz/ 

Como realpath() eliminaría el último separador de directorio, el método podría volver "buen camino" si $_GET['path'] era igual a" ../ Baz_baz", ya que sería algo así como

strpos("/foo/bar/baz_baz", "/foo/bar/baz") 

Tal vez:

$basepath = '/foo/bar/baz/'; 
$realBase = realpath($basepath); 

$userpath = $basepath . $_GET['path']; 
$realUserPath = realpath($userpath); 

if ($realUserPath === false || strcmp($realUserPath, $realBase) !== 0 || strpos($realUserPath, $realBase . DIRECTORY_SEPARATOR) !== 0) { 
    //Directory Traversal! 
} else { 
    //Good path! 
} 
+1

¿Qué hace "strcmp" allí en su código? – Andrew

1

Usted puede tener la tentación de tratar de utilizar expresiones regulares para eliminar todos los ../s pero hay algunas funciones interesantes incluidas con PHP que va a hacer un trabajo mucho mejor:

$ page = nombre base (realpath ($ _ GET));

nombre base - tiras toda la información del directorio de la ruta, por ejemplo ../pages/about.php se convertiría acerca .ph p

realpath: devuelve una ruta completa al archivo, p. about.php se convertiría en /home/www/pages/about.php, pero solo si el archivo existe.

Combinados devuelven solo el nombre de los archivos, pero solo si el archivo existe.

+0

¡No creo que esto impida atravesar! – Gerfried

Cuestiones relacionadas