java security path-traversal

java - ¿Cuál es la mejor manera de defenderse contra un ataque transversal de ruta?



security path-traversal (3)

Si está ejecutando esto en una máquina Unix (no estoy seguro de si windows tiene algo similar, pero podría) querrá ver chroot. Incluso si cree que recurre a todos los métodos para que alguien remita algunos directorios, es bueno tener el sistema operativo allí haciendo cumplir el hecho.

(chroot hace que ''/'' se refiera a otro directorio, por lo que "/" podría ser "/ home / me / project" y "/../../ .." sigue siendo "/ home / me / project". )

EDITAR:

Hay una llamada al sistema chroot y una herramienta de línea de comandos chroot. No sé si Java tiene un método nativo, pero nada le impediría ejecutar su servidor con la herramienta de línea de comandos. Esto debería, por supuesto, ser además de hacer su mejor esfuerzo para evitar otras manipulaciones de ruta.

Tengo una implementación de servidor Java (TFTP si es importante para ti) y me gustaría asegurarme de que no sea susceptible a ataques de ruta cruzada que permitan el acceso a archivos y ubicaciones que no deberían estar disponibles.

Mi mejor intento de defender hasta ahora es rechazar cualquier entrada que coincida con File.isAbsolute() y luego confiar en File.getCanonicalPath() para resolver cualquier componente ../ and ./ fuera de la ruta. Finalmente, me aseguro de que la ruta resultante aún esté dentro del directorio raíz requerido de mi servidor:

public String sanitize(final File dir, final String entry) throws IOException { if (entry.length() == 0) { throw new PathTraversalException(entry); } if (new File(entry).isAbsolute()) { throw new PathTraversalException(entry); } final String canonicalDirPath = dir.getCanonicalPath() + File.separator; final String canonicalEntryPath = new File(dir, entry).getCanonicalPath(); if (!canonicalEntryPath.startsWith(canonicalDirPath)) { throw new PathTraversalException(entry); } return canonicalEntryPath.substring(canonicalDirPath.length()); }

¿Hay problemas de seguridad que esto falta? ¿Hay mejor / más rápido para lograr el mismo resultado de manera confiable?

El código debe funcionar de manera consistente en Windows y Linux.


Puede consultar los caracteres permitidos en los nombres de archivo ( http://en.wikipedia.org/wiki/Filename ) y filtrar todos los caracteres no permitidos (lista blanca) y luego puede estar seguro de que tiene un nombre de archivo allí.


Lo siguiente puede ayudar. Compara las rutas canónica y absoluta, y si difieren, entonces fallará. Solo probado en un sistema Mac / Linux (es decir, sin ventanas).

Esto es para el caso en el que desea permitir que el usuario proporcione una ruta relativa, no una ruta absoluta, y no permite ninguna referencia de directorio principal.

public void failIfDirectoryTraversal(String relativePath) { File file = new File(relativePath); if (file.isAbsolute()) { throw new RuntimeException("Directory traversal attempt - absolute path not allowed"); } String pathUsingCanonical; String pathUsingAbsolute; try { pathUsingCanonical = file.getCanonicalPath(); pathUsingAbsolute = file.getAbsolutePath(); } catch (IOException e) { throw new RuntimeException("Directory traversal attempt?", e); } // Require the absolute path and canonicalized path match. // This is done to avoid directory traversal // attacks, e.g. "1/../2/" if (! pathUsingCanonical.equals(pathUsingAbsolute)) { throw new RuntimeException("Directory traversal attempt?"); } }