PHP Type Juggling
El Type Juggling es un abuso de las comparaciones flexibles de PHP. El operador de igualdad laxa == intenta convertir los operandos a un tipo común antes de compararlos, en vez de exigir que sean idénticos como hace el estricto ===. Esa conversión implícita produce igualdades sorprendentes que rompen comprobaciones de seguridad: tokens, contraseñas o firmas que se validan con == pueden saltarse enviando un valor que PHP considere "igual" tras la conversión.
El caso más famoso son los magic hashes: si un hash empieza por 0e seguido solo de dígitos, PHP lo interpreta como notación científica (0 * 10^n = 0), así que dos hashes distintos con esa forma se comparan como iguales. Una contraseña cuyo md5 sea 0e... iguala a cualquier otra 0e...:
"0e123456" == "0e999999" // true: ambas valen 0
md5("240610708") == md5("QNKCDZO") // true: dos magic hashes 0e...Entradas conocidas cuyo hash tiene forma 0e[0-9]+ (para pegar directamente en el campo):
md5: 240610708 QNKCDZO aabg7XSs aabC9RqS
sha1: aaroZmOk aaK1STfY aaO8zKZF
# tambien vale un valor cuyo propio texto sea "0e...": muchas apps comparan token==hashEl otro clásico llega por arrays en la entrada. Si el código compara con == o pasa un array a funciones como strcmp, se fuerza un resultado favorable: strcmp(array, string) devuelve NULL en PHP antiguo, y NULL == 0 es true, con lo que la comprobación pasa. En una API JSON basta con enviar el tipo inesperado:
// si el backend hace if (strcmp($_POST['pass'], $real) == 0)
pass[]=x // strcmp(array, str) -> NULL -> NULL==0 -> bypass
// o en JSON, forzar un booleano/entero donde se espera string
{"password": true}Requisitos. El backend debe (1) estar en PHP y (2) comparar datos sensibles con == (o funciones laxas) en vez de ===/hash_equals, y aceptar que la entrada llegue con un tipo controlable por el atacante (array, booleano, cadena 0e). Con comparación estricta y validación de tipo, el juggling no tiene por dónde entrar.
Cómo detectarlo. En el log de la aplicación, la firma son parámetros con tipo anómalo para el campo: sufijos [] que convierten un valor en array (pass[]=), o cadenas con forma 0e[0-9]+ en campos de contraseña o token. Un pico de intentos de login con esos patrones sobre el mismo endpoint delata el ataque.
Defensa. Comparar siempre con === (o con hash_equals() para secretos y firmas, que además es de tiempo constante), validar y forzar el tipo de cada entrada (is_string, casteo explícito) antes de compararla, y no confiar en la conversión implícita. Se solapa con el bypass de autenticación cuando el objetivo es saltarse un login.