php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #71974 Regression PHP5->7: trans sid will always be send,even if cookies are available
Submitted: 2016-04-06 10:28 UTC Modified: 2016-04-06 21:06 UTC
From: phpbug at wisl dot de Assigned: yohgaki (profile)
Status: Closed Package: Session related
PHP Version: 7.0.5 OS: All
Private report: No CVE-ID: None
 [2016-04-06 10:28 UTC] phpbug at wisl dot de
Description:
------------
I am using session.use_trans_sid=1 as a transparent fallback for users who have cookies disabled. By setting both use_trans_sid and use_cookies until PHP7 the cookie users would silently be upgraded to using cookies, while users without cookies could still use the session related function due to PHPSESSID that was written automatically into the html.

Cause seems to be this commit: https://github.com/php/php-src/commit/f248df900300c5b2201d4cf634d58d413399e2eb
"Cleanup trans sid code. Behavior is unchanged."

But the behavior is changed, because the new macro APPLY_TRANS_SID only looks for the ini settings use_trans_sid and use_only_cookies, but the code wrt. cookies like lines 540+541 was removed.


Test script:
---------------
<?php
ini_set("session.use_cookies","1");
ini_set("session.use_only_cookies","0");
ini_set("session.use_trans_sid","1");
session_start();
?>
<a href="bugtest.php">Follow Me</a>

Expected result:
----------------
On first call to the supplied test script (wenn saved as bugtest.php) the use_trans_sid feature will insert an additional parameter PHPSESSID into the <a href>, but because of use_cookies the script will also send an Set-Cookie-Header.

After clicking the link, the same page will reopen again. But if cookies are allowed in the browser, the <a href> will now no longer contain a PHPSESSID parameter.

After clicking the link, the <a href> should only still contain a PHPSESSID parameter, if there was no cookie set.

This behavior works as expected as of PHP 5.6.18.

Actual result:
--------------
Under PHP7 (tested with 7.0.2, 7.0.3, 7.0.4, 7.0.5) it will:
 * no longer send a Set-Cookie Header, despite use_cookies=1 and use_only_cookies=0
 * will still rewrite the <a href> even if a cookies is already set

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-04-06 10:37 UTC] phpbug at wisl dot de
Additional information:
session_regenerate_id() for example is also broken.

bugtest3.php:
<?php
ini_set("session.use_only_cookies","0");
ini_set("session.use_trans_sid","1");
session_start();
for($i=0;$i<$_REQUEST["count"];$i++) session_regenerate_id();
?>
<a href="bugtest3.php?count=0">0</a></br>
<a href="bugtest3.php?count=1">1</a></br>
<a href="bugtest3.php?count=2">2</a></br>
<a href="bugtest3.php?count=3">3</a></br>

Using the URL bugtest3.php?count=3 under PHP 5.5 without having a cookie set results in hrefs like "bugtest3.php?count=3&PHPSESSID=f94bqpvtgksdiro232qolclut6". That is the correct and expected behavior.

Under PHP 7.0.4 the URLs look like this: "bugtest3.php?count=3&PHPSESSID=pgvvh2d39jpr4vnubnq2r2m800&PHPSESSID=umpctfqdp4q0av74l6mtflmqp3&PHPSESSID=a94c7n4694n2rrkqc2tlnlt1k3&PHPSESSID=ek4m6ikt29po9oh6045m1fpke2"

Each call to session_regenerate_id() seems to add another rewriter and an additional PHPSESSID parameter.


Where I think the behavior was changed in this commit: 

1.: https://github.com/php/php-src/commit/f248df900300c5b2201d4cf634d58d413399e2eb#diff-52eb9eb7f9d5d9125fbb1337a6541c06L538

By removing the condition " && PS(send_cookie)" before apply_trans_sid was set 1, now a trans sid will always be transmitted, even if a correct session cookie is available. That prevents using the trans sid as a simple fallback, because as of PHP7 if it is enabled at all, it will always send an PHPSESSID rendering any cookie support superfluous despite using cookies for session ids is the better way.

2.: https://github.com/php/php-src/commit/f248df900300c5b2201d4cf634d58d413399e2eb#diff-52eb9eb7f9d5d9125fbb1337a6541c06L1494

By no longer resetting the rewriter each call to php_session_reset_id() will add another PHPSESSID parameter instead of replacing the old one.
As session_regenerate_id() is calling into this function when switching to a new session id this means, that each call to session_regenerate_id() will add another PHPSESSID parameter.

For me this means, that if a visitor request the first page of my site an new session will be generated. This will add a first PHPSESSID parameter to all URLs. This new empty session will be regarded as unsafe, by my code, because its ID might have been supplied by an attacker. So my code calls session_regenerate_id() to generate a new, guaranteed to be safe, session id. This will now add a second PHPSESSID parameter, while leaving the original (possible tampered with ID) in all URLs. PHP version before PHP7 would correctly only insert the correct new session id.


Both of these changes are serious regression for my code, as it means I can no longer use the trans sid in PHP7 and now need to force all my visitors to enable cookies. As the commit promised "Behavior is unchanged", I see this as bugs and not changes that were needed to make PHP7 work, so please restore the trans sid behavior as it was in PHP5.
 [2016-04-06 21:06 UTC] yohgaki@php.net
-Status: Open +Status: Verified -Assigned To: +Assigned To: yohgaki
 [2016-04-07 01:27 UTC] yohgaki@php.net
Automatic comment on behalf of yohgaki
Revision: http://git.php.net/?p=php-src.git;a=commit;h=6467a4eb367fd1174fbed79f014772321f68e8bc
Log: Fixed Bug #71974 Trans sid will always be send, even if cookies are available
 [2016-04-07 01:27 UTC] yohgaki@php.net
-Status: Verified +Status: Closed
 [2016-07-20 11:32 UTC] davey@php.net
Automatic comment on behalf of yohgaki
Revision: http://git.php.net/?p=php-src.git;a=commit;h=6467a4eb367fd1174fbed79f014772321f68e8bc
Log: Fixed Bug #71974 Trans sid will always be send, even if cookies are available
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Tue Apr 23 22:01:31 2024 UTC