Wrapping superglobals to enforce input sanitizing
One of the cornerstones of secure web applications is input validation and sanitization.
Frequently this is an afterthought for developers, because PHP semantics do not actually
enforce it.
With the filter extension (since PHP 5.2) this would actually be quite effortless. But not
many open source projects have adopted it yet. While it is widely available and
technically one of the best solutions, the filter extension has a cumbersome API. And
here lies the problem. If developers are to be encouraged to always validate every
piece of input, it must be ultra simple to do so. Everything else leads to laziness-related
XSS worries.
This article presents a trick to force yourself, as developer, to always apply input
validation.
We just take the raw input arrays $_GET and $_POST away. - That's it.
Or not quite.
Superglobals can be replaced like every other variable. And this proposal is to replace
$_REQUEST and Co. with objects:
$_REQUEST = new input($_REQUEST);
$_GET = new input($_GET);
$_POST = new input($_POST);
So, instead of accessing input variables the old-fashioned and may-or-may-not-forget-to-
sanitize-it way, there are now access methods. And these access methods conveniently
also provide data validation. Instead of $_GET[„category“] you'd write:
$_GET->int(„category“)
Every variable that was an array entry before in $_GET or $_POST, can now be accessed
only through one of the sanitization methods. That's it, problem solved.
How so?
With having the old superglobal arrays available, you cannot ensure that every piece of
code accesses input variables carefully. You might have legacy libraries in your
codebase, or fellow developers who are less stringent about XSS security.
By taking the old arrays away, you can force a code review. There is no way around
checking every instance and deciding on an eligible sanitizing function.
However, unlike the PHP filter function, the rewrite is not as voluminous. The syntax is
rather close to the old. Instead of $_GET[] you have $_GET->int(). That's syntactically a
serious difference, but not when it comes to key strokes.