

Inspekt is a library for PHP4 and PHP5 that aims to make safe input handing easier, and unsafe actions more difficult. Inspekt establishes a new development approach by wrapping input within “cage” objects, and requiring the developer to use validation and filtering methods to test and manipulate the input data. This article provides a brief introduction to Inspekt and its capabilities.
Inspekt is a library for PHP 4 and PHP 5 that aims to make safe input handing easier, and unsafe actions more difficult. Inspekt establishes a new development approach by wrapping input within “cage” objects, and requiring the developer to use validation and filtering methods to test and manipulate the input data. In cases where raw, unfiltered input is required, the developer is forced to demonstrate clear intent. This makes secure development significantly easier, and insecure development significantly harder.
If we examine security issues in web applications, the vast majority have to do with how input is handled. The National Vulnerability Database data from the past two years shows us that mistakes with input validation and filtering in PHP-based web apps account for a near-majority of all reported vulnerabilities. Handling input safely, then, needs to be a core focus of the tools and libraries a developer chooses.
The standard way of retrieving input in PHP is to work with the Superglobals. $_GET, $_POST, $_COOKIE and the rest give you easy access to data passed into your web app, like so:
Despite the comments above, this is not awesome. If you've read anything with the words “security” and “PHP” in the title within the past few years, you will have noticed that there's no input filtering or validation being done in the code above. It's ripe for all sorts of attacks.
The usual way this gets addressed is with what we might call piecemeal filtering. Basically, you pick the appropriate function and call it right before you do anything dangerous with your data.
That works okay for short snippets of code, but some problems start showing up when we deal with anything of appreciable size:
Inspekt takes a different approach. When used in the recommended way, the unsafe choice is no longer the default. The developer is forced to make a decision about how to handle input at every step.
Inspekt does this by creating cage objects around input data. These cages only allow access to their data through their methods, all of which perform validation or filtering, save for the getRaw method. The creation of the cage also unsets the existing Superglobal, so the only way to get the data is through the cage object.
The above example only wraps one Superglobal in an input cage. Inspekt makes it easy to automatically wrap all input with the makeSuperCage method:
With the SuperCage, a cage is made for each Superglobal and assigned as a property to the SuperCage. They are:
$sc->get: cage from $_GET
$sc->post: cage from $_POST
$sc->cookie: cage from $_COOKIE
$sc->server: cage from $_SERVER
$sc->files: cage from $_FILES
$sc->env: cage from $_ENV
Each cage has a variety of methods for filtering and validation. Filter methods remove data from the value of the given key and return what remains. If the key does not exist, they return FALSE. Some examples include:
getAlnumgetIntnoTagsFALSE on fail or if key fails. Some examples:testAlphatestEmailtestIpPHP's Superglobals are convenient in that they maintain a global scope without the need to declare then as globals in each function. PHP unfortunately does not allow user-defined superglobals, so we need to find a way to reduce the burden of switching scopes.
All of the Inspekt::make*Cage() methods implement a singleton pattern. This means that the developer does not have to pass the cage object to and from functions—or use the global keyword—to access it outside of the global scope. Just use the make*Cage() method to access the same object you created in a different scope.
Inspekt uses a special kind of formatting to make it easier to grab an arbitrary key from a deep multidimensional array. Let's take a (rather contrived) form example like this:
Submitting the form above would give us an array that looks like this:
Inspekt's “Array Path” queries use a UNIX path-style notation to reference items inside an array. Using it, we can test a particular entry with the following code:
The notation is very simple, and has a few caveats:
/) is the separator, so you can't access keys where you're using that characterInspekt supports automatic input filtering by using a config file. Multiple filters can be chained together and applied either to a single input key, or all input within a certain method (GET, POST, etc.).
As shown above, automatic filtering is applied immediately.
Because the cage objects unset the input Superglobals, Inspekt may interfere with existing apps and frameworks. If this is the case, we might consider disabling the unset behavior like so:
If we take this approach, coding standards should be more carefully enforced. Something like the PHP_CodeSniffer package (http://pear.php.net/package/PHP_CodeSniffer/) may be very useful in these situations. The codebase can then be migrated away from reliance on Superglobals, and the unset behavior can be re-enabled.
Inspekt isn't an all-in-one solution to a web app's security problems—nothing is. Inspekt should be used as part of a multilayered security approach, including hardware and software firewalls, application firewalls like mod_security, proper configuration of PHP and other parts of your web app stack, and sensible segregation of data on a “need to know” basis.
Inspekt does, however, address the biggest security problem with web apps: improper handling of input. By changing the way we interact with input in PHP, Inspekt makes it significantly easier for developers to apply input filtering correctly and consistently.
For more information, you can visit:
I read the Poka Yoke article in php|arch, and explained something like this. With that article, i created my own filter.. a little class like this one. Then came Zend Framework, and it was not compatible. Zend_Controller_Router needed the $_GET superglobals, so we remove the unset from the class. Then, we created a simple ORM (using Zend_Db_Table) and was able to do $table->update($arrayData). Our class wasn't able to return an array, so we wrote the getRaw method... so, at the end, no one was using the filter, everywone just used the getRaw method. By this time, none of the poka yoke principles were applied to our class... and so it was removed. We thought then that filtering was a model's task (model as in MVC) and delegate that task to each model.
Hey— I wrote the poka-yoke article; if you remember, one of the conditions that I mentioned as necessary to the success of a poka-yoke system was the fact that it needs to be convenient for the developers to use—that is, the fail-safe mechanism has to be passive (i.e.: refuse to work when you're doing things the wrong way) rather than actively preventing you from doing your job. The real problem with poka-yoke is that all the pieces of the puzzle must respect them in order for the entire system to work. As you found out, this is super-difficult when you need to integrate different software products that were not all built starting from the same basic infrastructure (incidentally, this one of the very few good reasons why filtering should be built into core, and one that I've very rarely heard proponents of ext_filter make). The pieces don't fit well together, developers get annoyed and they start working around the limitations of the fail-safe mechanisms, thus defeating their purpose. I found that a good way to deal with this kind of problems is to provide as much isolation as possible between the different systems. For example, many of the pieces of software in our infrastructure talk to each other using a very simple messaging system—a sort of super-lightweight SOA—so that the design specs of each of them can be as unique as they need to be. This enables us to integrate external applications without going crazy trying to fit a square peg into a round hole, and to take advantage of convenient features in other software (like phpBB, for example), without having to compromise our own infrastructure. --Mt.

