Volver al inicio

Carga segura de archivos en Go: 7 ataques

El artículo describe la protección de la carga de archivos en Go frente a 7 ataques: spoofing de tipo magic bytes, DoS vía MaxBytesReader+slots, path traversal con rutas fijas. Identificación ECDSA de dispositivos sin cuentas para extensión de navegador.

7 ataques a la carga de archivos en Go y su protección
Advertisement 728x90

Proteger las subidas de archivos en Go: Defensa contra 7 ataques comunes

En sistemas sin autenticación tradicional, las subidas de archivos requieren una identificación robusta de la fuente de la solicitud. Para una extensión del navegador que convierte PDF a Markdown, se implementa un modelo basado en ECDSA P-256 usando la API WebCrypto. En el primer lanzamiento, se genera un par de claves no exportables:

const keyPair = await crypto.subtle.generateKey(
  { name: 'ECDSA', namedCurve: 'P-256' },
  false,  // extractable = false
  ['sign', 'verify']
);

La clave pública se registra en el servidor, devolviendo un device_id y un device_token. Cada solicitud a la API incluye:

  • Authorization: Bearer <token>
  • X-Timestamp (±5 minutos)
  • X-Nonce (anti-replay)
  • X-Body-SHA256
  • X-Signature (firma ECDSA sobre METHOD+PATH+TIMESTAMP+NONCE+BODY_HASH)

El servidor verifica la firma usando la clave pública, asegurando:

Google AdInline article slot
  • Límites de tasa por dispositivo
  • Protección contra ataques de repetición
  • Control de slots (máximo 3 tareas activas)
  • Límites de registro (5/IP/hora)

Este modelo aumenta el costo del ataque: emularlo requiere implementar completamente la firma ECDSA.

Ataque 1: Spoofing de tipo de archivo

Un atacante disfraza un ejecutable como un PDF. La defensa es múltiple, con tres niveles de protección.

Frontend: Validación de tipo MIME y extensión:

Google AdInline article slot
const ALLOWED_TYPES = ['application/pdf'];
const ALLOWED_EXTENSIONS = ['.pdf'];

function validateFile(file) {
  const isPdf = ALLOWED_TYPES.includes(file.type) ||
                ALLOWED_EXTENSIONS.some(ext =>
                  file.name.toLowerCase().endsWith(ext));
  if (!isPdf) return { valid: false, error: 'Solo PDF' };
}

Backend: Ruta basada en Content-Type. Crucial: Bytes mágicos:

pdfMagicBytes := "%PDF"
header4 := make([]byte, 4)
_, err := file.Read(header4)
if string(header4) != pdfMagicBytes {
    respondError(w, http.StatusBadRequest,
        models.ErrCodeValidationError,
        "El archivo no es un PDF válido")
}
file.Seek(0, 0)

Verificar los primeros bytes evita manipulaciones en encabezados o extensiones. Los archivos poliglotos (PDF válidos con contenido malicioso) requieren firmas adicionales.

Ataque 2: Agotamiento de disco (DoS)

Denegación de servicio mediante archivos grandes. Las medidas de mitigación incluyen:

Google AdInline article slot
  • http.MaxBytesReader(w, r.Body, MaxFileSize + 1MB) — detiene la lectura al alcanzar el límite.
  • Slots por dispositivo: máximo 3 tareas activas (queued, processing, ready, error).
  • Límites de tasa en registro y solicitudes.

La identificación por dispositivo hace inefectivas rotaciones de IP o token.

Ataque 3: Traversía de rutas

Un atacante usa ../../../etc/passwd. Solución: Ruta fija {UUID}/input.pdf. La entrada del usuario en rutas se ignora completamente.

Sanitización en frontend (capa adicional):

function sanitizeFileName(name) {
  return name
    .replace(/[/\\?%*:|"<>]/g, '-') 
    .replace(/^\.+/, '')
    .replace(/\.$/, '')
    .substring(0, 255)
    .trim();
}

El backend genera la ruta independientemente del nombre del archivo.

Ataque 4: SSRF mediante carga desde URL

Para la función "cargar desde URL", se bloquean:

  • Resolución DNS antes de la descarga
  • Redirecciones
  • IPs privadas (denegadas: 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)

Ataque 5: Repetición de ataques

X-Nonce + X-Timestamp + firma. El nonce se almacena por dispositivo; el timestamp se valida dentro de ±5 minutos.

Ataque 6: Impersonación de dispositivo

extractable: false garantiza que la clave privada no pueda exportarse. Robar device_token es inútil sin firmas válidas.

Ataque 7: Abuso a nivel de aplicación

Límites de tasa + control de slots + firma criptográfica. Máximo 3 slots, 5 registros/IP/hora.

Conclusiones clave

  • La identificación criptográfica por dispositivo reemplaza las cuentas para límites de tasa.
  • Los bytes mágicos (%PDF) son la única forma confiable de verificar el tipo de archivo.
  • MaxBytesReader + gestión de slots previenen DoS.
  • Rutas fijas eliminan riesgos de traversía.
  • ECDSA P-256 con nonce/timestamp bloquea repeticiones e impersonación.

— Editorial Team

Advertisement 728x90

Leer después