¿Qué hace AddressSanitizer (ASan)?
AddressSanitizer (ASan) es una herramienta ampliamente adoptada para la detección de errores de memoria, utilizada extensamente durante pruebas de software, especialmente fuzzing. Ayuda a detectar errores de corrupción de memoria que de otro modo pasarían desapercibidos, como desbordamientos de búfer, errores de uso después de liberación y otras violaciones de seguridad de memoria.
Descripción general
ASan es una práctica estándar en fuzzing debido a su efectividad para identificar vulnerabilidades de memoria. Instrumenta el código en tiempo de compilación para rastrear asignaciones y accesos a memoria, detectando operaciones ilegales en tiempo de ejecución.
Conceptos clave
| Concepto | Descripción |
|---|---|
| Instrumentación | ASan añade comprobaciones en tiempo de ejecución a las operaciones de memoria durante la compilación |
| Memoria sombra | Asigna 20 TB de memoria virtual para rastrear el estado de asignación |
| Coste de rendimiento | Aproximadamente 2-4 veces más lento en comparación con código no instrumentado |
| Alcance de detección | Encuentra desbordamientos de búfer, uso después de liberación, doble liberación y fugas de memoria |
Cuándo aplicarlo
Aplica esta técnica cuando:
- Hagas fuzzing de código C/C++ para vulnerabilidades de seguridad de memoria
- Pruebes código Rust con bloques inseguros (unsafe)
- Depures fallos relacionados con corrupción de memoria
- Ejecutes pruebas unitarias donde se sospechen errores de memoria
Omite esta técnica cuando:
- Ejecutes código en producción (ASan puede reducir la seguridad)
- La plataforma sea Windows o macOS (soporte limitado de ASan)
- El costo de rendimiento sea inaceptable para tu caso de uso
- Hagas fuzzing de lenguajes puramente seguros sin FFI (por ejemplo, Go puro, Java puro)
Referencia rápida
| Tarea | Comando/Patrón |
|---|---|
| Habilitar ASan (Clang/GCC) | -fsanitize=address |
| Habilitar verbosidad | ASAN_OPTIONS=verbosity=1 |
| Deshabilitar detección de fugas | ASAN_OPTIONS=detect_leaks=0 |
| Forzar aborto en error | ASAN_OPTIONS=abort_on_error=1 |
| Múltiples opciones | ASAN_OPTIONS=verbosity=1:abort_on_error=1 |
Paso a paso
Paso 1: Compilar con ASan
Compila y enlaza tu código con la bandera -fsanitize=address:
clang -fsanitize=address -g -o mi_programa mi_programa.c
Se recomienda la bandera -g para obtener mejores trazas de pila cuando ASan detecta errores.
Paso 2: Configurar opciones de ASan
Establece la variable de entorno ASAN_OPTIONS para configurar el comportamiento de ASan:
export ASAN_OPTIONS=verbosity=1:abort_on_error=1:detect_leaks=0
Paso 3: Ejecutar tu programa
Ejecuta el binario instrumentado con ASan. Cuando se detecten errores de memoria, ASan imprimirá informes detallados:
./mi_programa
Paso 4: Ajustar límites de memoria del fuzzer
ASan requiere aproximadamente 20 TB de memoria virtual. Deshabilita las restricciones de memoria del fuzzer:
- libFuzzer:
-rss_limit_mb=0 - AFL++:
-m none
Patrones comunes
Patrón: Integración básica de ASan
Caso de uso: Configuración estándar de fuzzing con ASan
Antes:
clang -o objetivo_fuzzing objetivo_fuzzing.c
./objetivo_fuzzing
Después:
clang -fsanitize=address -g -o objetivo_fuzzing objetivo_fuzzing.c
ASAN_OPTIONS=verbosity=1:abort_on_error=1 ./objetivo_fuzzing
Patrón: ASan con pruebas unitarias
Caso de uso: Habilitar ASan para un conjunto de pruebas unitarias
Antes:
gcc -o suite_pruebas suite_pruebas.c -lcheck
./suite_pruebas
Después:
gcc -fsanitize=address -g -o suite_pruebas suite_pruebas.c -lcheck
ASAN_OPTIONS=detect_leaks=1 ./suite_pruebas
Uso avanzado
Consejos y trucos
| Consejo | Por qué ayuda |
|---|---|
Usa la bandera -g | Proporciona trazas de pila detalladas para depuración |
Configura verbosity=1 | Confirma que ASan está habilitado antes de que el programa comience |
| Deshabilita detección de fugas durante fuzzing | La detección de fugas no causa fallos inmediatos, satura la salida |
Habilita abort_on_error=1 | Algunos fuzzers requieren abort() en lugar de _exit() |
Cómo interpretar informes de ASan
Cuando ASan detecta un error de memoria, imprime un informe detallado que incluye:
- Tipo de error: Desbordamiento de búfer, uso después de liberación, etc.
- Traza de pila: Dónde ocurrió el error
- Trazas de asignación/liberación: Dónde se asignó/liberó la memoria
- Mapa de memoria: Estado de la memoria sombra alrededor del error
Ejemplo de informe de ASan:
==12345==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60300000eff4 at pc 0x00000048e6a3
READ of size 4 at 0x60300000eff4 thread T0
#0 0x48e6a2 in main /ruta/al/archivo.c:42
Combinar sanitizadores
ASan se puede combinar con otros sanitizadores para una detección integral:
clang -fsanitize=address,undefined -g -o objetivo_fuzzing objetivo_fuzzing.c
Consideraciones específicas de plataforma
Linux: Soporte completo de ASan con el mejor rendimiento macOS: Soporte limitado, algunas características pueden no funcionar Windows: Soporte experimental, no recomendado para fuzzing en producción
Antipatrones
| Antipatrón | Problema | Enfoque correcto |
|---|---|---|
| Usar ASan en producción | Puede hacer que las aplicaciones sean menos seguras | Usa ASan solo para pruebas |
| No deshabilitar límites de memoria | El fuzzer puede matar el proceso debido a 20 TB de memoria virtual | Configura -rss_limit_mb=0 o -m none |
| Ignorar informes de fugas | Las fugas de memoria indican problemas de gestión de recursos | Revisa los informes de fugas al final de la campaña de fuzzing |
Guía específica de herramientas
libFuzzer
Compila con el fuzzer y el sanitizador de direcciones:
clang++ -fsanitize=fuzzer,address -g harness.cc -o fuzz
Ejecuta con RSS ilimitado:
./fuzz -rss_limit_mb=0
Consejos de integración:
- Siempre combina
-fsanitize=fuzzercon-fsanitize=address - Usa
-gpara trazas de pila detalladas en informes de fallos - Considera
ASAN_OPTIONS=abort_on_error=1para un mejor manejo de fallos
Ver: libFuzzer: AddressSanitizer
AFL++
Usa la variable de entorno AFL_USE_ASAN:
AFL_USE_ASAN=1 afl-clang-fast++ -g harness.cc -o fuzz
Ejecuta con memoria ilimitada:
afl-fuzz -m none -i dir_entrada -o dir_salida ./fuzz
Consejos de integración:
AFL_USE_ASAN=1añade automáticamente las banderas de compilación adecuadas- Usa
-m nonepara deshabilitar el límite de memoria de AFL++ - Considera
AFL_MAP_SIZEpara programas con mapas de cobertura grandes
cargo-fuzz (Rust)
Usa la bandera --sanitizer=address:
cargo fuzz run objetivo_fuzzing --sanitizer=address
O configura en fuzz/Cargo.toml:
[profile.release]
opt-level = 3
debug = true
Consejos de integración:
- ASan es útil para fuzzing de código Rust inseguro (unsafe) o límites FFI
- El código Rust seguro puede no beneficiarse tanto (el compilador ya previene muchos errores)
- Concéntrate en bloques unsafe, punteros crudos y enlaces con bibliotecas C
Ver: cargo-fuzz: AddressSanitizer
honggfuzz
Compila con ASan y enlaza con honggfuzz:
honggfuzz -i dir_entrada -o dir_salida -- ./objetivo_fuzzing_asan
Compila el objetivo:
hfuzz-clang -fsanitize=address -g objetivo.c -o objetivo_fuzzing_asan
Consejos de integración:
- honggfuzz funciona bien con ASan directamente
- Usa el modo guiado por retroalimentación para mejor cobertura con sanitizadores
- Monitorea el uso de memoria, ya que ASan aumenta la huella de memoria
Solución de problemas
| Problema | Causa | Solución |
|---|---|---|
| El fuzzer mata el proceso inmediatamente | Límite de memoria demasiado bajo para los 20 TB de memoria virtual de ASan | Usa -rss_limit_mb=0 (libFuzzer) o -m none (AFL++) |
| "ASan runtime not initialized" | Orden de enlace incorrecto o runtime faltante | Asegura que -fsanitize=address se use tanto en compilación como en enlace |
| Informes de fugas saturan la salida | LeakSanitizer habilitado por defecto | Configura ASAN_OPTIONS=detect_leaks=0 |
| Rendimiento pobre (>4x de ralentización) | Modo debug o compilación no optimizada | Compila con -O2 o -O3 junto a -fsanitize=address |
| ASan no detecta errores obvios | Binario no instrumentado | Verifica con ASAN_OPTIONS=verbosity=1 que ASan imprime información de inicio |
| Falsos positivos | Conflictos de interceptores | Consulta las FAQ de ASan para problemas conocidos con bibliotecas específicas |
Habilidades relacionadas
Herramientas que usan esta técnica
| Habilidad | Cómo se aplica |
|---|---|
| libfuzzer | Compila con -fsanitize=fuzzer,address para fuzzing integrado con detección de errores de memoria |
| aflpp | Usa la variable de entorno AFL_USE_ASAN=1 durante la compilación |
| cargo-fuzz | Usa la bandera --sanitizer=address para habilitar ASan en objetivos de fuzzing de Rust |
| honggfuzz | Compila el objetivo con -fsanitize=address para fuzzing instrumentado con ASan |
Técnicas relacionadas
| Habilidad | Relación |
|---|---|
| undefined-behavior-sanitizer | A menudo se usa junto con ASan para detección integral de errores (comportamiento indefinido + errores de memoria) |
| fuzz-harness-writing | Los harnesses deben diseñarse para manejar fallos detectados por ASan y evitar falsos positivos |
| coverage-analysis | El fuzzing guiado por cobertura ayuda a ejecutar rutas de código donde ASan puede detectar errores de memoria |
Recursos
Recursos externos clave
AddressSanitizer en Google Sanitizers Wiki
La documentación oficial de ASan cubre:
- Algoritmo y detalles de implementación
- Lista completa de tipos de errores detectados
- Características de rendimiento y sobrecarga
- Comportamiento específico de plataforma
- Limitaciones e incompatibilidades conocidas
Banderas de configuración comunes compartidas por todos los sanitizadores:
verbosity: Controla el nivel de salida de diagnósticolog_path: Redirige la salida del sanitizador a archivossymbolize: Habilita/deshabilita la resolución de símbolos en informesexternal_symbolizer_path: Usa un simbolizador personalizado
Opciones de configuración específicas de ASan:
detect_leaks: Controla la detección de fugas de memoriaabort_on_error: Llama aabort()vs_exit()en caso de errordetect_stack_use_after_return: Detecta errores de uso después de retorno en la pilacheck_initialization_order: Encuentra errores de orden de inicialización
Problemas comunes y soluciones:
- Problemas de orden de enlace
- Conflictos con otras herramientas
- Problemas específicos de plataforma
- Consejos de ajuste de rendimiento
Documentación de Clang sobre AddressSanitizer
Guía específica de Clang:
- Banderas y opciones de compilación
- Interacción con otras características de Clang
- Plataformas y arquitecturas compatibles
Opciones de instrumentación de GCC
Documentación de ASan específica de GCC:
- Banderas y comportamiento específicos de GCC
- Diferencias con la implementación de Clang
- Soporte de plataforma en GCC
AddressSanitizer: A Fast Address Sanity Checker (Artículo USENIX)
Artículo de investigación original con detalles técnicos:
- Algoritmo de memoria sombra
- Requisitos de memoria virtual (históricamente 16 TB, ahora ~20 TB)
- Evaluaciones comparativas de rendimiento
- Decisiones de diseño y compensaciones