1

Hello, I am writing this to warn you and because I haven't selected yet witch solution to choose , so your opinion is more than welcomed.

The problem: in some version of iPhone / iPad software the cookies aren't separated by “;” but by comma and doubled. The first fatal to that is
exception '_Exception_FatalError' with message 'session_start(): The session id is too long or contains illegal characters
The cookie that caused was “PHPSESSID=ea4fee7dcf4446d5cd61aabab13a0df2,PHPSESSID=ea4fee7dcf4446d5cd61aabab13a0df2”
PHP parses that like PHPSESSID is “ea4fee7dcf4446d5cd61aabab13a0df2,PHPSESSID=ea4fee7dcf4446d5cd61aabab13a0df” that of course is illegal.

The problem occurs in these devices + software (with * is all that have problem and (something|something) is if it has two values from the HTTP_USER_AGENT
Mozilla/5.0 ( (iPhone|iPad); CPU * like Mac OS X) AppleWebKit/* (KHTML, like Gecko) GSA/8.0.* * Safari/*

As you saw I catch catchable fatal errors , so the first option is that , in the core of the framework to check if there is a an Exception_FatalError that contains that message and if it is re parse HTTP_COOKIE header comma seperated and retry.

The second option is to do that before session_start , (notice that if you alternate $_SERVER[“HTTP_COOKIE”] PHP want rely on that for the session id) , that means an extra if ( HTTP_COOKIE contains comma) and ... that even if cookies with comma as value are valid , this cause an exception generated by fatal error.

The third choice is to act as I didn't understood that. I am sure that everyone that has a iPhone or iPad with such a problem already know that has problem accessing mobile web applications. In few years, there will not be as many.

As I wrote I posted this to warn you but also to read your opinions on how to resolve it (or not) .

2
Contributors
3
Replies
28
Views
2 Years
Discussion Span
Last Post by jkon
0

Hi!

According to the RFC 2109 this seems to be the expected behavior, section 4.2.1:

An origin server may include multiple Set-Cookie headers in a
response. Note that an intervening gateway could fold multiple such
headers into a single header.

And section 4.2.2:

Informally, the Set-Cookie response header comprises the token Set-
Cookie:, followed by a comma-separated list of one or more cookies.
Each cookie begins with a NAME=VALUE pair, followed by zero or more
semi-colon-separated attribute-value pairs. The syntax for
attribute-value pairs was shown earlier. The specific attributes and
the semantics of their values follows. The NAME=VALUE attribute-
value pair must come first in each cookie. The others, if present,
can occur in any order. If an attribute appears more than once in a
cookie, the behavior is undefined.

Link: http://www.w3.org/Protocols/rfc2109/rfc2109

Questions:

  • are you setting the session through session_id()?
  • what is returned by $_COOKIE["PHPSESSID"]?

I ask this because $_SERVER["HTTP_COOKIE"] returns the raw header of Set-Cookie, while $_COOKIE should handle the multiple cookies for you and it should reduce multiple cookies with the same name to only one:

Note that a cookie will replace a previous cookie by the same name in your browser unless the path or domain is different.

Source:

Not sure, but hope this helps.

0

Hello cereal , thank you for your response and especially the idea to see what has the $_COOKIE array in these cases. I added id to the report but all I can do is to wait for someone with a system that matches the HTTP_USER_AGENT to enter , since it doesn't happen in all iPhone/iPad ( I will reply when I will catch again such an error ) .

Meanwhile I found that there were a similar problem with some Nokia browsers in the past @see https://bugs.php.net/bug.php?id=32111 and https://bugs.php.net/bug.php?id=32827 . This seems really weird to me because if it happens also in some iPhone / iPad then somebody else should have been noticed it also.

I will came back to it when I will have more about what the $_COOKIE array contains in such cases and the session_id() result.

Edited by jkon

0

The session_id() is:
e.g.
b1d563872157c7b7d7d7c0891dd1867b,PHPSESSID=b1d563872157c7b7d7d7c0891dd1867b

and the $_COOKIE array is:
e.g.

array (
  'PHPSESSID' => 'b1d563872157c7b7d7d7c0891dd1867b,PHPSESSID=b1d563872157c7b7d7d7c0891dd1867b',
)

After doing a quick research , it turns out that the problem isn't newer iPhone/iPad browsers + system ( maybe there is an intervening gateway ) the problem lies in PHP. ( 5.5.24 in that server but I don't believe they have solved it yet ). The first thing that made me realize that , is acceptable as ; for separator was that from the RFC 2109 cereal shared.

Note: For backward compatibility, the separator in the Cookie header is semi-colon (;) everywhere. A server should also accept comma (,) as the separator between cookie-values for future compatibility.

But it isn't only that , comma is also a well known separator between different cookie sets in the cookies header of the request. So PHP should have handled that.
I believe that we are going to hear more about this issue. So a simple solution could be:

if( isset( $_SERVER["HTTP_COOKIE"] ) 
&& substr_count( $_SERVER["HTTP_COOKIE"], ",") > 0)
{
    $cookies = array();
    $parts = explode( ";"
        , str_replace( "," , ";"
        , $_SERVER["HTTP_COOKIE"] ) );

    if( count( $parts ) > 0 )
    {
        foreach( $parts as $part )
        {
            $pair = explode( "=" , $part );
            if( count( $pair ) == 2 )
            {
                $cookies[ trim( $pair[0] ) ] 
                    = trim( $pair[1] );
            }
        }
    }
    $_COOKIE = $cookies;
}

if(isset( $_COOKIE[session_name()] ) )
{
    session_id( $_COOKIE[session_name()] );
}

session_start();

What this doesn't cover:
1. If there is an = inside a value . This is rather strange but some suggest that there can be an equals within double quotes ( I haven't see it anywhere so I guess it is not a very possible scenario ) @see http://php.net/manual/en/function.http-parse-cookie.php#108185.
2. The second case is almost same with the first one except , if there is a comma inside a value. I also believe that this is highly impossible since comma inside cookies values are highly discouraged , but I am not sure if people comply to that.

After some tests , PHP will change , with %2C and = with %3D . So these two cases may occure only if something else sets cookies except PHP.

Edited by jkon: tests

This topic has been dead for over six months. Start a new discussion instead.
Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.