martes, 8 de enero de 2013

Creando Nuestro Propio WebScan para Joomla [0x01]

Saludos a todos, hoy compartiremos mucho mas coding, ahora queremos tratar un proyecto desde cero en este caso se trata de nuestro propio script para verificacion de vulnerabilidades en joomla, trataremos de ir al grano pero explicar como se puede llegar hacer estas tools, muchos tal vez pensaran que es algo dificil pero realmente es muy simple cuando se cuenta con creatividad y con un minimo conocimiento en programación, creo que lo importante es irse directo contra un muro para poder aprender asi que mi consejo es que lo intenten en otro lenguaje que manejen o si quieren en el mismo lenguaje utilizado, el escript lo realizaremos sobre Perl.

Manos a la Obra...



como indicabamos en el post anterior lo importante es tener todo bien organizado desde un principio para saber a donde vamos a llegar, diciendo esto, el algoritmo seria el siguiente:

1. Recibir por parametros la url y el directorio de instalacion
2. Verificar si los datos ingresados al hacer la consulta GET existe  o es valida generalmente la podemos validar con una respuesta http (200)
2. Despues de que este verificado la url podemos consultar la version de joomla desde archivos sin proteccion (administrator/manifests/files/joomla.xml)
3. Verificar la existencia de extenciones instaladas en el sistema gestor joomla, inicialmente utilizaremos los componentes que se instalan con el joomla, para la segunda parte de este post vamos a ir agregando mas componentes y mas funcionalidades a nuestro proyecto
4.mostrar la informacion por pantalla

estos serian los pasos o el algoritmo de nuestro script xD, ahora voy a dividir en funciones las operaciones que nos van a  indicar las versiones y las extenciones instaladas, y que paso a describir a continuacion.

config()
sub config{
  $admin = 'Administrator';
  $fileconf = 'administrator/manifests/files/joomla.xml';
  return ($admin,$fileconf);
}

esta función lo que hace es simplemente devolver en primer lugar el directorio del administrador que es donde se administra el CMS($admin) y en segundo lugar nos indica el archivo donde podemos sacar la version del joomla instalado($fileconf)

verificarHost()
sub verificarHost{
      my $url       = $_[0];
      my $pagina    = $url;
      my $response  = $ua->get($pagina);
      my $result    = 0;
      my $res       = $response->status_line;
      if($res=~m/200/g){ $result=200;}else{$result=0;}
  
      return($result);
}

esta funcion hace una consulta get a la url que le pasemos por parametro y si es una respuesta 200 lo guarda en $result y al final nos devuleve que resultado fue.

footprint()


sub footprint{
    my $host   = $_[0];                                
           
  
    if($host=~m/http:/g){ $host   = $_[0]; }else{ $host= 'http://'.$_[0];}
  
    my($dirAdmin,$fileConf)=config();
 
    $pagina = $host."/".$fileConf;
    my $busqueda = new HTTP::Request GET => $pagina;
    my $resultado = $ua->request($busqueda);
    my $result = $resultado->content();
    my $long = length($result);
  
    my @version = split("\n",$result);
    my @folders = split("\n",$result);
    my @files   = split("\n",$result);
  
    #Extract VERSION Joomla
    print "[+]Extrayendo Version del Joomla\n";
    sleep(1);
  
    foreach $linV(@version){
        if($linV=~m/(<version>)(.*)(<\/version>)/g){
            $vers = $2;
        }
    }
  
    #EXTRAER FOLDERS
    print "[+]Extrayendo Folders Instalados\n";
    sleep(1);
    my @data;
    foreach $lineF(@folders){
        if($lineF=~m/(<folder>)(.*)(<\/folder>)/g){
            $folde = $2;
            push(@data,$folde);
        }
    }
  
    print "[+]Extrayendo Files Instalados\n";
    sleep(1);
  
    foreach $linefil(@files){
        if($linefil=~m/(<file>)(.*)(<\/file>)/g){
            $fil = $2;
            push(@data,$fil);
        }
    }
    return($vers,@data);
}


esta funcion nos muestra todo el arhivo xml donde esta la version y otra información con la que se instalo el joomla, aca un ejemplo de la estructura de ese arhivo http://chocolateriatheo.com/administrator/manifests/files/joomla.xml

entonces de este aarchivo se extraera lo que este entre
<version></version>
<folder></folder>
<file></file>

esta es la informacion que sacaremos y en el codigo la podemos observar en las expresiones regulares de igual manera aca explico linea por linea


  • if($host=~m/http:/g){ $host   = $_[0]; }else{ $host= 'http://'.$_[0];}

esta linea indica o pregunta que si el argumento que recibe la funcion no posee un http que se lo anteponga ejemplo, digamos que la funcion recibe como parametro www.testeame.com, como vemos no posee el http entonces lo que hace este conficional es anteponerle el http quedando el parametro
http://www.testeame.com, simple no? ¬¬ espero que si ...


  •  my($dirAdmin,$fileConf)=config();
en esta linea se declaran dos variable $dirAdmin,$fileConf y estas variables se hacen igual lo que devuelva la funcion config() que ya explicamos anteriormente y mirando esta funcion devuleve estos datos en las mismas posiciones asi que $dirAdmin sera igual a Administrator y $fileConf contendra el archivo de configuracion del joomla

    -$pagina = $host."/".$fileConf;
    -my $busqueda = new HTTP::Request GET => $pagina;
    -my $resultado = $ua->request($busqueda);
    -my $result = $resultado->content();
    -my $long = length($result); 



en estas linea lo que realiza es una peticion get y luego el resultado de la peticion la guarda en $result posteriormente determinamos la logitud de toda la peticion que seria todo el html correspondiente a la web

    -my @version = split("\n",$result);
    -my @folders = split("\n",$result);
    -my @files   = split("\n",$result);


declaramos 3 arrays en dodne guardaremos la version los folders y los files
recuerdan???

<version></version>
<folder></folder>
<file></file>
¬¬
ok.....


-    #Extract VERSION Joomla

-    print "[+]Extrayendo Version del Joomla\n";
-    sleep(1);


creo que esto se entiende aunque no falta algun lammer perdido preguntandose que es un lammer y de que diablos habla este tio xD


-   foreach $linV(@version){
-        if($linV=~m/(<version>)(.*)(<\/version>)/g){
-            $vers = $2;
-        }
-    } 


aca se recorre el array @version y indicamos por medio de la expresion regular que extraiga la informacion que se encuentra entre <version>info</version> y lo guardo en una variable.

#EXTRAER FOLDERS
    print "[+]Extrayendo Folders Instalados\n";
    sleep(1);
    my @data;
    foreach $lineF(@folders){
        if($lineF=~m/(<folder>)(.*)(<\/folder>)/g){
            $folde = $2;
            push(@data,$folde);
        }
    }


aca estamos haciendo lo mismo que con la version pero ahora con folder
   
    print "[+]Extrayendo Files Instalados\n";
    sleep(1);
   
    foreach $linefil(@files){
        if($linefil=~m/(<file>)(.*)(<\/file>)/g){
            $fil = $2;
            push(@data,$fil);
        }
    }


aca lo mismo que con folder y version, todo queda dentro de un array que se llama @data

    return($vers,@data);



Continuando con las funciones ahora otra funcion que es la que me valida que exista una determinada extencion en el host remoto

verifComp()

sub verifComp{
    my $url = $_[0];
    my $pagina = $url;
    my $response  = $ua->get($pagina);
    my $result    = 0;
    my $res       = $response->status_line;
    if($res=~m/200/g){ $result=200;}else{$result=0;}
   
    return($result);
}

es igual a la funcion que verifica la pagina inicial inclusive se puede reutilizar dicha funcion pero para que lo puedan ver mejor la separe, entonces esta recibe la url como parametro hace la peticion get y si es ok la respues lo guarda y luego lo retorna de donde fue solicitada la funcion

creo que son suficientes por este post xD, ahora hay que llamarlas para esto se puede crear otra funcion digamos main() o simplemente lo ponemos al inicio del code


