PHP Security: Dumb Users or Dumb APIs?
There’s another round of “Is PHP Secure?” debate happening right now. Chris drew attention to it, pointing to a post by Andrew van der Stock (who’s a contributor to OWASP): PHP Insecurity: Failure of Leadership.
So the usual denials have been made (see replies to Chris’s entry) – “Damn newbies”, “Holes in PHP-based app != PHP insecure”, etc., all of which I agree with. But…
Think it is safe to assume that pointy haired bosses are picking up signals containing the words “PHP” and “vulnerability”. At this point, perhaps you don’t care – your stronghold keeps the pointy haired people on the outside. But once you’ve run into this wall once, while bidding with / arguing for PHP (I’ve been in the latter situation), you start to wonder.
So let’s turn things around for a moment and try some fresh discussion.
What if Andrew does have a point? What if we’re living in denial? I think Andrew got “slayed” initially because his argumentation is too cautious not too scandalous. But later on (see his second comment to Chris’s post) think he finally nails it;
Struts and .NET both make the easiest to use output method XSS safe by default.
.NET’s web forms have page validation methods, which automatically detect most forms of XSS attack without writing any code.
Now let’s contrast with this innocent looking snippet of PHP and HTML;
<form action="<?php echo $_SERVER['PHP_SELF']; ?>"> <input type="hidden" name="submitted" value="1" /> <input type="submit" value="Submit!" /> </form>
We haven’t even got to accepting any user input – we’re just displaying a form right? This is the example is sprayed all over the web – a great way to avoid hard coding a script name. Whoops – sorry about the XSS.
So who’s dumber? The “stupid newbie” who hasn’t grasped the relationship between the $_SERVER superglobal and the CGI or PHP for failing to expose a simple and secure solution for this very common problem: how to display a form which submits to itself, without hard coding the action attribute?
Let’s get yet more controversial and pick on short open tag. Great stuff because it allows you to do this:
<?=$someVar?>. Oh wait… more potential for XSS. Alan Knowles summed that topic nicely here;
This is why PHP style templates are just a bad idea..—unless you copy and paste htmlspecialchars everywhere, in which case, you have to look through the trees to see the bugs…
The output layer should default to escaping code if possible, and make it easy to find where escaping is not done, not the other way round.
Perhaps “smart” would be to have that style of short tag automatically pass output through htmlspecialchars?
Entering a much grayer zone… another PHP reality is if you really want to be able to do user input validation strictly, you need regular expressions – there’s really no way round it.
Regexes are fine if you know how but real newbies (i.e. first time coding) would rather run a mile. Could PHP offer something by default to address this, such as a set of functions, for validating common input? Yes I know that’s a dark path to functions with optional arguments like “charset” but emphasis on the word common, as in common use case – probably those guys still encoding that pages as ISO-8859-1. Most of the PHP frameworks that sprout “dozen a day” right now pack a default set of validation helpers – why do they do that?
An alternative path is filtering. Derick mentioned this PECL extension, which he’s been working on with Rasmus. This is a whitelist / blacklist thing and the sceptical might argue it will lead to magic_quotes V2. And what about lessons from the Myspace worm?
That said, Jeff raises good points on the ins and outs of input filtering here and it’s worth bearing in mind his closing remark;
I guess I’ve been programming for about 23 years now. The longer I do it, the more reluctant I am to be strict with user input. Ultra sanitized, ultra structured data may seem attractive to the programmer, but its a pain for the user and its only a matter of time before a legitimate exception comes along. A European phone number, the 51rst state, a canadian postal code, a new millennium, etc. The exception is the rule. Understandably, XSS must be prevented, but its easy to go too far.
Marco has interesting things to say as well, following on from Chris’s post, which boil down to;
I don’t think that security belongs in the language itself.
There you have to pause on that word “language”. Sterling Hughes (blog now RIP but quoted here) once said;
If PHP is anything, then its a framework, which includes a really cute scripting language
Whatever you’re take on that, it doesn’t really matter. It’s what you’re getting compared to that counts.
So what’s you’re point sir?
In fact I don’t really have one. There’s nothing but hard choices and hard work here. Breaking backward compatibility to “fix” things like
$_SERVER['PHP_SELF']; or short tags obviously isn’t an option. Adding alternatives and more functions may not help much either – getting people to use them is the struggle.
What I do think is we need to stop blaming the “stupid newbies” and admit there is a problem. Call it a learning curve issue if you like. Or confess that PHP was conceived in the days of the webs innocence. Whatever. Point them at the available books and warn them to be careful.
And it’s likely we’ll have to make future bids based on this platform (release early, release often!), and encourage others to do the same. For the sake of the newbies, I hope “Extreme Simplicity” and MVC are able to fit into the same sentence.
But to finish on a positive note, with help from Bjarne Stroustrup;
There are only two kinds of languages: the ones people complain about and the ones nobody uses