DEV Community

MichaelSPeralta
MichaelSPeralta

Posted on

Cómo Realizar y Detectar Ataques de Path Injection

Antes que nada, no soy especialista en el tema, estoy aprendiendo y divirtiendome haciendo uso de herramientas de IA.

Dicho eso... Estuve realizando un desarrollo para un amigo, tiene un PDF con 100 hojas, con registros de transacciones bancarias. Necesita tener estos registros en un excel para poder procesarlo despues.

Con el uso de Github copilot, realice un script para la extraccion de datos usando python y algunas librerias... Tres doritos despues... Y como desayuno, almuerzo y ceno sistemas, levante un servidor flask, para servir el script atravez de un endpoint en un front con html, css y js puro y duro.

Durante el proceso de interaccion con Copilot, me levanto una alerta que una parte del código tenia una vulnerabilidad del tipo "path injection". Bastante interesante esta alerta :D

Y como estoy en busqueda de aprender mas sobre seguridad informatica, acá estoy blogeando para dejar registro de este journey...

Acá empieza a hablar la IA.

Un atacante podría explotar una vulnerabilidad de path injection manipulando la entrada del usuario para acceder a archivos o directorios no autorizados en el sistema de archivos del servidor. Aquí tienes un ejemplo de cómo podría hacerlo:

Ejemplo de Path Injection

Supongamos que tienes una ruta en tu aplicación Flask que permite a los usuarios subir archivos y guardarlos en el servidor. Si no validas o sanitizas el nombre del archivo, un atacante podría enviar un nombre de archivo malicioso para intentar acceder a archivos sensibles en el sistema.

Código Vulnerable

@app.route('/upload', methods=['POST'])
def upload():
    file = request.files['file']
    filename = file.filename  # Nombre del archivo proporcionado por el usuario
    save_path = os.path.join('uploads', filename)

    # Guardar el archivo sin validar el nombre del archivo
    with open(save_path, 'wb') as f:
        f.write(file.read())

    return 'File uploaded successfully'
Enter fullscreen mode Exit fullscreen mode

Ataque de Path Injection
Un atacante podría enviar una solicitud con un nombre de archivo malicioso como ../../etc/passwd. Esto podría resultar en la siguiente ruta:

uploads/../../etc/passwd

Si el servidor no valida ni sanitiza el nombre del archivo, el archivo podría ser guardado en una ubicación no deseada, permitiendo al atacante sobrescribir archivos sensibles en el sistema.

Solución: Validar y Sanitizar la Entrada
Para evitar este tipo de ataques, debes validar y sanitizar el nombre del archivo antes de guardarlo. Aquí tienes una versión segura del código:

Código Seguro

import os
import re
from flask import Flask, render_template, request, send_file
import requests
from datetime import datetime

app = Flask(__name__)

def sanitize_filename(filename):
    # Eliminar caracteres no permitidos del nombre del archivo
    return re.sub(r'[^a-zA-Z0-9_\-\.]', '', filename)

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/upload', methods=['POST'])
def upload():
    file = request.files['file']
    response = requests.post('http://127.0.0.1:5001/pdf-to-excel', files={'file': file})

    # Obtener la fecha actual
    current_date = datetime.now().strftime("%Y%m%d")

    # Obtener el nombre original del archivo sin la extensión
    original_filename = os.path.splitext(file.filename)[0]

    # Sanitizar el nombre del archivo
    sanitized_filename = sanitize_filename(original_filename)

    # Crear el nuevo nombre del archivo con la fecha al final
    output_filename = f'{sanitized_filename}_{current_date}.xlsx'

    # Crear la ruta completa del archivo
    save_path = os.path.join('uploads', output_filename)

    # Asegurarse de que la ruta sea absoluta
    save_path = os.path.abspath(save_path)

    # Guardar el archivo Excel resultante localmente con el nuevo nombre
    with open(save_path, 'wb') as f:
        f.write(response.content)

    # Enviar el archivo Excel de vuelta al usuario con el nuevo nombre
    return send_file(save_path, as_attachment=True, download_name=output_filename)

if __name__ == '__main__':
    app.run(port=5000, debug=True)
Enter fullscreen mode Exit fullscreen mode

Explicación del Código Seguro
Sanitizar el Nombre del Archivo: La función sanitize_filename elimina caracteres no permitidos del nombre del archivo utilizando una expresión regular.

Crear la Ruta Completa del Archivo: La función os.path.join se utiliza para crear la ruta completa del archivo, combinando el directorio de destino (uploads) con el nombre del archivo sanitizado (output_filename).

Asegurarse de que la Ruta sea Absoluta: La función os.path.abspath convierte la ruta en una ruta absoluta para evitar manipulaciones con rutas relativas.

Guardar el Archivo: Finalmente, el archivo se guarda en la ruta especificada.

Resumen
Path Injection: Un atacante puede manipular la entrada del usuario para acceder a archivos o directorios no autorizados.
Validación y Sanitización: Siempre valida y sanitiza las entradas del usuario para evitar ataques de path injection.
Rutas Absolutas: Utiliza rutas absolutas para evitar manipulaciones con rutas relativas.
Siguiendo estas prácticas, puedes proteger tu aplicación contra ataques de path injection y mejorar la seguridad general de tu sistema.

