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

Medir una simulación de phishing sin vigilar a nadie

Un clic en un link de prueba no siempre es una persona. Medí una simulación autorizada con PhantomLog: permiso por escrito, reporte agregado, clics de escáneres filtrados y la IP real detrás de un proxy.

#phishing#awareness#privacidad#http

Antes de empezar necesitás

  • Saber leer un CSV y correr un script de Python
  • Idea básica de HTTP: método, headers y User-Agent
  • El entorno con Podman de este lab, o Python 3 con Flask

Al terminar vas a poder

  • Escribir la autorización de una simulación antes de enviar un solo link
  • Separar clics de personas de previsualizaciones, escáneres y gateways de correo
  • Reportar una campaña en forma agregada, sin rankings ni nombres
  • Explicar por qué remote_addr miente detrás de un proxy y cuándo confiar en X-Forwarded-For

Para ver y leer

Entorno listo con Podman

PhantomLog corriendo detrás de un proxy de juguete, con los datos sintéticos de una campaña de 40 personas y el reporte agregado. lab-check revisa la autorización, el filtro de ráfagas, el reporte y las tres IP del experimento del proxy.

# Una vez: cloná el repo y construí la imagen
git clone https://github.com/ValentinTorassa/Open-Security-Labs.git
cd Open-Security-Labs
podman build -t osl/medir-simulacion-phishing -f entornos/ciberseguridad/medir-simulacion-phishing/Containerfile entornos

# Abrí el entorno (se borra al salir)
podman run --rm -it --name osl-medir-simulacion-phishing --hostname labs -p 127.0.0.1:5000:5000 osl/medir-simulacion-phishing

# Al terminar, adentro del contenedor
lab-check
  • lab-check revisa lo que hiciste y guarda el resultado en /home/vt/evidencia. Desde otra terminal, en la carpeta del repo, npm run lab:check -- ciberseguridad/medir-simulacion-phishing corre el mismo chequeo y copia tu evidencia a evidencia/medir-simulacion-phishing/.
  • ¿Usás Docker? Cambiá podman por docker en los comandos y funciona igual.
  • Qué trae, qué revisa y sus límites: entornos/ciberseguridad/medir-simulacion-phishing/README.md.

Una simulación de phishing sirve para una sola cosa: saber si la capacitación funciona y dónde reforzarla. No sirve para escrachar a nadie. Y medirla bien es más difícil de lo que parece, porque buena parte de los “clics” no los hace una persona.

En este lab usás PhantomLog, un tracker de clics chico: genera un link único por destinatario y registra cuándo lo abren. No tiene formularios ni pide credenciales, y eso es a propósito. Todo lo que ves acá es sintético: personas seudónimas, IP de los rangos de documentación y una organización inventada.

La autorización no es un trámite. Es el documento que define qué vas a medir y qué no, y es lo primero que te van a pedir si algo sale mal. Como mínimo responde:

quién autoriza y quién opera        por escrito, con cargo
alcance                             áreas, cantidad de personas, canal, fechas
fuera de alcance                    qué no se toca (por ejemplo, pedir contraseñas)
qué se registra y qué no            PhantomLog: hora, id, IP, User-Agent, método
quién ve los resultados             y en qué forma (agregada)
retención y borrado                 cuándo se borran los logs crudos
comunicación                        cómo y cuándo se avisa a las personas
consecuencias                       qué pasa con quien hizo clic (debería ser: capacitación)

2. Un clic no es una persona

Cuando un mail llega a una organización, varias máquinas abren el link antes, o en lugar, de la persona:

  • Gateways de correo que “detonan” los links para revisarlos antes de entregar el mensaje. Suelen abrir los links de muchos destinatarios en segundos, desde la misma IP y con un User-Agent de navegador común.
  • Escáneres que solo piden HEAD para ver si el link responde.
  • Previsualizaciones: Slack, Telegram, WhatsApp y compañía piden la página para armar la tarjeta del link cuando alguien lo pega en un chat. A veces es justo la persona que pregunta “¿esto es phishing?”, que es lo que querés que haga.
  • Tu propio equipo probando el link con curl.
