intelliproject logo

Location: Web development - PHP    License: The GNU General Public License (GPL)

Cookie or not Cookie

Posted by europeaw

How to know if client accept cookies, and what you can do if not.

Skill: Beginner

Posted: 09/12/2008

Views: 575

Rating: 4.00 /5

Popularity: 0.00

Sign Up to vote for this article

Introduction

On a lot of forums I found this basic question about PHP sessions:

How to know if the client accept cookies ?

The easyest way I found is to start a session and look at the constant SID.

About sessions :

On the PHP manual you can find this introduction about sessions:

"Session support in PHP consists of a way to preserve certain data across subsequent accesses. This enables you to build more customized applications and increase the appeal of your web site.

A visitor accessing your web site is assigned a unique id, the so-called session id. This is either stored in a cookie on the user side or is propagated in the URL."

As propagating the session id in the URL isn't the safest way to do, most of sites use cookies, but users can choose to not accept cookies and the session id is propagated in the URL. By default the directive session.use_trans_sid is set to false, urls are not rewritten to send the SID and sessions are not available for users who don't accept cookies (see also directive session.use_only_cookies).

To avoid this you can :

  • enable session.use_trans_sid and modifiy the directive url_rewriter.tags to set wich urls are rewritten
  • or for some cases, manage yourself how urls are written depending on the user.

How to manage sessions without transparent SID?

First we have to know if the user accept cookies or not. When the session start (session_start()), the constant SID is defined and receive the session id if you don't use cookies, or an empty string ('') if you use cookies.

Example :

On the example, you can see that we send the GET variable PHPSESSID between each page to keep current session if cookies are disabled. On forms you can use an hidden input and send PHPSESSID by POST or GET method. But propagating the session id by url isn't safe because everybody can get your information if they found your session id, so I would suggest a way to add more security.

Suggesting a security issue

A basic issue is to change the session id between each pages. On the example below, uncomment line 11 and replace line 10 by session_regenerate_id(true) ; ( true to delete old sessions )

Another solution, is to have a fixed session id and use an temporary id to send in the URL. For this solution, you have to store an table of temporary id and corresponding sessions id, there is different way to do: file, database or shared memory. The example below use shared memory, it is given as a demonstration without any guarantees, I strongly advise to complete it to prevent attacks for sessions by cookies.

All is explained commented in the code, completed by the notes and the example below.

NOTES: The class shm_session use singleton pattern to have only one instance of the class (one session = one object only).

To create a new shm_session object you have the choice between two static methods :

  • shm_session::create(optional $tid) // if you want to specify the temporary id by hand
  • shm_session::start() // if the temporary id is send by GET or POST

Unless the visitor use cookies, if $tid is false or if no temporary id is found a new session start with a new temporary id, otherwise while constructing, the session id is got in the shared memory and the session start as if it was sent by url. You can use the static variable shm_session::$cookie to know if the visitor accept cookies and the constant TID to send the temporary id to the next page.

There is also two others public statics methods :

  • shm_session::clean_mem(optional $address) // if you want to clean a memory segment
  • shm_session::show_mem(optional $address) // to see all stored sessions and temporary ids

If you want to change the size of memory, or the address you have to clean it before with the method clean_mem , otherwise it may not function and return errors.

As semaphores don't function on Windows, they're not required but it's more safe with them. (not tested without)

EXAMPLE :

EXAMPLE SCREEN SHOOT :

Example Screen Shoot

Conclusion

We have seen that sessions in PHP are not easy as we can think. There is a lot of potential risks of security, we cannot just make a session_start( ) and pray god to save us from attacks.

As sessions by cookies are safest and because I think it's better to prevent attacks depending on the user preference about cookies, I've presented a way to protect sessions only when you don't use cookies letting you free to choose your method for sessions by cookies. Then I just aim at introduce basic concept, and let you dig to find your solution and not just copy and paste mine (it's more secure for my sites and for yours) so I give below some tracks to improve security that can be used with shm_session or not.

The method suggested at the PHP security consortium site (see one example here) use a fingerprint with user consistant informations (like user agent) that permit to identify if the visitor is the same between each pages, you can save the fingerprint in the variable $_SESSION or why not in the shared memory.In despite it reduce risks of hijacking attacks (it's a good idea to implement it), I have a critic about, if someone have captured your session id (the base for hijacking), I don't think it's difficult for him to have your user agent and sending it in his headers (if he has your session id he certainly has already captured your headers). With a simple PHP script that implement a browser everybody can send modified headers, as this method is well known it's not a security insurance. Another track can be to regenerate the session id if the user accept cookies and store it in the shared memory at the key of the temporary id, this would not break sessions when an user alternate connections with cookie and without, but this not protect efficiently againt hijacking attacks. Finally you can use shared memory with shm_session to store other informations (see session_set_save_handler ), and with solutions presented in this article I hope you have basis for a better protection against attacks on sessions and a better comprehension of sessions.

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPL)

About the author

europeaw

Location: France
Ocupation: PHP dev
Home page: http://europeaweb.com

Posted by europeaw at 10/12/2008 19:41
I forgot to mention that shm_session is compatible with sending PHPSESSID by GET or POST. If you want to disable it, add something like this: if (isset($_POST['PHPSESSID'])) unset ($_POST['PHPSESSID']);
if (isset($_GET['PHPSESSID'])) unset ($_GET['PHPSESSID']);

Sign up to post message on the article message board!