100722 items (110 unread) in 22 feeds
MSNBC
(1 unread)
PHP
(61 unread)
Deals
(12 unread)
Web Development
(35 unread)
CNN Money
(1 unread)

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 a
Truncated by Planet PHP, read more at the original (another 3726 bytes)
A new year begins, so for the ninth year in a row, I'm taking a moment to record, reflect, assess, and aim.
Last year, I described 2010 as a landmark year, and it was. Analog, Mild Bunch, Brooklyn Beta, Mapalong, and PHP Advent. Even without factoring in conferences and such, it was a big year.

All of 2010's accomplishments seem trivial when compared to 2011, because in May, Tegan was born.
She's eight months old as I write this, and being a father still feels new. Life has changed, and I have a renewed excitement for what lies ahead. I love what I do, and I love where I do it, but I can't wait to get home each night.
If you want to keep up with Tegan, you can follow her on Twitter. Her Twitter account has been a fun way to record life as it happens from her perspective.
Here are a few other highlights of 2011:
Mapalong Mapalong is an app for bookmarking places. In a nutshell, we've made Google Maps social and beautiful. I haven't blogged much about Mapalong, but 2011 was full of ups and downs that I wish I had recorded. Although I've been involved with many startups and have even been involved early enough to be emotionally and financially invested, there's nothing quite like the struggle of bringing your own idea to life. If we find the right investor, we're going to be growing the team and opening the doors this year, and that's exciting. If you'd like to try Mapalong in the meantime, reserve your username with Twitter, then let me know. Brooklyn Beta With the help of our colleagues and friends (especially Jessi), Cameron and I organized a second Brooklyn Beta this past October. It was an experience that's hard for me to put into words. I will try to summarize Brooklyn Beta in a separate post soon. For now, I'd just like to say thanks to every speaker and every attendee who helped make it something truly special. Ideas of March In March, I pledged to blog more and convinced a lot of other people to do the same. It worked for a while. Planet Chris was full of wonderful content, and my link blog was busier than ever. Over time, my commitment waned, but I had a pretty good excuse. No excuses this year; I will get my blogging rhythm back. Conferences I went to New Adventures in January, but I went as an attendee, not a speaker. In fact, I did not speak at any conferences in 2011. (I spoke briefly at Brooklyn Beta, but that doesn't really count.) Just a few years ago, a recurring resolution was to speak at fewer conferences, because I felt like I was never home. How things have changed! 2011 was a really nice break, and it gave me a chance to focus on my family and my work. PHP Advent Sean and I curated another PHP Advent. This year was more of a struggle than usual, but I'm very happy with how it turned out.Finally, here are a few goals for the coming year:
Mapalong I believe strongly in Mapalong's promise, and 2012 is an important year. We need money to give us the freedom to focus on it and make it a success. We're also working on an iOS app with full mobile support to follow. Once you can take Mapalong with you wherever you go, we'll be a release or two away from opening the doors. I can't wait. Brooklyn Beta This is the year Brooklyn Beta becomes more than a conference. We've got some exciting things planned, and if you want to stay informed, please follow @brooklynbeta or subscribe to our newsletter. Conferences In 2012, I'm going to speak at a few select events. In FebTruncated by Planet PHP, read more at the original (another 1299 bytes)
I’ve seen several instances where people have demonstrated the ease with which encrypted cookies can replace sessions within PHP. Michael Nitschinger wrote a piece recently demonstrating the switch with Lithium, while CodeIgniter does this by default (optionally encrypting). The problem is that while replacing sessions with cookies works, it introduces a few risks not present with native session support, and these risks tend to be under documented.
Encryption is often viewed as a panacea for security problems, you sprinkle a little encryption dust around, and your problems dissolve. Unfortunately, while properly implemented encryption solves the problem of other people reading your encrypted data quite well, it doesn’t do much else. It doesn’t (on its own) tell you if other people have duplicated your data, manipulated the data in question, or handed you an old copy of properly encrypted data.
Consider an attacker who manages to sit in between Amazon and one of their warehouses. Amazon (in this theoretical example) encrypts all order instructions well, then transmits them to the warehouse. The warehouse decrypts the instruction, fills the order, and ships. If the attacker wanted free stuff they could place an order during a low traffic period, and wait for Amazon to send an encrypted message and make a copy. A few minutes later they could re-send that encrypted message to the warehouse, never having even tried to read it. With luck, they’ll soon receive two of whatever they just ordered! This is an instance of the replay attack, and that vulnerability is the one this post will examine in detail.
Exploiting cookie based sessionsExecuting a replay attack against a cookie based session is easy, legitimately obtain some desired state on the system in question, and make a copy of your cookies. Should something go wrong, simply restore your cookies to the previous state. To demonstrate this, I’ve created a sample gambling application, you can get the source from github, or Play Now! (thanks to Orchestra.io, it's a free account so give it a moment)
In the game you start with $1000, then have the ability to make arbitrary wagers. Make a few bets to get a feel for the system, then make a copy of your cookie values. Bet again. If you lose money, simply restore your earlier cookies to get that money back. That’s it. This attack works because the system is willing to accept any successfully decrypted message as a valid, and current, session.
This attack doesn’t exist under traditional session storage. The user’s cookie doesn’t change from one request to the next as their money goes up and down. If a system is regenerating the session ID when the user changes privilege levels, the old session is deleted and no longer available when invoked properly: session_regenerate_id(TRUE);
A system using cookie based session storage, while using a CAPTCHA to defeat bots is doomed to fail, the attacker could solve the CAPTCHA once, then re-use that same cookie a million times. Encryption makes it difficult for an attacker to read the message, additional systems must be bolted on to defend against this sort of attack. In the stateless world of HTTP and the web, this is exceedingly difficult without some server-side datastore.
While this was clearly a trivial example, the problem is not. If you’re looking at using cookie based sessions it’s one of the things you need to be aware of.
If you’re interested in learning more about cryptography, including a great rundown of this problem and many others, I’d highly recommend Practical Cryptography
This article is part of a series of articles that explains how to create a framework with the Symfony2 Components: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12.
If you were to use our framework right now, you would probably have to add support for custom error messages. Right now, we have 404 and 500 error support but the responses are hardcoded in the framework itself. Making them customizable is easy enough though: dispatch a new event and listen to it. Doing it right means that the listener has to call a regular controller. But what if the error controller throws an exception? You will end up in an infinite loop. There should be an easier way, right?
Enter the HttpKernel class. Instead of solving the same problem over and
over again and instead of reinventing the wheel each time, the HttpKernel
class is a generic, extensible, and flexible implementation of
HttpKernelInterface.
This class is very similar to the framework class we have written so far: it dispatches events at some strategic points during the handling of the request, it uses a controller resolver to choose the controller to dispatch the request to, and as an added bonus, it takes care of edge cases and provides great feedback when a problem arises.
Here is the new framework code:
<?php // example.com/src/Simplex/Framework.php namespace Simplex; use Symfony\Component [HttpKernel\HttpKernel;] class Framework extends [HttpKernel] { }
And the new front controller:
<?php // example.com/web/front.php require_once __DIR__.'/../vendor/.composer/autoload.php'; use Symfony\Component [HttpFoundation\Request;] use Symfony\Component [HttpFoundation\Response;] use Symfony\Component\Routing; use Symfony\Component [HttpKernel;] use Symfony\Component\EventDispatcher\EventDispatcher; $request = Request::createFromGlobals(); $routes = include __DIR__.'/../src/app.php'; $context = new Routing\RequestContext(); $matcher = new Routing\Matcher\UrlMatcher($routes, $context); $resolver = new [HttpKernel\Controller\ControllerResolver();] $dispatcher = new EventDispatcher(); $dispatcher->addSubscriber(new [HttpKernel\EventListener\RouterListener(] matcher));
Truncated by Planet PHP, read more at the original (another 11484 bytes)
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.
Routing to ControllersIn this setup, we'll have models, controllers and ... output handlers. It's not really a view, because all we will do is transform the data to a given output format. More on that later on - for now we will return the data we fetch in the controller back to index.php, and dump it out so we can inspect it.
For RESTful routing, each thing in the system is considered as a resource, and it has a unique resource identifier (or URI) to represent it. In this example system, we have users and groups. Each resource belongs to a collection, which is the level above the resource – I usually think of files being in directories when I think of resources belonging to collections.
So for an incoming GET request to /users, we will return a list of users as this is the collection. Within our application, this means calling the getAction() on the UsersController, so index.php now looks like this:
// route the request to the right place
$controller_name = ucfirst($url_elements[1]) . 'Controller';
if (class_exists($controller_name)) {
$controller = new $controller_name();
$action_name = strtolower($verb) . 'Action';
$result = $controller->$action_name();
print_r($result);
}
At this point, you'll write a controller and model that will look hauntingly familiar from all the other MVC systems you've ever written! Before we do that though, let's talk about architecture and autoloading.
Designing and Loading ClassesWorking with classes gets much easier if you put them in reliable places and call them reliable names. If you do, you can autoload them and avoid all those tedious require() statements. My directory structure looks like this:
. ├── controllers │ ├── MyController.php │ └── UsersController.php ├── index.php └── models
The users controller is in the controllers directory, and it inherits from a shared parent controller called MyController. I have no idea what will go into here, but from experience, I recommend that both models and controllers should inherit from a shared parent - as will our output handlers (because we don't have views) later on. You can see that the controllers are reliably found in the controllers directory, called something ending in *Controller.php. This makes it simple to add to an autoload rule
Truncated by Planet PHP, read more at the original (another 12049 bytes)