sequenceDiagram
participant G as Gateway de correo
participant S as Previsualización (Slack)
participant P as Persona
participant L as PhantomLog
G->>L: GET /log?id=… (22 ids en 8 s, misma IP)
G->>L: HEAD /log?id=…
S->>L: GET /log?id=… (User-Agent: Slackbot)
P->>L: GET /log?id=… (una vez, a su hora)
Tres de estos cuatro pedidos no son una persona haciendo clic.

Si contás todo, tu tasa de clics es la del gateway. En el entorno, la campaña sintética de 40 personas da 65% con un conteo ingenuo. Las reglas de filtros.py descartan HEAD y User-Agents de bots; la de ráfagas (misma IP, tres o más ids distintos en diez segundos) te toca escribirla a vos.

vt@labs:~/phishing
python3 reporte.py datos      # 26 de 40 (65.0%): el gateway cuenta como gente
nano filtros.py               # implementá es_rafaga
python3 reporte.py datos      # la tasa real, con 30 clics descartados

3. El reporte es agregado

reporte.py no tiene una opción para listar personas, y eso también es a propósito. Muestra la tasa de la campaña y la de cada área, pero esconde las áreas con menos de cinco personas: un “1 de 4” en dirección señala a alguien con nombre y apellido aunque el reporte no lo diga.

Personas que hicieron clic: 9 de 40 (22.5%)
Por área (solo grupos de 5 o más):
  finanzas     2 de 9 (22.2%)
  ...
  (1 área(s) con menos de 5 personas no se muestran)

El panel de PhantomLog sí muestra cada clic con su id. Es una herramienta de operación: la ve quien opera la campaña, con acceso restringido, y sus datos crudos se borran cuando vence la retención acordada.

4. La IP que miente detrás de un proxy

Casi ninguna app se publica sola: delante hay un nginx, un balanceador o el proxy de la plataforma donde la desplegás. Para la app, quien se conecta es el proxy, y request.remote_addr vale lo mismo para todos los clics. El proxy avisa la IP real en el header X-Forwarded-For.

vt@labs:~/phishing
# PhantomLog arrancó sin confiar en X-Forwarded-For (TRUSTED_PROXIES=0)
curl --interface 127.0.0.2 'http://127.0.0.1:8081/log?id=prueba-1'
tail -n 1 ~/phantomlog-datos/logs.csv     # IP: 127.0.0.1, la del proxy

# Confiá en un salto: el único proxy que hay
phantomlog-ctl restart --proxies 1
curl --interface 127.0.0.3 'http://127.0.0.1:8081/log?id=prueba-2'
tail -n 1 ~/phantomlog-datos/logs.csv     # IP: 127.0.0.3, la de origen

--interface elige la IP de origen dentro de 127.0.0.0/8, así podés simular clientes distintos en un solo contenedor. TRUSTED_PROXIES activa ProxyFix de Werkzeug, que toma la última IP de X-Forwarded-For: la que agregó tu proxy.

5. Guardá menos

Después de todo esto, mirá el log con otra pregunta: ¿qué hacía falta de verdad? Para la tasa de clics alcanza con el id seudónimo y una marca de “parece automático”. La IP ayudó a detectar el gateway, pero se puede truncar o descartar cuando la campaña cierra. Lo que no guardás no se puede filtrar.

Lo que practicás en este lab

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

  • Autorización completa de una campaña ficticia: alcance, datos, retención y comunicación
  • Reporte agregado con los clics descartados y el motivo de cada descarte
  • Tres líneas de log: la IP sin ProxyFix, con ProxyFix y con un X-Forwarded-For falso
  • Writeup sobre qué datos hacían falta de verdad para medir la campaña

Reto

La campaña sintética del entorno reporta 65% de clics. Implementá la regla de ráfagas en filtros.py hasta que el reporte dé la tasa real, y explicá en cuatro líneas qué fueron los 42,5 puntos de diferencia, qué regla los atrapó y qué clic de persona podría estar descartando mal esa regla.

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.