-
Notifications
You must be signed in to change notification settings - Fork 0
Docs Session
Often there are situations when it is required to transport data from one request of the user to his next request without that this data leaves the server. This is where sessions come into play. Stubbles offers a default session implementation based on the default PHP session, but it is possible to create an own session implementation. The session classes can be found inside the net::stubbles::ipo::session package.
A class which implements one of the Stubbles interfaces or extends one of the Stubbles classes will get the session instance injected. As the session is not a singleton it should only be constructed in the very beginning of the request handling. Using the Stubbles MVC component this will take care of instantiation and passing the session to all classes that require it.
The base interface for all session implementations is net::stubbles::ipo::session::stubSession.
#php <?php $session->putValue('foo', 'bar'); var_dump($session->hasValue('foo')); var_dump($session->getValue('foo')); var_dump($session->hasValue('baz')); var_dump($session->getValue('baz', 'default')); $session->removeValue('foo'); var_dump($session->hasValue('foo')); var_dump($session->getValue('foo')); ?>
Result:
bool(true) 'bar' (length=3) bool(false) 'default' (length=7) bool(false) null
To protect an application against Cross-Site Request Forgery the session offers two methods. Basically, on every new instantiation the session creates a new random token. This token may be put into forms as a hidden field, where the value of it can be retrieved from the session via getNextToken(). After the form is submitted the application can read the token from the request and compare it with the value of getCurrentToken(). If both values are equal the application can continue the processing, else the request could have been an attempt of Cross-Site Request Forgery so the application should just represent the form to the user and ask him to submit it again.
Returns true if it is the first request of an user, and false on any subsequent requests of the same user.
Returns the unix timestamp which represents the time when the session was started.
Returns the id of the session.
Regenerates the id.
Checks if the current session is still valid. A session may be invalidated via invalidate(). Please note that an invalidated session can not be turned back into a valid session.
Deletes all session data, but leaves session intact.
Returns a list of all keys under which values are stored within the session.
The only concrete (and the default) implementation offered by Stubbles is the net::stubbles::ipo::session::stubPHPSession, a layer across the built-in PHP session system. To create an own session implementation we advise to extend the net::stubbles::ipo::session::stubAbstractSession class. This has two advantages: the concrete implementation only has to take care of storing and accessing the values while it can rely on basic behaviour like token handling, checks for validity of the session and protection against session fixation and session hijacking.
Here is a template for an own implementation based on net::stubbles::ipo::session::stubAbstractSession. For an example implemenation see net::stubbles::ipo::session::stubPHPSession.
#php <?php class MyOwnSession extends stubAbstractSession { /** ***template method for child classes to do the real construction * ***This is a replacement for the constructor. As the constructor of ***stubBaseSession is marked as final a concrete implemenation can not ***have its own constructor. This replacement is called by the parent ***constructor. * ***@param stubRequest $request access to request layer ***@param string $sessionName name of the session ***/ protected function doConstruct(stubRequest $request, $sessionName) { /* your code here */ } /** ***returns fingerprint for user * ***The return value of this method will be used to protect the application ***against session hijacking. The fingerprint of a user should be the same ***over the whole session. If the fingerprint of the user changes the ***stubAbstractSession will detect this as an attempt to hijack a session and ***therefore invalidate the whole session. * ***@return string ***/ protected function getFingerprint() { /* your code here */ } /** ***returns session id * ***@return string the session id ***/ public function getId() { /* your code here */ } /** ***regenerates the session id but leaves session data * ***The method should create a new id for the session but not ***change any session data. ***/ public function regenerateId() { /* your code here */ } /** ***invalidates current session and creates a new one * ***When this method is called it should clear all session data ***and make the session invalid so it can not be used any more. ***/ public function invalidate() { /* your code here */ } /** ***stores a value associated with the key * ***@param string $key key to store value under ***@param mixed $value data to store ***/ protected function doPutValue($key, $value) { /* your code here */ } /** ***returns a value associated with the key or the default value * ***@param string $key key where value is stored under ***@return mixed ***/ protected function doGetValue($key) { /* your code here */ } /** ***checks whether a value associated with key exists * ***@param string $key key where value is stored under ***@return bool ***/ public function hasValue($key) { /* your code here */ } /** ***removes a value from the session * ***@param string $key key where value is stored under ***@return bool true if value existed and was removed, else false ***/ protected function doRemoveValue($key) { /* your code here */ } /** ***return an array of all keys registered in this session * ***@return array<string> ***/ protected function doGetValueKeys() { /* your code here */ } } ?>
The abstract implementation of the session class offers protection against session fixation and session hijacking. The following will describe how this protection works. Any reviews and suggestions to improve them are highly appreciated.
It should be noted that the protection relies on some behaviour implemented in the concrete session class, like getting the fingerprint of the user, regenerating the session identifier or storing and retrieving values. If the concrete class does not implement this correctly the protection may be broken and therefore not working correctly.
Session fixation is an attack that relies on tricking users to visit a site by sending them an URL that contains a session identifier known by the attacker. If the target site does not verify the integrity of a session identifier the attacker can use the same session after the victim visited the site and perform any action in the name of the victim.
To protect against such attacks the base implementation of the session checks if the session data contains a value stored under the key __stubbles_SessionStartTime. If no such value exists the session id is regenerated and the old session id will be thrown away.
Please bear in mind that this protection becomes useless if the application has a security hole which allows Session Data Pollution.
Session hijacking is an attack that relies on getting the session identifier from a user of a site. Often, users by themselves send their session identifier to other users by mistake, because it is part of the URL and the user wants to show other what he has found. Another way could be referrers. If the application contains links to other sites and the application handles session identifiers as part of the URL these will show up in the referrer for the other site. Now third parties who gain knowledge about those session identifiers can use them to identify themselves as the user and perform any action in the name of this user.
To protect against such attacks the session contains a fingerprint. This can be the IP address of the user, or its user agents name. On the start of every request the session checks if the fingerprint of the last request in the same session is equal to the fingerprint of the current request. If they are not equal the session will be invalidated. The fingerprint of the current request is stored under the key __stubbles_SessionFingerprint. The PHP implementation provided by Stubbles uses the user agent plus a configurable hidden salt for the fingerprint.
Please bear in mind that this protection becomes useless if the application has a security hole which allows Session Data Pollution or Cross-site Scripting.
As noted above the session can not guarantee protection if the application itself is vulnerable. Besides protection against those attacks that render the session protection useless the application can incorporate other measures to lower the risk of such attacks and raise the security level of the application:
- Regenerate the session identifier on every change of the user authentication (login, logout, changes of permissions)
- Usage of long random numbers/strings as session identifier (However this often is part of the session system itself and not influence able by the application or the concrete session implementation.)
- Provide a logout function and force the users to use it
- time-out session identifiers not used for more than x minutes (We think about implementing this within the abstract implementation, but did not come to a final solution yet.)