Informe Comparativo — Brute Force DVWA (Low → Medium → High → Impossible)
Data: 2026-04-26
Contorno: Laboratorio controlado — DVWA 2.x en http://10.0.2.100
Clasificación: Educativo / CTF
1. Táboa Resumo
| Nivel | Token CSRF | Retardo fallo | Bloqueo conta | Consultas PDO | Explotable | Técnica usada |
|---|---|---|---|---|---|---|
| Low | ✗ | ✗ | ✗ | ✗ | ✅ | Hydra http-get-form directo |
| Medium | ✗ | 2 s fixos | ✗ | ✗ | ✅ | Hydra + -t 1 -w 3 adaptado ao retardo |
| High | ✓ (por sesión) | 2 s fixos | ✗ | ✗ | ✅ | Script Python: GET token → POST creds |
| Impossible | ✓ (por petición) | 2–4 s aleatorio | ✓ (3 fallos / 15 min) | ✓ | ❌ | Non explotable |
2. Análise por Nivel Explotable
2.1 Nivel Low
Fallo principal: Ausencia total de proteccións anti-brute-force (CWE-307) e sen token CSRF (CWE-352).
Técnica: Hydra con http-get-form e cookie de sesión. O servidor responde instantaneamente a cada petición.
hydra -l admin -P wordlist.txt 10.0.2.100 \
http-get-form '/dvwa/vulnerabilities/brute/: \
username=^USER^&password=^PASS^&Login=Login: \
H=Cookie\: PHPSESSID=...; security=low: \
Username and/or password incorrect' -t 16
Resultado: Contrasinal password atopado en < 1 s.
CWEs relevantes:
- CWE-307 — Improper Restriction of Excessive Authentication Attempts
- CWE-352 — Cross-Site Request Forgery (Missing CSRF Token)
- CWE-521 — Weak Password Requirements (contrasinal trivial)
CVEs ilustrativos da mesma clase:
| CVE | Produto | Descrición |
|---|---|---|
| CVE-2019-5420 | Ruby on Rails (activestorage) |
Brute force sen límite en endpoint de autenticación |
| CVE-2021-22175 | GitLab CE/EE | Sen rate-limiting en API de autenticación |
| CVE-2020-15782 | Siemens SCALANCE | Autenticación HTTP sen bloqueo de conta |
Puntuación CVSS v3.1:
| Métrica | Valor | Razón |
|---|---|---|
| Attack Vector | Network (N) | Accesible vía HTTP |
| Attack Complexity | Low (L) | Sen condición especial |
| Privileges Required | None (N) | Non require conta previa |
| User Interaction | None (N) | Totalmente automatizable |
| Confidentiality | High (H) | Credenciais comprometidas |
| Integrity | High (H) | Toma de conta completa |
| Availability | None (N) | Sen impacto de dispoñibilidade |
Base Score: 9.1 — CRÍTICO
2.2 Nivel Medium
Fallo principal: O sleep(2) reduce a velocidade do ataque pero non o impide. Segue sen CSRF nin bloqueo (CWE-307 + CWE-208).
Técnica: Hydra con -t 1 (un fío) para respectar o retardo fixo. O formulario acepta o mesmo token durante toda a sesión.
hydra -l admin -P wordlist.txt 10.0.2.100 \
http-get-form '.../brute/: \
username=^USER^&password=^PASS^&Login=Login: \
H=Cookie\: PHPSESSID=...; security=medium: \
Username and/or password incorrect' -t 1 -w 3
Resultado: Contrasinal password atopado en 8 s (4.º intento × ~2 s/intento).
Tempo máximo wordlist completa (197 entradas): ~394 s (~6,5 min).
CWEs relevantes:
- CWE-307 — Sin bloqueo de conta
- CWE-208 — Observable Timing Discrepancy (retardo fixo e predecible)
- CWE-352 — Sen token CSRF
CVEs ilustrativos:
| CVE | Produto | Descrición |
|---|---|---|
| CVE-2019-7642 | Mautic | Brute force con retardo fixo contornable con fíos únicos |
| CVE-2022-22947 | Spring Cloud Gateway | Rate-limiting incompleto en rutas protexidas |
| CVE-2021-43798 | Grafana | Path traversal + auth sen lockout |
Puntuación CVSS v3.1:
Base Score: 9.1 — CRÍTICO
Nota: O retardo de 2 s non reduce a puntuación base de CVSS (non é un control de seguridade efectivo); só incrementa o tempo de explotación.
2.3 Nivel High
Fallo principal: O token CSRF rénvase por sesión PHP, non por petición. Un atacante que obtén un token válido pode reutilizalo durante toda a sesión (CWE-352 parcial). Ademais non hai bloqueo de conta (CWE-307).
Técnica: Script Python con ciclo GET→POST: obtén un token fresco antes de cada intento de contrasinal, mantendo a mesma sesión PHP.
def attack_step(session, password):
# 1. GET fresco para token actual da sesión
token = get_token(session) # extrae user_token do HTML
# 2. POST con ese token válido
return try_password(session, password, token)
Resultado: Contrasinal password atopado en 9 s (4.º intento × ~2.3 s/intento).
CWEs relevantes:
- CWE-307 — Sin bloqueo de conta
- CWE-352 — Token CSRF ligado á sesión, non á transacción
- CWE-613 — Insufficient Session Expiration
CVEs ilustrativos:
| CVE | Produto | Descrición |
|---|---|---|
| CVE-2019-3396 | Atlassian Confluence | CSRF en formularios de autenticación sen token por-petición |
| CVE-2020-17519 | Apache Flink | Token de sesión reutilizable en operacións sensibles |
| CVE-2022-0540 | Atlassian Jira | Bypass de CSRF en determinados endpoints de auth |
Puntuación CVSS v3.1:
| Métrica | Valor | Razón |
|---|---|---|
| Attack Complexity | High (H) | Require xestión de estado (token CSRF fresco por petición) |
| Outros | igual Low/Medium | — |
Base Score: 7.4 — ALTO
2.4 Nivel Impossible
Non explotable. As defensas en capas impiden calquera ataque automatizado:
- Token CSRF por transacción →
generateSessionToken()tras cada POST invalida o token anterior - Bloqueo tras 3 fallos → persistido en BD; 15 min de espera
- Bloqueo activo con clave correcta → nin o contrasinal real funciona mentres a conta está bloqueada
- Retardo aleatorio →
sleep(rand(2,4))impide análise de timing - Mensaxe de erro idéntica → "Username and/or password incorrect" tanto para fallo como para bloqueo (anti-enumeración)
- PDO con parámetros ligados → inmune a inxección SQL
Puntuación CVSS v3.1:
Base Score: 0.0 — NINGÚN
3. Comparativa de Puntuacións CVSS v3.1
Nivel CVSS Vector Puntuación Severidade
─────────────────────────────────────────────────────────────────────────────────────
Low AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N 9.1 CRÍTICO
Medium AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N 9.1 CRÍTICO
High AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N 7.4 ALTO
Impossible AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:N 0.0 NINGÚN
9 │ ██████████ ██████████
8 │
7 │ ████████
6 │
5 │
4 │
3 │
2 │
1 │
0 │ ──
└────────────────────────────────────────
Low Medium High Impossible
4. Top 5 Recomendacións de Remediación (por impacto)
R1 — Implementar bloqueo de conta con backoff exponencial ⚡ CRÍTICO
Impacto: Elimina a viabilidade práctica de calquera ataque de forza bruta.
// PHP — exemplo de implementación
$max_intentos = 5;
$bloqueo_base = 30; // segundos
$multiplicador = 2; // backoff exponencial
$intentos = $cache->get("bf:{$ip}:{$usuario}") ?? 0;
if ($intentos >= $max_intentos) {
$espera = $bloqueo_base * pow($multiplicador, $intentos - $max_intentos);
http_response_code(429);
header("Retry-After: {$espera}");
exit("Too Many Requests");
}
Complementar con:
- Bloqueo por IP E por usuario (evitar lockout selectivo)
- Notificación ao usuario por email cando se bloquea a súa conta
- CAPTCHA progresivo (activar tras 2–3 fallos)
R2 — Token CSRF por transacción (non por sesión) ⚡ CRÍTICO
Impacto: Invalida todos os ataques automatizados que non xestionen estado HTTP completo.
// Xerar token novo ANTES de servir o formulario
function generateTransactionToken(): string {
$token = bin2hex(random_bytes(32));
$_SESSION['csrf_token'] = $token;
$_SESSION['csrf_token_ts'] = time(); // TTL de 5 min
return $token;
}
// Validar: token correcto + non caducado + consumir (one-time use)
function validateTransactionToken(string $token): bool {
$valid = hash_equals($_SESSION['csrf_token'] ?? '', $token)
&& (time() - ($_SESSION['csrf_token_ts'] ?? 0)) < 300;
unset($_SESSION['csrf_token'], $_SESSION['csrf_token_ts']); // one-time
return $valid;
}
R3 — Cabeceiras HTTP de seguridade en todas as respostas 🔴 ALTO
Impacto: Mitiga clickjacking, XSS reflectido, sniffing de MIME e fixación de sesión.
Estado actual do servidor (confirmado por laboratorio):
# PRESENTES (ben configuradas)
Set-Cookie: PHPSESSID=...; HttpOnly; SameSite=Strict ✓
Cache-Control: no-cache, must-revalidate ✓
# AUSENTES — deben engadirse en Apache /etc/apache2/conf-enabled/security.conf:
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: geolocation=(), microphone=(), camera=()
Configuración Apache recomendada:
# /etc/apache2/conf-enabled/security-headers.conf
<IfModule mod_headers.c>
Header always set X-Frame-Options "DENY"
Header always set X-Content-Type-Options "nosniff"
Header always set X-XSS-Protection "1; mode=block"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Permissions-Policy "geolocation=(), camera=(), microphone=()"
Header always set Content-Security-Policy \
"default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; \
img-src 'self' data:; frame-ancestors 'none'; form-action 'self'"
# Ocultar versión do servidor
ServerTokens Prod
ServerSignature Off
</IfModule>
Set-Cookie óptimo para formulario de login:
⚠️ Actualmente falta
Secure— debe engadirse cando se despregue con HTTPS.
R4 — Consultas parametrizadas con PDO en todos os niveis 🔴 ALTO
Impacto: Elimina SQL Injection en paralelo co brute force (niveles Low–High usan concatenación ou mysqli_real_escape_string).
// ✗ INSEGURO (Low/Medium): string concatenation
$query = "SELECT * FROM users WHERE user='$user' AND password='$pass'";
// ✓ SEGURO (Impossible): PDO preparado
$stmt = $db->prepare('SELECT * FROM users WHERE user = :user AND password = :pass LIMIT 1');
$stmt->bindParam(':user', $user, PDO::PARAM_STR);
$stmt->bindParam(':pass', $hash, PDO::PARAM_STR);
$stmt->execute();
R5 — Retardo aleatorio + log de eventos de autenticación 🟡 MEDIO
Impacto: Dificulta ataques de timing e permite detección e resposta (SIEM/alertas).
// Retardo aleatorio en fallo (igual que Impossible)
sleep(random_int(2, 5));
// Log estruturado para SIEM
error_log(json_encode([
'event' => 'auth_failure',
'user' => $usuario,
'ip' => $_SERVER['REMOTE_ADDR'],
'ua' => $_SERVER['HTTP_USER_AGENT'],
'ts' => date('c'),
'attempt' => $intentos_fallidos,
]));
Complementar con fail2ban:
# /etc/fail2ban/filter.d/dvwa-brute.conf
[Definition]
failregex = ^.*"event":"auth_failure".*"ip":"<HOST>".*$
ignoreregex =
# /etc/fail2ban/jail.d/dvwa.conf
[dvwa-brute]
enabled = true
filter = dvwa-brute
logpath = /var/log/apache2/error.log
maxretry = 5
bantime = 3600
findtime = 300
5. Exemplo Completo de Cabeceiras HTTP Seguras
5.1 Cabeceiras actuais do servidor (confirmadas)
HTTP/1.1 200 OK
Server: Apache/2.4.52 (Ubuntu) ← ⚠️ Revela versión e SO
Set-Cookie: security=impossible; path=/; HttpOnly ← falta Secure + SameSite
Set-Cookie: PHPSESSID=...; HttpOnly; SameSite=Strict ← ben, falta Secure
Cache-Control: no-cache, must-revalidate
Content-Type: text/html;charset=utf-8
5.2 Cabeceiras recomendadas (estado obxectivo)
HTTP/1.1 200 OK
Server: Apache ← sen versión nin SO
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
Content-Security-Policy: default-src 'self'; script-src 'self'; \
style-src 'self' 'unsafe-inline'; img-src 'self' data:; \
form-action 'self'; frame-ancestors 'none'
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: geolocation=(), camera=(), microphone=()
Cache-Control: no-store, no-cache, must-revalidate, private
Pragma: no-cache
Set-Cookie: PHPSESSID=<opaco>; Path=/dvwa/; HttpOnly; Secure; \
SameSite=Strict; Max-Age=1800
Set-Cookie: security=high; Path=/dvwa/; HttpOnly; Secure; SameSite=Strict
Content-Type: text/html; charset=UTF-8
5.3 Mapeo cabeceira → ataque que mitiga
| Cabeceira | Ataque mitigado |
|---|---|
X-Frame-Options: DENY |
Clickjacking para roubo de credenciais |
CSP: form-action 'self' |
Envío de formulario a servidor do atacante |
CSP: frame-ancestors 'none' |
UI redressing / clickjacking |
X-Content-Type-Options: nosniff |
MIME sniffing + XSS via upload |
SameSite=Strict |
CSRF cross-site |
HttpOnly |
Roubo de cookie via XSS |
Secure |
Intercepción de cookie en HTTP |
Strict-Transport-Security |
Downgrade a HTTP / SSL stripping |
Referrer-Policy |
Fuga de token CSRF en cabeceira Referer |
Cache-Control: no-store |
Caché de credenciais en proxy/navegador |
6. Referencias
- OWASP Top 10 2021 — A07: Identification and Authentication Failures
- CWE-307: https://cwe.mitre.org/data/definitions/307.html
- CWE-352: https://cwe.mitre.org/data/definitions/352.html
- CWE-208: https://cwe.mitre.org/data/definitions/208.html
- CVSS v3.1 Specification: https://www.first.org/cvss/v3.1/specification-document
- OWASP Testing Guide v4.2 — OTG-AUTHN-003 (Testing for Weak Lock Out Mechanism)
- OWASP CSRF Prevention Cheat Sheet
- Mozilla Observatory: https://observatory.mozilla.org