Saltar al contenido
Open Security
Ciberseguridad PrácticaIntermedio· 30 min

Seccomp: observá una carga de juguete antes de bloquear

Capturá syscalls de un contenedor descartable con AutoConfine, revisá la procedencia de la traza y usá audit para buscar diferencias sin romper la carga.

#linux#contenedores#seccomp#ebpf

Antes de empezar necesitás

  • VM descartable Linux amd64 con cgroup v2, Podman, Go y permisos sudo
  • Saber qué son un contenedor y una syscall

Al terminar vas a poder

  • Distinguir una traza eBPF observada de una traza sintética
  • Generar y validar un perfil seccomp para una carga concreta
  • Leer drift en modo audit antes de considerar una restricción
  • Explicar por qué una ventana corta no prueba cobertura completa

Miralo en video

Una lista de syscalls permitidas sólo sirve si sabés de dónde salió y qué ejecutó el contenedor durante la medición. En este lab usás AutoConfine sobre una imagen pública de juguete, en una VM que puedas descartar. No uses un servicio, datos ni credenciales reales.

Capturá desde el arranque

En la VM, cloná AutoConfine y compilá el binario. Estos comandos no publican puertos:

vt@vm:~
git clone https://github.com/ValentinTorassa/AutoConfine.git
cd AutoConfine
go build -o autoconfine ./cmd/autoconfine
sudo podman pull docker.io/library/nginx:alpine
sudo ./autoconfine learn --image docker.io/library/nginx:alpine \
  --from-start --duration 8s --out trace.jsonl
sudo ./autoconfine generate trace.jsonl --out profile.json
sudo ./autoconfine validate profile.json

--from-start prepara el contenedor, conecta la sonda eBPF y recién entonces inicia la aplicación. La traza debe contener eventos con phase: observed-ebpf y capture_mode: from-exec. validate comprueba que el perfil tenga una estructura seccomp válida; no comprueba que la carga esté cubierta en todos sus estados.

Leé los datos que juntaste

Usá un resumen que no imprima el contenido de cada evento:

vt@vm:~/AutoConfine
sudo ./autoconfine summary trace.jsonl
sudo python3 - <<'PY'
import collections, json
events = [json.loads(line) for line in open('trace.jsonl') if line.strip()]
print('eventos:', len(events))
print('syscalls únicas:', len({e['syscall'] for e in events}))
print('orígenes:', dict(collections.Counter(e.get('capture_mode') for e in events)))
PY

Esos números describen ocho segundos de esa ejecución. Otro pedido, configuración o versión de la imagen puede usar otras syscalls. Tampoco asumás que una syscall observada es necesaria o segura: el perfil es un punto de partida para revisión.

Auditá una segunda carga

El modo audit permite ejecutar syscalls fuera del perfil y las anota. Probá el comando id dentro de la misma imagen, sin publicar puertos ni montar archivos:

vt@vm:~/AutoConfine
sudo ./autoconfine enforce --profile profile.json --audit \
  --out audit.jsonl -- podman run --rm --entrypoint /bin/sh \
  docker.io/library/nginx:alpine -c 'id >/dev/null'
sudo python3 - <<'PY'
import collections, json
events = [json.loads(line) for line in open('audit.jsonl') if line.strip()]
print('drift audit:', len(events))
print('por syscall:', dict(collections.Counter(e['syscall'] for e in events)))
PY

AutoConfine sale con código 2 si detecta drift; en este ejercicio puede ser el resultado esperado. Si no registra diferencias, documentá cero y el comando exacto: una observación vacía también es un dato. --audit cambia la acción por defecto del perfil a SCMP_ACT_LOG; no bloquea esas llamadas. Para comparar de verdad, repetí con cargas representativas antes de restringir nada.

El ensayo Linux del proyecto comprobó además los dos mecanismos de drift en vivo: audit con sys_enter y monitor con sys_exit. Para el segundo usó un perfil de prueba derivado del perfil normal de Podman; un perfil aprendido con nginx no tiene por qué iniciar un comando diferente. Esa evidencia demuestra el funcionamiento de las sondas en esa VM, no que el perfil generado sea apto para producción.

Lo que practicás en este lab

Llevátelo a tu repo si querés, pero no es obligatorio: es tu aprendizaje.

  • Conteo de eventos y syscalls únicas de una traza del contenedor de juguete
  • Perfil validado y tres líneas de drift audit con contenido del host omitido
  • Writeup breve sobre procedencia, cobertura y pasos previos a aplicar el perfil

Reto

Explicá por qué el perfil observado para nginx no debe aplicarse sin pruebas a otro comando o imagen. Entregá el conteo de la traza, el resultado de validate y una interpretación de audit.

Resolvelo y escribí dos líneas explicando qué pasó. Con eso lo fijás.

¿Hiciste el lab?

Si querés, guardá lo que hiciste (comandos, notas, un repo) para volver después. Y si encontrás un error o querés mejorar este lab,contribuí al repo. El progreso se guarda solo en tu navegador.