Resumen ejecutivo
Veredicto: VULNERABILIDADES CRITICAS ENCONTRADAS
Se detectaron 3 crashes con corrupción de memoria en el módulo dataflow_parser. Los errores permiten
ejecución de código arbitrario mediante archivos CSV/XLSX malformados subidos por usuarios externos.
Recomendación inmediata: parchear antes del próximo despliegue a producción.
Crashes únicos
3
2 críticos · 1 alto
Cobertura alcanzada
74%
1.847 de 2.493 ramas
Corpus final
312
inputs · 84 KB totales
Ejecuciones / s
4.2K
media durante campaña
Crashes detectados
| ID |
Severidad |
Tipo ASan |
Función afectada |
Input trigger (hex) |
Impacto |
| crash-001 |
Crítico |
heap-buffer-overflow READ |
parse_csv_row() |
46 55 5a 5a 2c 22 00 ff 41 41 41 41 41 ...×512 |
RCE posible via heap spray |
| crash-002 |
Crítico |
heap-use-after-free WRITE |
xlsx_sheet_alloc() |
50 4b 03 04 00 00 00 00 ff ff ff ff 00 00 ...×128 |
Corrupción de heap, RCE |
| crash-003 |
Alto |
stack-buffer-overflow READ |
validate_schema_str() |
7b 22 73 63 68 22 3a 20 22 41 41 ...×1024} |
Info leak de stack |
Cobertura por función objetivo
Línea de tiempo de la campaña
▶
T+0:00
Inicio campaña parse_csv
Corpus semilla: 4 ficheros CSV válidos. cov: 12 → 487 ramas en 30 s.
!
T+2:14
crash-001 detectado
heap-buffer-overflow en parse_csv_row(). Input guardado en corpus/crash-001.
▶
T+10:00
Inicio campaña parse_xlsx
Corpus semilla: 3 XLSX mínimos (PK magic bytes). cov: 8 → 312 ramas.
!
T+14:38
crash-002 detectado
heap-use-after-free en xlsx_sheet_alloc(). Corrupción confirmada con ASan.
▶
T+20:00
Inicio campaña validate_schema
Corpus semilla: 8 JSON schemas válidos. Modo -max_len=2048.
!
T+26:51
crash-003 detectado
stack-buffer-overflow en validate_schema_str(). Input mínimo: 1.036 bytes.
✓
T+30:00
Campaña completada
312 inputs en corpus final. 3 crashes reproducibles. Minimización aplicada.
Harnesses generados
fuzz_parse_csv.py
fuzz_parse_xlsx.py
fuzz_validate_schema.py
Dockerfile
import sys
import atheris
with atheris.instrument_imports():
import dataflow_parser
@atheris.instrument_func
def test_one_input(data: bytes):
if len(data) < 1:
return
try:
result = dataflow_parser.parse_csv(data)
if result and "rows" in result:
_ = result["rows"]
except (ValueError, UnicodeDecodeError, KeyError):
pass
def main():
atheris.Setup(sys.argv, test_one_input)
atheris.Fuzz()
if __name__ == "__main__":
main()
Reproducir crashes — comandos
Construir entorno Docker
docker build \
--build-arg PYTHON_VERSION=3.11 \
--build-arg LLVM_VERSION=19 \
-t dataflow-fuzz .
docker run --rm -it \
--cap-add SYS_PTRACE \
--security-opt seccomp=unconfined \
dataflow-fuzz
Reproducir crash-001 (CSV)
python -c "import atheris; print(atheris.__version__)"
python fuzz_parse_csv.py crash-001
python fuzz_parse_csv.py \
-minimize_crash=1 \
-max_total_time=60 \
crash-001
Recomendaciones
Prioridad 1 — Inmediata (crash-001, crash-002)
Corregir bounds checking en parse_csv_row() y gestión de memoria en xlsx_sheet_alloc().
Añadir validación de longitud antes de toda operación de lectura en el heap. Activar -D_FORTIFY_SOURCE=2 en compilación de producción.
Prioridad 2 — Esta semana (crash-003)
Aumentar el buffer estático en validate_schema_str() o migrar a asignación dinámica con limite explícito.
El stack overflow es explotable en entornos sin stack canaries.
Proceso continuo — Integración CI/CD
Integrar los 3 harnesses en ClusterFuzzLite (GitHub Actions). Cada PR que modifique dataflow_parser
debe ejecutar al menos 5 minutos de fuzzing. Corpus de regresión: guardar los 3 inputs de crash como corpus permanente.
Cobertura — Mejorar parse_xlsx y validate_schema
Las funciones de XLSX (71%) y schema (63%) tienen ramas sin explorar. Enriquecer corpus con:
XLSX con múltiples hojas, formulas, nombres compartidos; schemas con propiedades anidadas y $ref circulares.