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