Log Analysis - Compromised WordPress


Pipeline de análisis inicial

cat access.log | grep "POST" | awk '{print $7}' | sort | uniq -c | sort -nr
  • cat access.log: Inyecta el archivo en el flujo de datos.
  • grep "POST": Descarta todo el ruido de lectura (GET). Solo interesan las modificaciones y ejecuciones de código que el atacante envió al servidor.
  • awk '{print $7}': Extrae exactamente la séptima columna (la URL de la petición), ignorando fechas, navegadores y basura.
  • sort | uniq -c | sort -nr: Agrupa las URLs idénticas, las cuenta y las devuelve en orden descendente.

Para ver qué plugins específicos instaló y activó a través de peticiones GET:

grep "action=activate" access.log | awk '{print $7}' | cut -d'=' -f3 | cut -d'&' -f1

Anatomía del Log

Columna 1 — IP del Cliente

Muestra direcciones como 172.21.0.1 o 127.0.0.1. Es la coordenada de red de origen. En respuesta a incidentes, esta es la firma balística del atacante; la pista principal que debes aislar para bloquear su nodo.

Columna 2 — Marca de Tiempo

Extraído como [12/Jan/2021:15:52:41 +0000]. El sello temporal y zona horaria. Esto es vital para construir la línea de tiempo del incidente.

Columna 3 — La Petición

Muestra el método, la ruta y el protocolo. Ejemplo: "GET / HTTP/1.1". Este es el vector de ataque puro. Te revela si el atacante simplemente escanea (GET) o si inyecta código, altera configuraciones e instala plugins maliciosos (POST).

Columna 4 — Código de Estado HTTP

Muestra números como 200, 302 o 500. Es el veredicto del servidor. Un 200 significa que el atacante tuvo éxito; un 404 que exploró el vacío buscando backdoors inexistentes; un 500 indica que sus peticiones colapsaron un subproceso.

Columna 5 — Tamaño de la Respuesta

Representado en bytes, como 5173. Indica el volumen exacto de datos que el servidor entregó al host malicioso. Picos inusuales en esta columna son prueba irrefutable de exfiltración de base de datos o archivos voluminosos.

Columna 6 — User-Agent

El disfraz del navegador. Ejemplo: "Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0". Es la cadena que usa la herramienta o el atacante para identificarse. Si el atacante fuese un novato, esta columna a menudo los traiciona mostrando firmas literales como "Nmap" o "WPScan".


Resumen de Actividad

Se han procesado un total de 1,978 peticiones válidas a partir de los datos proporcionados.

  • Distribución por Código de Estado: La gran mayoría de las peticiones fueron exitosas (código 200), aunque se observa un volumen considerable de errores 404 (No encontrado) y 403 (Prohibido).
  • Concentración de Tráfico: Una única dirección IP (172.21.0.1) es responsable de más de la mitad de las peticiones totales, lo que sugiere una actividad intensa desde esa fuente específica.

Top 5 Códigos de Estado

#CódigoSignificadoPeticiones
1200OK1,435
2404Not Found272
3403Forbidden163
4302Found/Redirect65
5304Not Modified22

Top 5 Direcciones IP

#IPPeticiones
1172.21.0.11,024
2119.241.22.121249
3168.22.54.119168
4116.23.212.69141
5156.32.113.2571

Contexto

Uno de los sitios de WordPress ha sido comprometido, pero aún desconocemos cómo. La hipótesis principal es que un plugin instalado era vulnerable a una ejecución remota de código que le dio al atacante acceso al sistema operativo del servidor.

Para separar el grano de la paja, lo primero es entender qué estamos buscando. En WordPress, los ataques suelen seguir este orden:

  1. Reconocimiento: Buscan plugins vulnerables.
  2. Autenticación: Intentan entrar al /wp-admin.
  3. Explotación: Suben una webshell o modifican un plugin/tema.

Visión General (Estadísticas Rápidas)

Antes de leer líneas individuales, necesitamos saber quién es el más “ruidoso”:

cut -d' ' -f1 "Log Analysis - Compromised WordPress.log" | sort | uniq -c | sort -nr

Identificar el panel de administración

Normalmente en WordPress es wp-login.php o wp-admin, pero a veces los administradores usan plugins para cambiar esta URL por seguridad.

Busca peticiones de la IP más sospechosa que tengan que ver con “login” o “admin”. Busca una petición que contenga un Token. Los tokens suelen aparecer en la URL después de un signo de interrogación (ej. ?token=123...).


¿Cómo descartar la “paja”?

En un log de WordPress verás miles de peticiones a .css, .js, .png, .jpg — esto es carga normal de la web. Descártalo. También descarta peticiones GET que devuelven 200 OK a páginas de blog.

Céntrate en:

  1. Peticiones POST: Intentos de inicio de sesión, envío de formularios o subida de archivos.
  2. Peticiones a /wp-content/plugins/: Aquí es donde suelen ocurrir las vulnerabilidades de RCE (Remote Code Execution).

Filtra solo lo que “escribe” o “ejecuta” la IP sospechosa:

grep "POST" "Log Analysis - Compromised WordPress.log" | awk '{print $1, $7, $9}'

Preguntas clave:

  • ¿Hay alguna URL de login que no sea la estándar de WordPress?
  • ¿Hay algún parámetro largo y raro (el token) en alguna de esas URLs?

Preguntas del desafío

  1. Identifique la URI del panel de inicio de sesión de administrador al que el atacante obtuvo acceso (incluye el token).
  2. ¿Puedes identificar dos herramientas que utilizó el atacante?
  3. El atacante intentó explotar una vulnerabilidad en “Contact Form 7”. ¿A qué CVE era vulnerable el plugin?
  4. ¿Qué plugin se utilizó para obtener acceso?
  5. ¿Cuál es el nombre del archivo de shell web PHP?
  6. ¿Cuál fue el código de respuesta HTTP proporcionado al acceder a la consola web por última vez?