¿Desea omitir el filtro transversal del directorio en PHP?

6

Tengo una aplicación PHP heredada, que tiene un código similar a este:

<?php

$doc = $_GET['doc'];

if (preg_match('#\.\./#', $doc)) {
  header("HTTP/1.1 403 Forbidden");
  die();
}

$content = file_get_contents("/home/example/src/docs/" . $doc);

echo $content;

El filtro me parece un poco simplista. He intentado lanzarle todo tipo de ataques y parece que los detiene. ¿Alguien puede pensar en una manera de evitar este filtro?

    
pregunta Noodles 08.05.2016 - 23:30
fuente

3 respuestas

2

De hecho es demasiado simplista. Puedes evitarlo usando un carácter de barra invertida. Ejemplo de una manera de omitirlo en mi servidor IIS: http://example.com/index.php?doc=..\/index.php

Comprueba "../" mientras que, para que sea "más seguro", debe verificar ".." o no permite ningún punto y asegúrese de que solo esté incluido en la extensión del archivo solicitado.

    
respondido por el Technidev 09.05.2016 - 00:50
fuente
2

Si bien no puedo pensar en nada en un sistema Linux / POSIX que no sea el escape ya descrito por Technidev, eso no quiere decir que no haya uno. Si fuera yo, estaría confiando en realpath () pudiendo manejar la semántica de las cadenas de ruta correctamente, independientemente del sistema operativo subyacente ...

$basedir="/home/example/src/docs/";
$target=realpath("/home/example/src/docs/" . $_GET['doc']);
if (substr($target, 0, strlen($basedir)) != $basedir || !file_exists($target)) {
   header("HTTP/1.1 403 Forbidden");
   exit -1;
}
    
respondido por el symcbean 09.05.2016 - 13:41
fuente
1

Filtrado de entrada & Eludir

Los filtros siempre son excelentes como una capa adicional de seguridad, pero no deberían ser su única línea de defensa, ya que generalmente a los filtros les falta contexto, lo que hace imposible un filtrado 100% seguro.

Por ejemplo, su filtro no sabe nada sobre el sistema operativo subyacente. ¿Acepta \ como separador de directorio? Si es así, ..\ puede funcionar. @Technidev mencionó otro problema con ..\/ . Dependiendo del sistema operativo, otros ataques pueden funcionar también (por ejemplo, puede haber un carácter que se ignora al tratar las rutas, pero no al filtrar; probé %00 como ejemplo, pero no funciona). Sin embargo, no debería haber un desvío general que funcione independientemente del sistema operativo.

Un filtro mejor, pero posiblemente demasiado restrictivo, filtraría por .. .

Defensas adecuadas

Su pregunta implícita parece ser si este código es seguro o cómo hacerlo más seguro.

Si no necesita una ruta, solo use basename , que devolverá un nombre de archivo.

Si necesita una ruta, pero debería estar dentro del directorio docs, resuelva la ruta y compárela con la ruta base .

    
respondido por el tim 09.05.2016 - 11:14
fuente

Lea otras preguntas en las etiquetas