Código seguro java para evitar ataques path traversal (controlar la interacción con el sistema de archivos)

Cuando vamos a interactuar desde el código con el sistema de archivos, por ejemplo para crear uno nuevo, debemos tener cuidado con los datos de entrada del usuario. Un payload habitual es el comando especial de dos puntos seguidos «..», que para la ejecución de la mayoría de los sistemas de archivos es subir un nivel, ir al directorio padre. Un atacante puede jugar con nuestra aplicación desde el exterior con este tipo de comandos especiales, si no lo controlamos.

A continuación un ejemplo en código Java para evitar ataques, controlando la ruta y el nombre del archivo:

private static final String variable_Constante_Directorio = "/opt/application/directorio_padre_subida_archivos";

public static String dameContenidoArchivo(String ruta_A_Controlar, String nombre_Archivo) throws IOException {

  //Esta llamada elimina la posible aparición del comando especial ".." para descender de directorio (el elemento mas usado en ataques informaticos de tipo path trasversal). Ejemplo: transforma esto "a/b/../c" en esto "a/c"
  //El método normalize() de java.nio.file.Path se utiliza para devolver una ruta a partir de la ruta actual en la que se eliminan todos los elementos de nombre redundantes. Como por ejemplo "." y ".." que son comandos especiales que indican el directorio actual y el directorio padre. 
  String ruta_A_Controlar_Normalizada = Paths.get(ruta_A_Controlar).normalize().toString();

  //El método "FilenameUtils.getName" nos devuelve solo el nombre final del archivo e ignora cualquier otro contenido 
  String nombre_Archivo_Controlado = FilenameUtils.getName(nombre_Archivo);

  File archivo = new File(ruta_A_Controlar_Normalizada, nombre_Archivo_Controlado);

  //Comprobación de que el archivo con el que vamos a trabajar tiene como ruta padre la indicada como segura
  if (archivo.getCanonicalPath().startsWith(variable_Constante_Directorio)) {
    String contenido = new String(Files.readAllBytes(archivo.toPath()));
    return contenido;
  } else {
    //
  }
}

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

error: