Cross-site Scripting in PHP's Transparent Session ID Support ------------------------------------------------------------ SHH #5, 2003-05-11 Description ----------- PHP may automatically embed session IDs as part of URLs in a web page. The automatic embedding is called "transparent SID support". It is possible to dictate the value of the session ID using the PHPSESSID URL parameter. PHP does little to validate the dictated ID. Combined with lack of URL encoding and HTML encoding of automatically embedded session IDs, this makes PHP open to Cross-site Scripting attacks. Details ------- For a vulnerable web site, the following URL may lead to the generation of a web page containing the script included at the end: http://www.somesite.example/index.php?PHPSESSID="> The page generated by PHP will include anchor tags that look like this: Note that the attacker closes the anchor tag prematurely before including the script tag. An attacker may trick a victim into visiting such a URL, and be able to e.g. steal the victim's session ID, redirect login forms to gain access to passwords, modify text on the page, etc. Please note that Cross-site Scripting may be possible even if PHP is automatically adding backslashes to selected characters (magic_quotes_gpc). An attacker may for instance use the JavaScript construct String.fromCharCode(65,66,67) as a substitute for the string constant "ABC" in order to avoid the double quotes that would be escaped by PHP. The initial double quote used to close the anchor tag will work regardless of magic_quotes_gpc, as backslash is not an escape character in HTML. As a side note: PHP may or may not accept the incoming script as a valid session ID, depending on what session.save_handler is used. Whether a session is created or not, PHP will output the invalid ID as part of the generated web page. Solution -------- The preferred solution is to disable the use of transparent SID support, as secrets--such as session IDs--should not be included in URLs. Transparent SID support is disabled by including the following line in php.ini: session.use_trans_sid=0 If transparent SID support is needed, one should upgrade to a PHP version that is not affected by the bug (see below). If an upgrade is not possible, the problem can be fixed by adding URL encoding of the output session IDs, which is what the PHP developers did in the CVS tree. Open the PHP source file ext/session/session.c and find a line looking like this (line break inserted for readability): php_url_scanner_add_var(PS(session_name), strlen(PS(session_name)), PS(id), strlen(PS(id)), 0 TSRMLS_CC); Change it to look like this (replace "0" with "1"): php_url_scanner_add_var(PS(session_name), strlen(PS(session_name)), PS(id), strlen(PS(id)), 1 TSRMLS_CC); Recompile and install PHP. Depending on how it uses PHP, you may have to restart the web server. Vendor Notification ------------------- The PHP developers were notified 2003-02-19. They made a fix available in CVS at 2003-02-20 (added URL encoding of the session ID). The first public release (candidate) to contain the fix was 4.3.2RC1, released 2003-03-13. Affected versions ----------------- Versions 4.3.0 and 4.3.1 with php.ini containing session.use_trans_sid=1 Versions 4.2.0 to 4.2.3 without php.ini, or with php.ini containing session.use_trans_sid=1 (php.ini-dist and php.ini-recommended from the PHP source distribution had use_trans_sid=1 from 4.2.0 to 4.2.2, and use_trans_sid=0 for 4.2.3 and later versions.) Versions prior to 4.2.0 compiled with --enable-trans-sid and with session.use_trans_sid=1 Fixed versions -------------- Version 4.3.2RC1 and later. Credits ------- Thanks to Tommy Gildseth for helping me double check that the problem did in fact exist. ---------------------------- Reported by Sverre H. Huseby