Natas Nivel 23 a 24
Nivel oficial: http://natas23.natas.labs.overthewire.org
Este nivel expone una vulnerabilidad clasica de PHP: la comparacion laxa entre una cadena y un numero entero. El formulario pide una contrasena aparentemente arbitraria, pero la logica de validacion en el servidor puede satisfacerse con un valor que nunca esperarias escribir.
Este laboratorio es legal y autorizado. Solo practica estas tecnicas en entornos de wargame como OverTheWire o sistemas sobre los que tengas permiso explicito.
Objetivo
Enviar un valor al parametro passwd que satisfaga simultaneamente dos condiciones: contener la subcadena iloveyou y compararse como mayor que 10 segun PHP, para que el servidor revele la contrasena de natas24.
Que aprendes
| Concepto / Comando | Para que sirve |
|---|---|
strstr($var, "cadena") | Comprueba si una cadena contiene una subcadena; devuelve false si no la encuentra |
Comparacion laxa $var > 10 con cadena | PHP convierte la cadena a numero usando los digitos iniciales antes de comparar |
| Type juggling en PHP | El motor de PHP coerciona tipos automaticamente en comparaciones con == y operadores relacionales (<, >) |
curl -d | Envia datos POST desde la linea de comandos |
curl -u usuario:pass | Adjunta credenciales HTTP Basic Auth a la peticion |
Concepto clave: type juggling en PHP
La categoria de vulnerabilidad es Type Confusion / Loose Comparison (relacionada con OWASP A03 - Injection y A04 - Insecure Design). No es una inyeccion de codigo, sino un abuso del sistema de tipos dinamico de PHP.
El patron: PHP, cuando compara una cadena con un entero usando operadores relacionales (>, <, ==), convierte la cadena a numero extrayendo los digitos del inicio. Por ejemplo:
"11iloveyou" > 10 // PHP extrae 11 → 11 > 10 → true
"iloveyou" > 10 // No hay digitos al inicio → 0 > 10 → false
"10iloveyou" > 10 // 10 > 10 → false (no es estrictamente mayor)El codigo vulnerable del nivel es aproximadamente:
if (strstr($passwd, "iloveyou") && $passwd > 10) {
// muestra la contrasena de natas24
}Ambas condiciones deben ser verdaderas al mismo tiempo. La clave es que PHP evalua $passwd > 10 coercionando la cadena a entero, mientras que strstr() trabaja sobre la cadena original sin modificarla. Un valor que empiece por un numero mayor que 10 y contenga iloveyou cumple las dos condiciones.
Paso a paso
1. Acceder al nivel con las credenciales de natas23
# Usuario: natas23
# Contrasena: <pass_natas23>
# URL: http://natas23.natas.labs.overthewire.org2. Analizar el formulario
La pagina presenta un campo de texto etiquetado como “Password” y un boton de envio. Inspecciona el HTML: hay un <form method="POST"> con un <input name="passwd">. No hay JavaScript de validacion en el cliente; toda la logica esta en el servidor.
3. Construir el payload
El valor que satisface ambas condiciones es cualquier cadena que:
- Empiece por un entero mayor que 10 (p. ej.
11,42,100) - Contenga la subcadena exacta
iloveyou
El payload minimo es:
11iloveyou
4. Enviar el payload via curl
curl -u natas23:<pass_natas23> \
-d "passwd=11iloveyou" \
http://natas23.natas.labs.overthewire.org/index.phpO directamente desde el navegador: escribe 11iloveyou en el campo de texto y pulsa el boton.
5. Leer la respuesta
El servidor devolvera la contrasena de natas24 en la pagina HTML. Buscala en la salida de curl o en el cuerpo de la respuesta en el navegador.
# Filtrar directamente la linea relevante
curl -s -u natas23:<pass_natas23> \
-d "passwd=11iloveyou" \
http://natas23.natas.labs.overthewire.org/index.php \
| grep -i "password\|natas24"Por que funciona
PHP es un lenguaje de tipado dinamico con reglas de coercion heredadas de sus primeras versiones. Cuando el operador > recibe operandos de tipos distintos (cadena vs entero), PHP no lanza un error: convierte la cadena a numero aplicando (int)"11iloveyou", que resulta en 11. La comparacion 11 > 10 es true.
strstr() opera sobre la representacion de cadena original, sin coercion, por lo que encuentra iloveyou dentro de 11iloveyou sin problema.
El resultado es que ninguna de las dos validaciones por separado protege contra el otro vector: strstr no impide numeros al principio, y la comparacion numerica no impide cadenas con texto adicional. La conjuncion de ambas, pensada para ser mas restrictiva, es en realidad trivialmente bypasseable.
Nota: desde PHP 8.0 el comportamiento de comparacion cadena-vs-entero cambio.
"11iloveyou" > 10en PHP 8 ya no hace coercion automatica en todos los contextos igual que en PHP 7. Si encontraras este patron en PHP 8, el resultado podria diferir. Los niveles de Natas corren sobre PHP 7.x, donde el type juggling clasico aplica.
Errores comunes
-
Enviar solo
iloveyousin prefijo numerico:strstr()devuelve true, pero"iloveyou" > 10evalua como0 > 10(false). La condicion global falla. -
Usar exactamente
10iloveyou:(int)"10iloveyou"es10, y10 > 10esfalse(mayor estricto, no mayor-o-igual). Usa un valor mayor que 10, como11iloveyou. -
Olvidar las credenciales HTTP Basic Auth: el subdominio completo requiere autenticacion. Sin
-u natas23:<pass>en curl (o sin rellenar el popup del navegador), obtendras un 401 antes de llegar al formulario. -
Buscar el payload en la URL (GET) en lugar de en el cuerpo (POST): el formulario usa
method="POST". Enviar?passwd=11iloveyouen la URL no tendra efecto porque el servidor lee$_POST["passwd"], no$_GET.
Pasar al siguiente nivel
La contrasena obtenida es la credencial para:
- URL:
http://natas24.natas.labs.overthewire.org - Usuario:
natas24 - Contrasena:
<pass_natas24>
El nivel 24 introduce otra variante de comparacion laxa en PHP, esta vez con strcmp() y su comportamiento frente a tipos no-cadena (como arrays). El patron de “romper una funcion de comparacion con un tipo inesperado” es el mismo concepto que este nivel, escalado un paso mas.