TOCTOU (time-of-check to time-of-use) es un problema en el que el estado de algo cambia entre el momento en que se comprueba y el momento en que se usa. Esta página explica cómo funciona y cómo prevenirlo (sin pasos de ataque).
Qué es TOCTOU
Los programas suelen funcionar como «comprobar y, si parece correcto, usar»: por ejemplo, «comprobar que este archivo puede escribirse y luego abrirlo y escribir en él». Pero existe un pequeño intervalo de tiempo entre la comprobación y el uso. Si otro programa o solicitud cambia el objetivo en ese intervalo, el resultado de la comprobación deja de ser válido.
El CWE-367 de MITRE describe esto como un producto que comprueba el estado de un recurso antes de usarlo, donde el estado puede cambiar entre la comprobación y el uso de forma que invalide la comprobación. CWE (Common Weakness Enumeration) es un catálogo compartido de las debilidades que están detrás de las vulnerabilidades. TOCTOU es un tipo de condición de carrera, en la que el resultado depende del orden temporal de procesos que se ejecutan al mismo tiempo.
Por qué ocurre
Según el CWE-367, las consecuencias pueden incluir el acceso a recursos que deberían estar fuera de alcance, recursos modificados de forma no deseada y registros que faltan. El intervalo puede ser breve, pero en sistemas que ejecutan muchas tareas a la vez se produce de forma repetida, no solo por casualidad.
Dónde aparece
| Lugar | Comprobación | Uso | Qué sale mal |
|---|---|---|---|
| Manejo de archivos | Comprobación de existencia o permisos | Abrir o escribir | El archivo se reemplaza después de la comprobación |
| Stock o saldo en una aplicación web | SELECT del número restante | UPDATE para reducirlo | Dos solicitudes concurrentes pasan ambas y superan el límite |
| Pagos y registros | ¿Sigue sin procesarse? | Ejecutar la acción | Un doble envío la ejecuta dos veces |
| Subida de archivos | Inspeccionar el contenido | Almacenar o publicar | El contenido cambia después de la inspección |
Para la inspección de subidas, consulta también vulnerabilidades de subida de archivos.
Defensa: no separes la comprobación del uso
Deja de comprobar antes de usar
El consejo más básico del CWE-367 es no realizar una comprobación antes del uso. Usa el recurso directamente y gestiona el error si falla. Así se elimina el propio intervalo.
Usa descriptores de archivo, no rutas
Abre primero el archivo y luego comprueba el estado y escribe a través del descriptor de archivo abierto. Buscar repetidamente el mismo nombre de ruta puede apuntar a un objetivo distinto cada vez. Las banderas como O_NOFOLLOW (no seguir enlaces simbólicos) y las llamadas como openat (abrir relativo a un directorio) también ayudan; lo que está disponible depende del sistema operativo.
Usa actualizaciones condicionales y transacciones en bases de datos
En lugar de «SELECT para comprobar y luego UPDATE», usa un solo UPDATE que incluya la condición (por ejemplo, decrementar solo cuando el número sea 1 o mayor). Cuando intervienen varias sentencias, usa una transacción con un nivel de aislamiento adecuado y bloqueos de fila.
Bloquea antes de comprobar
Si usas bloqueos, tómalos antes de la comprobación, como indica el CWE-367. Bloquear después no garantiza que el objetivo comprobado sea el que usas.
Evita la doble ejecución con claves de idempotencia
En pagos y registros, asigna a cada solicitud una clave única (una clave de idempotencia) y ejecuta la acción solo una vez por clave.
Cómo revisar tu propio código
Hazlo en código que construyas o gestiones tú.
- Busca lugares donde el código que comprueba y el código que usa son llamadas separadas (comprobación de existencia y luego apertura; SELECT y luego UPDATE)
- En cada caso, pregúntate si puedes eliminar la comprobación y convertir el paso en una sola operación
- Escribe una prueba que envíe la misma solicitud varias veces a la vez, y confirma que solo se aplica una
- No pruebes esto nunca contra el servicio de otra persona; usa tu propio entorno
Opinión de este sitio: pon la comprobación dentro de la misma operación que el uso
TOCTOU no es que «alguien olvidó la comprobación». La comprobación existe; simplemente está separada del uso. Añadir más código de comprobación no lo soluciona. La solución es poner la comprobación dentro de la misma operación atómica que el uso, en lugar de añadirla como un paso extra. Estudiarlo junto a IDOR ayuda en las revisiones: ambos son errores en los que «existe una comprobación, pero no cumple su función».
Fuentes (primarias)
- MITRE CWE-367: Time-of-check Time-of-use (TOCTOU) Race Condition — cwe.mitre.org (definición, consecuencias, mitigaciones)
- Las técnicas concretas (O_NOFOLLOW, openat, claves de idempotencia, transacciones) se describen como práctica general de implementación; su disponibilidad varía según el sistema operativo y la base de datos, así que consulta la documentación oficial de cada producto
Lectura siguiente
- Glosario: Qué es path traversal · Qué es IDOR · Qué es el OWASP Top 10
- Guía: Vulnerabilidades de subida de archivos
- Glosario: Qué es un CVE