Storing Session Data In Cookies: Problems And Security Concerns To Be Aware Of

Image via Wikipedia
Back from my extended leave of absence, I’ll re-open the dusty cobwebbed depths of this blog to echo the sentiments of Paul Reinheimer in his recent article “Cookies don’t replace Sessions“. The topic is actually an old one since Ruby On Rails has adopted the strategy of storing application session data in cookies by default (take note, performance hounds). The purposes of storing sessions in userland cookies rather than the conventional “stick-it-on-the-filesystem/database” used by many apps is one of performance and a little obscuration. Cookie data can be accessed faster than hitting the filesystem/database plus it has the dubious ability to disguise the session-targeted programming language. Really though, PHP is assumed to be on all web servers so hiding its existence is a bit like trying to hide an elephant in a zoo. Hide it all you want – we still know there has to be one in there!
In exchange for speeding up session reading, storing session data in cookies has some fairly uncomfortable costs.
Now, developers are not unaware of the problems of storing potentially sensitive application data in plain text files on the user’s PC which users can manipulate, copy, and mangle to their (or the hacker’s currently fiddling with the user’s PC) heart’s content. It’s dangerous depending on just how much you rely on session data to drive other security rules or restrictions on business logic within the application. Technically, the reliance placed on sessions should be close to nothing – session data should drive the application towards other storage solutions for the really essential stuff and just stay around as a minimal identifier/stash of basic ID info. Such minimal information can be dumped, corrupted, or overwritten with the only cost being to perhaps require a user to login again when that happens. Stuffing a bank balance into a session, on the other hand, is one (very exaggerated!) example of the kind of data you should be shot for relying on a session for.
Programmers being programmers, it’s not rare to see sessions become a more intrinsically important storage location than it should be. In those cases, being able to manipulate the session data can become a problem and may give rise to exploitation scenarios where tampering with the stored data leads to some benefit for the manipulator. Obviously we want to make sure that that can’t happen even in scenarios where programmers may be a bit loose with where they store data. We don’t build frameworks and libraries for Gurus, we build them for all programmers – even the sometimes ignorant and under trained ones. This cookie stored session data is often coupled with the ability to encrypt that data. However…
As Paul Rainheimer remarks in his article, “Encryption is often viewed as a panacea for security problems, you sprinkle a little encryption dust around, and your problems dissolve”. This is an absolute truth in programming – programmers often view encryption as a solution without regard for one teeny tiny problem. If you encrypt a set of data for any purpose, even though it’s encrypted, the user (or the hacker hacking the user’s account) still has the data in some usable form!
With perfectly intact data, and even through it’s hidden by encryption, that data can be recycled simply by copying it to another machine. Depending on the data that is stored (which admittedly may require the hacker/user to figure out by doing actual work like finding your open source app on Github or breaking a developer’s fingers until they spill the beans), you can restore past data just by copying over a backup of a prior cookie or repeat a past transaction by continually reusing the original cookie it required. Paul offers a few trivial examples in his article.
Such reuse of data is known as a replay attack. A scenario where even encrypted data can be constantly reused to give rise to a positive result – all without any need whatsoever to break the encryption. The antidote to this vulnerability is to ensure that all data sets are unique and can be used only once, i.e. you include a single-use nonce (some generated set of characters or bits) in the data which is updated whenever that data is used. This continually forces the update of the relevant digital HMAC signature and/or encryption result (even for the exact same data otherwise) in order to prevent any reuse of old data in a replay attack. Once a nonce is used, it’s discarded, and the old data can no longer be accepted by your application. Of course, the downside is that since the nonce must be single-use, you need to keep track of all nonces to ensure they are not accidentally used again. You will need a database, possibly using a nonce-included timestamp as a time limit so your storage requirements aren’t completed insane, which obviously means that just using the traditional database storage for sessions in the first place would have been a much better and simpler choice.
So, in summary, encryption prevents the reading of data but it does not prevent the reuse of existing data. For that to be prevented you need a nonce implementation. And, due to the complexity of using and tracking nonces, practically no cookie stored session solutions will actually offer nonce support because it would eliminate their speed advantage. Which means they are susceptible to replay attacks, which means they are dangerous tools to be swinging around blindly, which means that the old local session storage strategies are still far superior from a security perspective, which all means that you should avoid cookie stores like the damned plague and stick to the old, traditional but secure session storage strategies we already have unless you a) are crazy or b) trust your colleagues (and yourself) not to screw it up.
Even without the security concerns, there is also another less critical downside to storing sessions in cookies which is that cookies have a storage limit of around 4KB. No other storage solution for session data should have that problem but you need to be aware of it anyway as using encryption may push you there sooner than the base data size might suggest (encrypted data size is usually larger than the original data). While noting this, you should never really hit that limit unless you are storing data there that you likely shouldn’t be anyway!
So, cookie based session storage: It’s very fast but lethally insecure if you store the wrong type of data. If you’re going to use it, make sure you keep a tight rein on what data is being stored.
Jani Hartikainen's Blog: Why does everything need to be integrated into a framework?
In this new post to his blog Jani Hartikainen wonders if "everything needs to be integrated into a framework".
There is occasionally people asking about things such as "Is there an integration for X in framework Y?" Then they are disappointed when it isn't, acting as if it's a really bad thing. But why do things need to be integrated to begin with?He points out that other frameworks (ex. Ruby on Rails) have a lot of things integrated, but he doesn't agree that this should be the standard. He suggests that, by not having tools that are tightly coupled with the framework you're using, you open yourself up to a wider, possibly better range of external tools.
One could argue that integrated libraries give you a productivity boost. While it may be so, I think the main boost you get is the very first steps: It's easier to get started, but after that the benefit fades. In the long run, it may even turn into a poor investment in general, as you could have learned a general purpose tool instead.7php.com: Interview With Michelangelo van Dam - President Of PHPBenelux PHP Use
On 7php.com today there's a new community interview - this time it's with Michelangelo van Dam, the President of the PHPBenelux user group and well known PHP speaker/community advocate.
In this edition, I talked with Michelangelo van Dam a senior PHP/Zend Framework consultant. This man really needs no introduction; he is so much of an invaluable asset to the PHP community. As per wefollow.com, he is ranked as the 4th (out of 113) most influential person on Twitter for #zendframework and as the 25th (out of 2,543) most influential person for #phpQuestions in the interview cover everything from a bit of history about Michelangelo out to how supportive the PHP community is:
Give and expect nothing in return. People appreciate it more when you give something from the heart instead of giving something as a favor for a future return.Other questions touch on his "community animal" nickname, his community/life balance and his tracking of the work Microsoft is doing to help the PHP language.
Lorna Mitchell's Blog: Building A RESTful PHP Server: Routing the Request
Lorna Mitchell is back with a second installment in her "Building a RESTful PHP Server" series with this new post about handling and routing the incoming requests. (You can find the first part about working with the request here)
This is the second part of a series, showing how you might write a RESTful API using PHP. This part covers the routing, autoloading, and controller code for the service, and follows on from the first installment which showed how to parse the incoming request to get all the information you need.She shows how to grab the controller name from the incoming request (based on her previous code), create the object for it and execute the requested action name. Also included is a sample autoloader and a basic controller - a UsersController with "getAction" and "postAction" methods for responding to GET and POST requests.
Fabien Potencier's Blog: Create your own framework... on top of the Symfony2 Components (part 10)
Fabien Potencier has posted the tenth part of his series about making a custom framework based on the Symfony2 component set. In this latest article he focuses on using the HttpKernelInterface to add in some additional HTTP-related support.
In the conclusion of the second part of this series, I've talked about one great benefit of using the Symfony2 components: the interoperability between all frameworks and applications using them. Let's do a big step towards this goal by making our framework implement HttpKernelInterface.By changing up the custom framework just a bit to use HttpKernelInterface, you get built-in HTTP caching (HttpCache). He shows how to use this class to create some custom caching rules and how to use Edge Side Includes to only cache partial parts of the page.
NetTuts.com: Testing your PHP Codebase with EnhancePHP
On NetTuts.com today a new tutorial has been posted to help you test your applications and make it a simpler process using the EnhancePHP framework. EnhancePHP is a lightweight Open Source PHP unit testing framework with support for mocks and stubs.
You know it; I know it. We should be testing our code more than we do. Part of the reason we don't, I think, is that we don't know exactly how. Well, I'm getting rid of that excuse today: I'm teaching you to test your PHP with the EnhancePHP framework.He shows you how to download it, get it installed and creates a simple structure to do some TDD (Test-Driven Development) with it. His tests check three things - valid email addresses, username restrictions and phone number formatting. He also includes a look at creating mocks/stubs for a "scoreboard" example.
You can find out more about the EnhancePHP framework on its github page.
PHPMaster.com: Rapid Application Development with CakePHP
On PHPMaster.com today there's a a new tutorial helping you take some first steps with CakePHP, a popular full-stack PHP framework, by Vito Tardia.
CakePHP is a framework that provides a solid base for PHP development. It allows users at any skill level to rapidly develop robust web applications. [...] Personally, the reason why I prefer CakePHP over other PHP frameworks is its better support for console applications. CakePHP has a powerful console tool that can be customized to build applications for both the web and the console world. In this article I'll introduce you to two of CakePHP's most useful features: automatic code generation using the console tool Bake and dynamic scaffolding.He walks you through the full (user friendly) installation and configuration, a few changes to increase security and where to go to set up your database connection. From there he shows how to use the "Bake" command to generate a "subscribers" model and automatically create the user interfaces to work with it (CRUD operations)
Sh*t Project Managers Say
Practical PHP Refactoring: Collapse Hierarchy
Intercepting class method invocations using metaclass programming in Python
In Ruby, objects have a handy method called method_missing which allows one to handle method calls for methods that have not been defined. Most examples out there explain how to implement this in Python using __getattr__, however, none of them (honestly, none) explain how to intercept class method invocations using __metaclass__.
And that’s why I wrote this post.
The function type is the built-in metaclass Python uses, it not only lets you know the type of an object, but also create classes on the fly. When you write, for example: class Example(object) the class object Example is not created in memory straight away. Python looks for the __metaclass__ attribute in the class definition and if it finds it, it uses it to create the object class Example. If it doesn’t, it uses type to create the class. The main purpose of a metaclass is to change the class automatically, when it’s created.
Here’s an example of how to use metaclass programming to intercept class method calls similar to the method_missing technique in Ruby:
class MethodInterceptor(type):
def __getattr__(cls, name):
def intercept(*args, **kwargs):
return cls.static_method_missing(name, *args, **kwargs)
return intercept()
def static_method_missing(cls, method_name, *args, **kwargs):
e = "type object 'static.%s' has no attribute '%s'" \
% (cls.__name__, method_name)
raise AttributeError(e)
class Example(object):
__metaclass__ = MethodInterceptor
def __getattr__(self, name):
def intercept(*args, **kwargs):
return self.method_missing(name, *args, **kwargs)
return intercept()
def method_missing(self, method_name, *args, **kwargs):
e = "type object '%s' has no attribute '%s'" \
% (self.__class__.__name__, method_name)
raise AttributeError(e)
@classmethod
def static(cls):
print 'static.%s' % cls.__name__
def instance(self):
print self.__class__.__name__
Example:
>>> Example.static()
static.Example
>>> Example.foo()
Traceback (most recent call last):
...
File "example.py", line 12, in static_method_missing
raise AttributeError(e)
AttributeError: type object 'static.Example' has no attribute 'foo'
>>> e = Example()
>>> e.instance()
Example
>>> e.foo()
Traceback (most recent call last):
...
File "example.py", line 26, in method_missing
raise AttributeError(e)
AttributeError: type object 'Example' has no attribute 'foo'
If you ever implement something like this, remember that Python doesn’t distinguish between methods and attributes the way Ruby does. There is no difference in Python between properties and methods. A method is just a property whose type is instancemethod.
Filed under: Programming, Python
DBAL and ORM 2.2 Release candidates
Jakub Zalas' Blog: Mocking Symfony Container services in Behat scenarios with Mockery
Jakub Zalas has a recent post to his blog with a hint about how to test Symfony container services by mocking them (when testing with Behat) with the help of Mockery (and the PSSMockeryBundle).
Mocking objects in unit tests is pretty straightforward as every object used in a test case is usually created in a scope of one test class. In functional tests it's a bit harder since we either don't have full control over objects being created or it's simply too laborious to mock half the framework. [...] We're getting the service from a container [in the example] and calling a method which should send a lead. The problem is we don't want to actually call an API while executing Behat scenarios.Rather than hitting up the API for each test, he opts to create mock objects and results with the tools Mockery has to offer. He gives code for a "is API available" method that either returns a valid container or a mocked object, depending on how it was called.
DZone Top Article of 2011: Programmers are f***ing lazy
Michael Nitschinger's Blog: Session Encryption with Lithium
Michael Nitschinger has a new post for the Lithium framework users out there - a quick tutorial about encrypting your session information with the new built in "Encrypt" strategy feature.
If you check out the master branch, you can use the new Encrypt strategy to encrypt your session data automatically. This means that you can read and write session data in cleartext and they will be encrypted on the fly before getting stored (in a cookie, for example).You'll need the mcrypt extension installed for it to work correctly, but it makes storing the encrypted version of your data more or less automatic. Just set up your Session configuration to use it as a strategy and any time you call a "read" or "write" the hard work is handled for you. For those more interests in what's "under the hood" he goes on to talk about how the strategy works, what cipher it uses by default, how to change it and the default string to use in hashing.
IBM developerWorks: Store datasets directly in shared memory with PHP
On the IBM developerWorks site today there's a new tutorial showing you how to store shared data directly to a shared memory space of your PHP application.
Once created, and given proper permissions, other processes in the same machine can manipulate those segments by: read, write, and delete. This means that an application written in C can share information with an application written in other languages, such as Java or PHP. They can all share information, as long as they can access and understand that information. [...] This article's proposal is simple, learn how to create and manipulate shared memory segments with PHP and use them to store datasets that other applications can use.Your PHP installation will need to have been compiled with "enable-shmop" to work with the code in this tutorial. Their examples show how to use the shmop_open, shmop_write and other related functions to read, write, remove and close segments in the shared memory space. They also include an example of using the SimpleSHM library to make it easier to interact with the shared memory space as a standard storage location.
WebDevRadio: Episode 95:Jeff Carouth Interview from Zendcon 2011
The WebDev Radio podcast has released their latest episode today - an interview with Jeff Carouth (@jcarouth) from last year's ZendCon conference:
I chatted with Jeff Carouth about his day to day worklife as a PHP guy (among other things) at Texas A and M. Learn the A and M mascot name, Jeff's favorite design pattern, and more.You can listen to this latest episode either via the in-page player or by downloading the mp3 directly.
DZone.com: PHPUnit_Selenium
On DZone.com today Giorgio Sironi has a quick tutorial showing you how to set up and use the PHPUnit_Selenium component in the latest releases of the popular testing software.
With the 1.2 release, PHPUnit_Selenium supports (basically) for the first time the Selenium 2 WebDriver API. While PHPUnit_Selenium already worked with Selenium 2, it did so only by using the Selenium 1 emulation included in the jar; now it provides an object-oriented API right natively supported in a base PHPUnit test case, shipped in PHPUnit's PEAR channel.He includes the steps you'll need to pull it from the PEAR channel and how to set up a test case based on the PHPUnit_Extensions_Selenium2TestCase object. He gives a few examples of how to select various components on the page (via CSS selectors and XPath), assert that the right information is there and interact with forms.
Brian Swan's Blog: Using SQL Azure Federations via PHP
Brian Swan has a new post to his blog about using Azure Federations in your PHP applications:
In a nutshell, SQL Azure Federations introduces an abstraction layer for the sharding of SQL Azure databases. The value in federations lies in your ability to have elastic scalability of the database layer of your application (to match the elastic scalability of the rest of your application when it's running in the cloud). And, one nice thing about the way federations work is that nearly everything can be done with simple SQL commands. Of course, that means that using SQL Azure Federations via PHP should be easy. So in this post, I'll introduce you to SQL Azure federations by showing you how to use them via PHP.He uses the SQL Server drivers to make the connection to the Azure instance and, based on his included code, creates a federation and tables inside it. He also shows how to insert data into these tables, split up a federation, insert data after this split and how to query a federation member with the filtering on or off.
Site News: Popular Posts for the Week of 01.20.2012
- Gonzalo Ayuso's Blog: Checking the performance of PHP exceptions
- PHPMaster.com: MongoDB Revisited
- DZone.com: Open/Closed Principle on real world code
- Stuart Herbert's Blog: ContractLib - An Introduction & Comparing it to PHP's Assert
- Stuart Herbert's Blog: Introducing ContractLib (Programming Contracts)
- Larry Garfield's Blog: PHP project structure survey
- Dave Marshall's Blog: Defending against Cache Stampedes
- Ulf Wendel's Blog: PHP mysqli quickstart is online!
- NetTuts.com: Zend Framework from Scratch - Models and Integrating Doctrine ORM
- Developer Drive: Building a PHP Ad Tracker: Creating the Database Tables