if(int(@ARGV)<2){
    print help();
}else{
    my $host = $ARGV[0];
    my $dir  = $ARGV[1];
   
    if($host=~m/http:/g){ $host   = $ARGV[0]; }else{ $host= 'http://'.$ARGV[0];}
    if($dir=~m/\//g){ $dir   = $ARGV[1]; }else{ $dir= '/'.$ARGV[1];}
   
    my $pg   = $host.$dir."/";
    my $r    = verificarHost($pg);
   
   
 if($r eq 200){  
    system('clear');
    header();
    print "\n[+]Consultando Informacion\n";
    sleep(1);

    my ($ver , @folde) = footprint($pg);
   
    $sep ="+"x80;
    print "[+]Consultado Complementos Instalados\n";
    sleep(1);
    my @compInstalados;
    foreach $lcom(@componentes){
        my $pcomplemento = $pg.$dirComp.$lcom."/index.html";
        my $vCom         = verifComp($pcomplemento);
       
        if($vCom=~m/200/g){ push(@compInstalados,$lcom);}
    }
   
   
    print "[+]Recogiendo Informacion Para Imprimir\n";
    print "\n".$sep."\n";
    print " [*]Host Remoto        : $pg                       \n";
    print " [*]Version Joomla     : ".$ver."\n";
    print " [*]Files Instalados   : \n";
    my $c=0;
    foreach $linFil(@folde){
       
        if($c<=4){
           print " ".$linFil." , ";
           $c=$c+1;
        }else{
            print " ".$linFil."\n";
            $c=0;   
        }
    }
   
    #recorrido de componentes instalados
    print " \n\n [*]Extenciones Instaladas   : \n";
    $cc=0;
    foreach $lcominstal(@compInstalados){
        if($cc<=4){
           print " ".$lcominstal." , ";
           $cc=$cc+1;
        }else{
            print " ".$lcominstal."\n";
            $cc=0;   
        }
    }
    #my $inf = join(' , ',@folde);
    #print $inf."\n";
    print "\n\n".$sep."\n\n";
 }
}


Enredado?? nha no creo, estas lineas toman los parametros iniciales que seria el host remoto a testear y el directorio del joomla dentro de ese host luego empieza a llamar a las funciones ya creadas y al terminar de llamar a las funciones simplemente muestra los datos extraidos.

creo que es el fin de este post, en la segunda parte vamos a empezar a agregar funciones para que verifique posibles extenciones vulnerables a travez de bases de datos conocidas para esto.


 aca el codigo completo  de lo realizado hasta ahor, es totalmente funcional :D espero que se haya entendido el code y comenten sobre el post o nos escriban a insultarnos o lo que sea, asi mejoraremos con todo lo que nos puedan decir

Nota: este codigo se puede hacer de muchas formas y optimizarlo mucho mas pero hasta ahora es funcional para nuestro proposito :D

 Codigo Completo



#!/usr/bin/perl

#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++#
# Script para Revicion de Versiones, Modulos Instalados y Vulnerabilidades de Joomla
# TrackMaze 2013
# http://trackmaze.blogspot.com
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++#

use LWP::UserAgent;
use HTTP::Request;

my @componentes = (
                   "com_banners","com_contact",
                   "com_content","com_finder",
                   "com_mailto","com_media",
                   "com_newsfeeds","com_search",
                   "com_users",
                   "com_weblinks",
                   "com_wrapper"
                   );
my $dirComp     = "components/";


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";

sub help{
    system('clear');
    header();
    print "+++++++++++++++++++++++++++++++++++++++++++\n";
    print " Uso: perl $0 joomla.com /joomla           \n";
    print "+++++++++++++++++++++++++++++++++++++++++++\n\n";
}


sub verificarHost{
    my $url       = $_[0];
    my $pagina    = $url;
    my $response  = $ua->get($pagina);
    my $result    = 0;
    my $res       = $response->status_line;
    if($res=~m/200/g){ $result=200;}else{$result=0;}
   
    return($result);
}

if(int(@ARGV)<2){
    print help();
}else{
    my $host = $ARGV[0];
    my $dir  = $ARGV[1];
   
    if($host=~m/http:/g){ $host   = $ARGV[0]; }else{ $host= 'http://'.$ARGV[0];}
    if($dir=~m/\//g){ $dir   = $ARGV[1]; }else{ $dir= '/'.$ARGV[1];}
   
    my $pg   = $host.$dir."/";
    my $r    = verificarHost($pg);
   
   
 if($r eq 200){  
    system('clear');
    header();
    print "\n[+]Consultando Informacion\n";
    sleep(1);

    my ($ver , @folde) = footprint($pg);
   
    $sep ="+"x80;
    print "[+]Consultado Complementos Instalados\n";
    sleep(1);
    my @compInstalados;
    foreach $lcom(@componentes){
        my $pcomplemento = $pg.$dirComp.$lcom."/index.html";
        my $vCom         = verifComp($pcomplemento);
       
        if($vCom=~m/200/g){ push(@compInstalados,$lcom);}
    }
   
   
    print "[+]Recogiendo Informacion Para Imprimir\n";
    print "\n".$sep."\n";
    print " [*]Host Remoto        : $pg                       \n";
    print " [*]Version Joomla     : ".$ver."\n";
    print " [*]Files Instalados   : \n";
    my $c=0;
    foreach $linFil(@folde){
       
        if($c<=4){
           print " ".$linFil." , ";
           $c=$c+1;
        }else{
            print " ".$linFil."\n";
            $c=0;   
        }
    }
   
    #recorrido de componentes instalados
    print " \n\n [*]Extenciones Instaladas   : \n";
    $cc=0;
    foreach $lcominstal(@compInstalados){
        if($cc<=4){
           print " ".$lcominstal." , ";
           $cc=$cc+1;
        }else{
            print " ".$lcominstal."\n";
            $cc=0;   
        }
    }
    #my $inf = join(' , ',@folde);
    #print $inf."\n";
    print "\n\n".$sep."\n\n";
 }
}

sub footprint{
    my $host   = $_[0];                                 
            
   
    if($host=~m/http:/g){ $host   = $_[0]; }else{ $host= 'http://'.$_[0];}
   
    my($dirAdmin,$fileConf)=config();
  
    $pagina = $host."/".$fileConf;
    my $busqueda = new HTTP::Request GET => $pagina;
    my $resultado = $ua->request($busqueda);
    my $result = $resultado->content();
    my $long = length($result);
   
    my @version = split("\n",$result);
    my @folders = split("\n",$result);
    my @files   = split("\n",$result);
   
    #Extract VERSION Joomla
    print "[+]Extrayendo Version del Joomla\n";
    sleep(1);
   
    foreach $linV(@version){
        if($linV=~m/(<version>)(.*)(<\/version>)/g){
            $vers = $2;
        }
    }
   
    #EXTRAER FOLDERS
    print "[+]Extrayendo Folders Instalados\n";
    sleep(1);
    my @data;
    foreach $lineF(@folders){
        if($lineF=~m/(<folder>)(.*)(<\/folder>)/g){
            $folde = $2;
            push(@data,$folde);
        }
    }
   
    print "[+]Extrayendo Files Instalados\n";
    sleep(1);
   
    foreach $linefil(@files){
        if($linefil=~m/(<file>)(.*)(<\/file>)/g){
            $fil = $2;
            push(@data,$fil);
        }
    }
    return($vers,@data);
}

sub config{
   $admin    = 'Administrator';
   $fileconf = 'administrator/manifests/files/joomla.xml';
   return ($admin,$fileconf);
}



sub verifComp{
    my $url = $_[0];
    my $pagina = $url;
    my $response  = $ua->get($pagina);
    my $result    = 0;
    my $res       = $response->status_line;
    if($res=~m/200/g){ $result=200;}else{$result=0;}
   
    return($result);
}

sub header{
    print"    __                       _     _____              _     \n";
    print"  |_  |                     | |   |_   _|            | |    \n";
    print"    | | ___   ___  _ __ ___ | | __ _| |_ __ __ _  ___| | __ \n";
    print"    | |/ _ \ / _ \| '_ ` _ \| |/ _` | | '__/ _` |/ __| |/ / \n";
    print"/\__/ / (_) | (_) | | | | | | | (_| | | | | (_| | (__|   <  \n";
    print"\____/ \___/ \___/|_| |_| |_|_|\__,_\_/_|  \__,_|\___|_|\_\ \n";
    print "      TrackMaze-2013 [http://trackmaze.blogspot.com/]      \n\n";                                                          
}

pueden modificarlo y hacer lo que quieran pero ojo con los lammers y escript kiddies ¬¬ respeten los creditos :D

 POC


salud2 y f3l1z c0d1ng f0r H4cK

 





No hay comentarios:

Publicar un comentario