Acá le pregunté el how to para llegar a realizar el ataque. Además que me dejé registrados logs para poder depurar estos casos.

Para asegurar tu aplicación contra ataques de path injection, es útil entender cómo se pueden realizar estos ataques. Aquí te muestro cómo un atacante podría intentar explotar tu aplicación y cómo puedes detectar estas actividades en los logs.

1. Desde el Navegador

Manipulando Formularios HTML
Un atacante puede manipular un formulario HTML para enviar un nombre de archivo malicioso.

Paso a Paso:

  • Abre la página web con el formulario de subida de archivos.
  • Usa las herramientas de desarrollo del navegador (F12) para inspeccionar el formulario.
  • Modifica el valor del campo de archivo para incluir una ruta maliciosa, por ejemplo, ../../etc/passwd.
  • Envía el formulario.
  • Detección en Logs: Registra el nombre del archivo recibido en los logs.
import logging

# Configurar el logging
logging.basicConfig(filename='app.log', level=logging.INFO)

@app.route('/upload', methods=['POST'])
def upload():
    file = request.files['file']
    logging.info(f"Archivo recibido: {file.filename}")

    # Resto del código...
Enter fullscreen mode Exit fullscreen mode

2. Usando Herramientas como Postman

Enviando Solicitudes HTTP Manipuladas
Un atacante puede usar Postman para enviar solicitudes HTTP manipuladas directamente al servidor.

Paso a Paso:

  • Abre Postman y configura una solicitud POST a http://127.0.0.1:5000/upload.
  • En el cuerpo de la solicitud, selecciona form-data y añade un campo file con un archivo cuyo nombre sea ../../etc/passwd.
  • Envía la solicitud.
  • Detección en Logs: Registra el nombre del archivo recibido en los logs.

3. Mediante Scripts Automatizados

Usando Scripts en Python
Un atacante puede usar scripts en Python para enviar solicitudes HTTP maliciosas.

Ejemplo de Script en Python:

import requests

url = 'http://127.0.0.1:5000/upload'
files = {'file': ('../../etc/passwd', open('local_file.txt', 'rb'))}
response = requests.post(url, files=files)
print(response.text)
Enter fullscreen mode Exit fullscreen mode

Detección en Logs: Registra el nombre del archivo recibido en los logs.

Implementación de Logs para Detección
Aquí tienes una implementación completa que incluye logging para detectar nombres de archivos sospechosos:

from flask import Flask, render_template, request, send_file
import requests
from datetime import datetime
import os
import re
import logging

# Configurar el logging
logging.basicConfig(filename='app.log', level=logging.INFO)

app = Flask(__name__)

def sanitize_filename(filename):
    # Eliminar caracteres no permitidos del nombre del archivo
    return re.sub(r'[^a-zA-Z0-9_\-\.]', '', filename)

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/upload', methods=['POST'])
def upload():
    file = request.files['file']
    logging.info(f"Archivo recibido: {file.filename}")

    response = requests.post('http://127.0.0.1:5001/pdf-to-excel', files={'file': file})

    # Obtener la fecha actual
    current_date = datetime.now().strftime("%Y%m%d")

    # Obtener el nombre original del archivo sin la extensión
    original_filename = os.path.splitext(file.filename)[0]

    # Sanitizar el nombre del archivo
    sanitized_filename = sanitize_filename(original_filename)

    # Crear el nuevo nombre del archivo con la fecha al final
    output_filename = f'{sanitized_filename}_{current_date}.xlsx'

    # Crear la ruta completa del archivo
    save_path = os.path.join('uploads', output_filename)

    # Asegurarse de que la ruta sea absoluta
    save_path = os.path.abspath(save_path)

    # Guardar el archivo Excel resultante localmente con el nuevo nombre
    with open(save_path, 'wb') as f:
        f.write(response.content)

    logging.info(f"Archivo guardado en: {save_path}")

    # Enviar el archivo Excel de vuelta al usuario con el nuevo nombre
    return send_file(save_path, as_attachment=True, download_name=output_filename)

if __name__ == '__main__':
    app.run(port=5000, debug=True)
Enter fullscreen mode Exit fullscreen mode

Resumen
Desde el Navegador: Manipulando formularios HTML o usando herramientas de desarrollo del navegador.
Usando Herramientas como Postman: Enviando solicitudes HTTP manipuladas directamente al servidor.
Mediante Scripts Automatizados: Usando scripts en Python, Bash, o cualquier otro lenguaje para enviar solicitudes HTTP maliciosas.
Detección en Logs: Registra el nombre del archivo recibido y otras actividades sospechosas en los logs para detectar posibles ataques.
Implementando estas medidas, puedes mejorar la seguridad de tu aplicación y detectar actividades sospechosas que podrían indicar un intento de ataque.

Conclución: Bajo este contexto de aprendizaje y desarrollo haciendo pair programming con la IA, me parece sumamente útil este tipo de alertas en la plataforma para detectar vulnerabilidades. Hoy me levante pensando que iba a deployar a heroku el back y acá me encuentro descubriendo distintas vulnerabilidades :D

happy coding!

Top comments (0)