Desarrollo de software
Ataques de tiempo en PHP: Un ejemplo práctico - por qué `hash_equals()` es importante
¿Quieres un ejemplo realista de un ataque de temporización a tokens API en Wordpress/Laravel/PHP? Lo cubrimos aquí, incluyendo consejos y medidas de mejores prácticas contra los ataques de temporización.
Muchos desarrolladores confían en la simple comparación mediante === o == cuando comprueban claves API, tokens u otras cadenas secretas. A primera vista, esto parece razonable - pero hay una trampa: las diferencias de tiempo en la comparación pueden ser explotadas por los atacantes.
Este artículo describe un ejemplo realista de cómo funciona conceptualmente un ataque de sincronización.
El escenario real (ejemplo simplificado)
Imagina que un microservicio interno acepta peticiones con un token de parámetro de consulta y lo compara con un token de API de GitHub almacenado en el entorno.
Código inseguro (simplificado):
$expected = getenv('GITHUB_API_TOKEN');' $provided = $_GET['token'] ?? '';if ($provided === $expected) { } PHP
Explicaré por qué esto es problemático en la siguiente sección.
¿Cómo funciona un ataque de sincronización?
Si la implementación de la comparación de tokens compara carácter por carácter y aborta inmediatamente al primer error, entonces una petición con el primer carácter correcto tardará un poco más de media.
Por tanto, un primer carácter correcto conlleva de media un tiempo de procesamiento ligeramente superior al de un primer carácter incorrecto. Lo mismo ocurre con el segundo carácter y así sucesivamente.
Un atacante se aprovecha de esto probando todos los caracteres posibles para cada posición, midiendo los tiempos de respuesta muy a menudo y analizándolos estadísticamente. El carácter con el mayor tiempo medio/proporcionalmente mayor es probablemente el correcto. De este modo, el token se reconstruye paso a paso.
Por qué hash_equals() es la elección correcta
PHP proporciona una función de comparación de cadenas en tiempo constante con hash_equals(). Asegura que el tiempo de ejecución de la comparación no depende de prefijos comunes - siempre y cuando ambas cadenas tengan la misma longitud.
Alternativa segura (para Laravel, PHP, Wordpress):
$expected = getenv('GITHUB_API_TOKEN'); $provided = $_GET['token'] ?? '';if (hash_equals($expected, $provided)) { } PHP
Nota: hash_equals() sólo es "independiente del tiempo" si las longitudes son iguales. Es una buena práctica diseñar tokens para que la longitud sea constante (por ejemplo, HMACs, UUIDs de longitud fija o cadenas Base64 aleatorias de longitud fija).
¿Lo sabías? Sólo UUID-V4 se genera de forma completamente aleatoria y, por lo tanto, se utiliza a menudo para los tokens de seguridad. Al no contener información relacionada con la hora o el dispositivo, ofrece un alto nivel de imprevisibilidad y, por lo tanto, protege contra ataques basados en patrones o predicciones. Esta es precisamente la razón por la que UUID-V4 es la opción preferida cuando se trata de identificadores seguros y difíciles de adivinar.
Medidas de defensa adicionales - algo más que hash_equals()
- Longitud constante del token
Utilice tokens con una longitud fija, por ejemplo UUID-V4. Si un atacante adivina la longitud, esto es menos útil siempre que los propios caracteres sean seguros.
- Limitación de velocidad
Limite las solicitudes por IP o por cuenta. Los ataques de sincronización requieren muchas mediciones; la limitación de la tasa aumenta significativamente el esfuerzo y los costes para el atacante.
- Registro y supervisión
Reconozca patrones inusuales (muchos intentos de token, variación sistemática de ciertos parámetros) y reaccione automáticamente.
- Sal / HMAC / Firmas
Utilice tokens firmados (HMAC con clave secreta) o tokens OAuth en lugar de comparar abiertamente claves estáticas sin procesar.
- TLS/HTTPS
La encriptación protege los canales de comunicación - aunque no previene ataques de tiempo a los internos del servidor, es un requisito básico.
- Rotación de tokens
La corta vida de los tokens reduce el beneficio de un token comprometido.
Conclusión
Los ataques de sincronización no son un problema puramente teórico: se han investigado en la práctica y pueden tener graves consecuencias, especialmente para puntos finales de acceso público. La buena noticia: para los desarrolladores de PHP/Laravel/Wordpress, la primera contramedida es muy sencilla:
- Sustituir las comparaciones directas de cadenas sensibles por
hash_equals().
- Garantizar longitudes de token constantes, limitación de velocidad, registro y gestión segura de tokens.