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.

<bean:write ...

and

.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

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • http://www.php-for-beginners.co.uk djdykes

    Hmm interesting, When i first started PHP the first thing i did was learn to pull things from a DB and echo stuff out, the security came later.
    I believe it’s down to the actually users of PHP to implement the security, all the tools are there its just down to how you use them. This is where the newbies need education and not to get left behind.

    I had my site hacked and was fortunate enough to be taken under the wing of a more experienced PHP developer who helped me safe guard against future attacks.
    Like you say rather then blame the language maybe we should look at better educating the users for a longer term solution. Then throwing in some functions for a quick fix.

    James

  • myrdhrin

    Any language and framework can be considered unsafe in a newbies hand; like chemical products found in your closet can be harmfull in anybodies hand if they want to mix them without knowing what they really are doing.

    People doing software need to start thinking that it’s not just putting something cute together that matters; doing software is more than that. if you want to do something cute stay away from anything that contains a branch statement.

    We should at software like we were looking at building bridges and churches… not the modern engineering way of doing it… software is nowhere mature enough to be considered engineering. I’m thinking about the masters and apprentices. In the old days nobody would have walked on a bridge is the master did not sign behind the work of his apprentice. Software is very much like that. We keep using expressions like : “I kept doing those mistakes until I found an experienced programmer that teached me this and that”, this is the verbiage of a craft… maybe we should considerer it in the full and stop putting on the tools the responsibilities that apprentices (or newbies) cannot handle in full at first.

  • Trent Reimer

    real newbies (i.e. first time coding) would rather run a mile…

    That’s because they haven’t yet perfected their programmer’s physique which will allow them to sit in their chairs for days on end. Once they’re in the groove they’ll never run again!

  • http://www.silentflute.co.uk worchyld

    Okay, if we can’t use $_SERVER['php_self'] what do we use? I don’t want to hard-code it, but I don’t want to be complict in XSS…

  • http://blog.phpdoc.info/ scoates

    htmlentities($_SERVER['PHP_SELF']) works fine

    S

  • Jaffa The Cake

    The way I see it, PHP gives you more control than .NET, PHP gives you more scope for optimisation. There’s a price for this mind, you have to avoid being an idiot with security.

  • jtoupin

    .NET is a framework, not a language. C# and VB.NET are languages.

    You can have the same .NET stuff in PHP by using any php framework (ie: Prado).

    Lets compare apples to apples.

  • WebDevGuy

    I guess I am still considered a newbie because I had not thought about or read about $_SERVER variables being XSS vulnerable.

    Does that mean you should consider session variables under SSL vulnerable as well?

    I learned PHP several years ago and have been putting it through its paces this last year. I’m learning another technology now so I can speak to the learning process of open source technology.

    There are many things to praise about open source technologies, mainly the price. And I am a big fan of not being locked in to MS or another vendor. However, can you imagine the adoption rate of PHP if there were as many books written about it as there are about .Net? Local bookstores have 6 to 8 PHP books at best and 3 to 5 shelves about .Net. I know, there’s the chicken and egg argument about books versus existing market but you get my point.

    Having “cut my PHP teeth” on sitepoint’s forums, being a newbie is not always a gentle upbringing. Sometimes you just don’t know how to even frame a question. So you end up spending days researching a question that might take an informed PHP developer a minute to explain. If that is a common theme among newbies, there should be a a “learning path” to integrate newbies. I have asked for this in other technologies and have had mixed responses.

    An example might be:
    1 – read so-and-so’s book chapter 1-5, doing examples
    2 – read http://www.so-and-so.com/php tutorial
    ….

    I started my learning with security in mind so I was thankful to find help where I could. On that note, Chris Shiflett’s book and Chris Snyder’s book look worth purchasing.

    You simply can’t tell a newbie to go read a 1000-page book and come back and talk to you then (oh, to have that kind of time available). Most need guidance in the beginning in the basics as well as security.

  • Gator99

    From what I experienced, PHP is most vulnernable to lazy programming practices. Finding a regex to filter data, even if you know absolutely nothing about them, is as close as your google toolbar.

  • http://www.whitelionsoft.com veslach

    Gator, that is true… as long as you *know* that you need a regex to filter data. Coming from a VB background I didn’t even know what regular expressions where. I found out about regular expressions from friends of mine (a perl programmer & a java programmer).

    Then there’s also the obstinant programmers who either know everything or admit that they don’t know enough, but learning would be to hard (I’ve run into both). Also don’t forget the “my users are different…”, “my friends wouldn’t do that”, “it’s only an internal app”, etc.

    Ignorance is bliss… at least until you discover all your index pages have been replaced with “we hax0r3d u”. At which point you hope you learn your lesson.

  • http://alec.bohemiandrive.com Webservant Alec

    Why not: ?

  • http://alec.bohemiandrive.com Webservant Alec

    That is, why not use action=””?

  • http://www.deanclatworthy.com Dean C

    Indeed, there was no emphasis on security and program design when I first started learning PHP. My books didn’t go into detail on it, and it only touched OOP. Nowadays i’m at uni learning java and we have a whole module on program design and security (not returning references in accessor methods when the data type is not immutable etc)…

    It’d be nice for the PHP manual to offer some basics to program security in a more clarified place (such as near the beginning of the manual). Explain how forms are processed, explain how XSS works, explain how to prevent it.

  • Pingback: Rhyll > PHP Blog > PHP Security

  • LinhGB

    If newbies use more “secure” languages without knowing that the languages (or frameworks) they use have been taking care of dealing with the vulnerabilities for them, how are they supposed to learn? Security by obscurity? It’s funny that Andrew said “.NET’s web forms have page validation methods, which automatically detect most forms of XSS attack without writing any code.” Only most? Does that mean that some types of XSS attacks will still slip through and .Net newbies will know no better? I don’t know what’s worse: not knowing what XSS attacks are or thinking that you’re safe from them when you’re not. I’d probably go with a false sense of security being the worse, as that sounds more like Microsoft’s approach to security to me.

    Also, you should compare apple to apple. PHP is a language. .Net is a framework. If you use a decent PHP framework (like Prado for example) all of these will be taken care of like in those more “secure” .Net or Java ones. I think this is one weakness of PHP that it doesn’t come with a framework by default and there are too many frameworks available for it. Similar to Linux, with so many distros, choices of desktop managers and available.

  • malikyte

    Okay, if we can’t use $_SERVER[’php_self’] what do we use? I don’t want to hard-code it, but I don’t want to be complict in XSS…

    I read, while perusing the PHP manual on-line, that someone said to use $_SERVER['SCRIPT_NAME'] over ‘PHP_SELF’, as the self can contain GET variables, whereas SCRIPT_NAME drops them. Perhaps using htmlentities() is a bit overboard, as it just involves another use of the stack where a call to a different system variable just pulls data from the language (still the stack? Either way, it’s much less intensive). If someone can find something wrong with this, please share, I’m currently using it on all my scripts.

    That is, why not use action=””?

    Because it would still contain the GET contents (any query string), I believe.

  • Adam George

    I think people should be using htmlspecialchars() anyway when they echo out URLs. Not just to prevent XSS attacks, but to make the markup standards complient. I.e. ampersands (&) in query strings need to be converted to & characters in most DOCTYPES.

    I didn’t actually know that you could send data in “http://example.com/tests/simple.php/extra_data_here” format and it would be available in PHP_SELF until I read this article. But my code will be secure anyway from XSS attacks because I’ve always used htmlspecialchars() out of habit to make sure my PHP generated markup is standards complient.

    -adam

  • http://www.recide.net/thr thr

    Why not just use: basename($_SERVER[’PHP_SELF’]);
    (If you have to use PHP_SELF that is)

  • WebDevGuy

    There is disagreement amonst PHP developers who have faced this $_SERVER[’PHP_SELF’]issue before. What does that tell you about community agreement on other security issues? I think it’s great Chris Schiflett and others are bringing PHP security to the forefront. Until there is one authoritative union or “face”, it will remain an issue because people will be free to disagree with full credibility.

  • Pingback: The Infotainment Telesector / Archive / Unsolicited Advice

  • http://www.phppatterns.com HarryF

    Thanks for honest / open comments here – had half expected to be slayed for this.

    One particular point;

    If newbies use more “secure” languages without knowing that the languages (or frameworks) they use have been taking care of dealing with the vulnerabilities for them, how are they supposed to learn?

    I think you need to be very careful about what “newbie” actually means there. I would guess the largest group of ASP.NET programmers are corporate developers following a path something like VB (desktop apps) > .NET (desktop apps) > ASP.NET. They may well not be newbies in the sense being beginners at programming – more that they are not used to thinking in terms of web apps and the specific security issues. They may also not be thinking in terms of security at all – if they’ve been developing for small user groups working in the “office next door” thats likely to be the case.

    I don’t think that having your site hacked is a required experience to be able to grasp security. Education about the risks can be as effective in teaching developers to think about the problem. If they then discover, through education, that they hadn’t even thought about a particular attack vector but, guess what, the platform they developed with had, that’s got to be a good thing.

    If you think in terms of what a beginner is obviously going to do with your platform, it’s pretty easy to make that path / use case secure against obvious problems. Perhaps you can’t cover all, but what’s better – that beginners wonder where all the & characters are coming from when they print output (via something like an auto htmlspecialchars) or that they discover that most of their code needs a detailed review after the first time they are hacked?

    Security by obscurity?

    This isn’t security by obscurity – it’s security by default. Security which is on by default unless you explicitly work round it for a particular reason.

    It’s funny that Andrew said “.NET’s web forms have page validation methods, which automatically detect most forms of XSS attack without writing any code.” Only most?

    I don’t know what “most” means in this context but I would imagine it’s along the lines of “unless you did something else, elsewhere, which broke it”. For example if you disabled reporting of charset in your “Content-Type” and had exposed yourself to UTF-7 example ( see here and here).

  • Pingback: Wonko The Sane » links for 2006-01-25

  • bonefry

    There are only two kinds of languages: the ones people complain about and the ones nobody uses

    This is the coolest quote I heard in a long time :)

  • LinhGB

    I think you need to be very careful about what “newbie” actually means there.

    Actually I was thinking of recent CompSci and SoftEng graduates who were taught ASP.Net at uni (or taught themselves ASP.Net). I know quite a few, and they think that it’s god’s gift to programmers.

    I don’t think that having your site hacked is a required experience to be able to grasp security.

    I don’t think so either.

    Secure by default is good but it’s only enough for end users. For programmers, understanding why a platform is secure by default, i.e why decisions were made to set these defaults, is far more important. For example, I understand that OpenBSD is secure by default because remote root login is disallowed and apache is chrooted out of the box, and I know why they do it that way. Being told that the platform you make your living on is secure and just leaving it at that is not a good attitude to have. If IT technicians believed Microsoft saying Windows XP SP2 is the most secure Windows they’ve ever made (they did in fact say so), they would be all fired by now.

    I don’t know what “most” means in this context but I would imagine it’s along the lines of “unless you did something else, elsewhere, which broke it”. For example if you disabled reporting of charset in your “Content-Type” and had exposed yourself to UTF-7 example ( see here and here).

    That’s precisely what I meant. It’s the understanding of why a platform is secure by default and what make it secure that is important. Not knowing what security issues are there that can affect your platform and what your platform does in the background to prevent them will come back and bite you really hard, because the lack of knowledge will give you the “power” to break that “secure by default” aspect of your platform. If I don’t know why my *nix OS disables remote root login by default and as a matter of convenience, I turn it on since I want to be root on my server all the time…well… :)

  • Pingback: Cyberborean Chronicles » Blog Archive » [Links:] Jan, 26 2006

  • Nick

    Screw the newbies. If you read a book on dynamite, then go out and try to make some, you are a fool (likely a a dead or deformed fool at this point). Same logic applies here IMHO. If people don’t take the time to learn the correct way to do something, they have no one to blame but themselves for the eventual repercussions. This is not a discussion about the security (or lack thereof) in PHP, but rather human nature in general. Just my $0.02.

  • malikyte

    Nick, the unfortunate thing is that it still comes back to PHP itself. With your dynamite example:

    1.) You can try to make some dynamite from scratch, buying all the chemicals, mixing it all together, pouring it into the candles…

    …OR…

    2.) You buy a kit with simple instructions and safety precautions.

    #2 doesn’t necessarily mean that it’s never going to be unsafe, but it’s a better chance that you’d have less problems because you don’t have to worry about the deep down nitty gritty stuff. This is something like PHP (#1) and ASP.NET (#2).

    Personally, I prefer PHP over ASP.NET (using C#), but that’s just me.

  • Pingback: Techniek » Projecten PHP en beveiliging

  • WebDevGuy

    If people don’t take the time to learn the correct way to do something, …

    The problem with that is where do you go to learn? One expert might do it this way and another expert another way.

    This is what I meant when I said earlier that until there is one recognized authority, it will be every man for himself.

    I am NOT advocating everyone give up their freedom and I am not saying we have to have a more secure base PHP be default.

    What I am saying is that everyone needs to educate themselves but in a standard way from an authoritative source. That source would consist of of 8 – 10 experts agreeing on a common way to overcome security isses.

    You might laugh and say, we can’t get 8 – 10 people to agree on that. If you do…you have restated the problem I am raising.

  • Pingback: RodeWorks » PHP Security

  • Icheb

    So what’s you’re point sir?

    My eyes hurt after having to read that sentence.

  • Hl4bFeK6tO

    uQtIgOAlE6KM qEgJ1S3mhQ B3o6TVDytknP15

  • http://www.lando-links.com planderman

    It seems like there’s a lot of php security risks when it comes to accepting input from a Web site or displaying data on a Web site. I doubt there’s any way to prevent them all, but is there a way to stop the top threats, maybe the top 5 threats?

  • crfzorgmzx