Top 10 PHP Security Vulnerabilities

Security is not a list of things you do. Security is a way of thinking, a way of looking at things, a way of dealing with the world that says “I don’t know how they’ll do it, but I know they’re going to try to screw me” and then, rather than dissolving into an existential funk, being proactive to prevent the problem.

But, you can’t buck statistics. Nobody is going to read an article entitled “Coding for Security.” Everyone wants an article with a number in it: “The 8 Most Common PHP Security Attacks and How to Avoid Them”, “23 Things Not to Say to a Super Model”, and “15 Reasons to Avoid Radiation Poisoning.” So, here goes, the “Top 10 PHP Security Vulnerabilities.”

SQL Injection

Number one on the hit list is the SQL injection attack. In this case, someone enters an SQL fragment (the classic example is a drop database statement, although there are many possibilities that don’t include deletions which could be just as destructive) as a value in your URL or web form. Never mind now how he knows what your table names are; that’s another problem entirely. You are dealing with an insidious and resourceful foe.

So, what can you do to avoid this? First and foremost you need to be suspicious of any input you accept from a user. Believe everyone is nice? Just look at your spouse’s family… they’re weird and freaky, some dangerously so.

The way to prevent this sort of thing is to use PDO Prepared Statements. I don’t want to go through a full discussion of PDO now. Suffice to say prepared statements separate the data from the instructions. In doing so, it prevents data from being treated as anything other than data. For more info, you might want to check out the article Migrate from the MySQL Extension to PDO by Timothy Boronczyk.

XSS (Cross Site Scripting)

Curse the black hearts who thrive on this type of deception. Parents, talk to you children today lest they become evil XSS’ers!

The essence of any XSS attack is the injection of code (usually JavaScript code but it can be any client-side code) into the output of your PHP script. This attack is possible when you display input that was sent to you, such as you would do with a forum posting for example. The attacker may post JavaScript code in his message that does unspeakable things to your site. Please don’t make me go into detail; my heart weeps at what these brigands are capable of.

For more information and how to protect yourself, I suggest reading these fine articles on PHPMaster:

Source Code Revelation

This one has to do with people being able to see the names and content of files they shouldn’t in the event of a breakdown in Apache’s configuration. Yeah, I dig it, this is unlikely to happen, but it could and it’s fairly easy to protect yourselves, so why not?

We all know that PHP is server side – you can’t just do a view source to see a script’s code. But if something happens to Apache and all of a sudden your scripts are served as plain text, people see source code they were never meant to see. Some of that code might list accessible configuration files or have sensitive information like database credentials.

The solution centers around how you set up the directory structure for your application. That is, it isn’t so much a problem that bad people can see some code, it’s what code they can see if sensitive files are kept in a public directory. Keep important files out of the publicly-accessible directory to avoid the consequences of this blunder.

For more information on this, including a sample of what your directory structure might look like, see point 5 in this article. For additional discussion on this topic, see this forum discussion.

Remote File Inclusion

Hang on while I try to explain this: remote file inclusion is when remote files get included in your application. Pretty deep, eh? But why is this a problem? Because the remote file is untrusted. It could have been maliciously modified to contain code you don’t want running in your application.

Suppose you have a situation where your site at www.myplace.com includes the library www.goodpeople.com/script.php. One night, www.goodpeople.com is compromised and the contents of the file is replaced with evil code that will trash your application. Then someone visits your site, you pull in the updated code, and Bam! So how do you stop it?

Fortunately, fixing this is relatively simple. All you have to do is go to your php.ini and check the settings on these flags.

  • allow_url_fopen – indicates whether external files can be included. The default is to set this to ‘on’ but you want to turn this off.
  • allow_url_include – indicates whether the include(), require(), include_once(), and require_once() functions can reference remote files. The default sets this off, and setting allow_url_fopen off forces this off too.

Session Hijacking

Session hijacking is when a ne’er-do-well steals and use someone else’s session ID, which is something like a key to a safe deposit box. When a session is set up between a client and a web server, PHP will store the session ID in a cookie on the client side probably called PHPSESSID. Sending the ID with the page request gives you access to the session info persisted on the server (which populates the super global $_SESSION array).

If someone steals a session key, is that bad? And the answer is: if you aren’t doing anything important in that session then the answer is no. But if you are using that session to authenticate a user, then it would allow some vile person to sign on and get into things. This is particularly bad if the user is important and has a lot of authority.

So how do people steal these session IDs and what can decent, God-fearing folk like us do about it?

Session IDs are commonly stolen via a XSS attack, so preventing those is a good thing that yields double benefits. It’s also important to change the session ID as often as is practical. This reduces your theft window. From within PHP you can run the session_regenerate_id() function to change the session ID and notify the client.

For those using PHP5.2 and above (you are, aren’t you?), there is a php.ini setting that will prevent JavaScript from being given access to the session id (session.cookie.httponly). Or, you can use the function session_set_cookie_parms().

Session IDs can also be vulnerable server-side if you’re using shared hosting services which store session information in globally accessible directories, like /tmp. You can block the problem simply by storing your session ID in a spot that only your scripts can access, either on disk or in a database.

Cross Site Request Forgery

Cross Site Request Forgery (CSRF), also known as the Brett Maverick, or Shawn Spencer, Gambit, involves tricking a rather unwitting user into issuing a request that is, shall we say, not in his best interest. But rather than me going on and on about CSRF attacks, refer to an outstanding example of just what kind of content we have here on PHPMaster: Preventing Cross-Site Request Forgeries by Martin Psinas.

Directory Traversal

This attack, like so many of the others, looks for for a site where the security is not all that it should be, and when if finds one, it causes files to be accessed that the owner did not plan to make publicly accessible. It’s also known as the ../ (dot, dot, slash) attack, the climbing attack, and the backtracking attack.

There are a few ways to protect against this attack. The first is to wish really, really hard that it won’t happen to you. Sometimes wishing on fairies and unicorns will help. Sometimes it doesn’t. The second is to define what pages can be returned for a given request using whitelisting. Another option is to convert file paths to absolute paths and make sure they’re referencing files in allowed directories.

Summary

Those are the top 10 issues that, if you aren’t careful to avoid, can allow your PHP application to be breached. Yep, 10. Count them… 1, 2, 3… What? You only counted 8? Okay, maybe 7. Well then that shows you just how easily you can be fooled, and I’m not even one of the bad guys!

Image via Fotolia

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.maccopacco.com maccopacco

    im gonna check for these vulnerabilities in my site, thanks again

    • Dave Shirey

      You’re welcome. Good luck.

  • Nand S

    Source Code Revelation; this shouldn’t be a vulnerability on PHP’s side, and to be quite honest it’t not really a vulnerability in it’s true essence – it’s a misconfiguration.
    The chances of Apache malfunctioning in this manner is next to zilch, the chances of the web server and/or Apache going down is of much greater concern.
    I can’t see how this is relevant, directory structures shouldn’t be used to hide things, they should be used to create a common layout to map files – much like Linux.

    • David Shirey

      You’re right – chances of this kind of failure are pretty remote. And maybe this item doesn’t deserve to be listed in a ‘top any number’ list. But I do think it’s a good idea not to make your config files too obvious. Thanks for the comment.

      • Bob

        “Source Code Revelation :it’s not really a vulnerability in it’s true essence”. I disagree. Misconfiguration or whatever, revealing source code makes an application vulnerable. Like most of the items listed, it’s not unique to php, so? Anyone should check that their application error messages or anything else don’t show code references, and importantly any php code should have the .php extension, not .inc meaning anyone can view the code if they know the url.

  • John Stevenson

    Regarding Remote File Inclusion, by setting allow_url_fopen to off you will disable the current functionality of Composer (http://getcomposer.org/)

    • david shirey

      Interesting. I did not know that although I don’t use Composer and so may sort of be forgiven. Definitely something to think about decision wise. Thanks!

      • John Stevenson

        No worries, and thanks for the article. Thinking about it, you would also be disabling the file_get_contents(), when used with a url.

  • http://alexfraundorf.com Alex Fraundorf

    Reading about security can be fun; this article proves it! Thanks for the great summary of items we should all be reminded of on a regular basis.

    • david shirey

      Thanks. I really appreciate that. If you thought this was fun you will definitely want to catch my next post. It’s all about the Black Death.

  • Fadhil

    Thanks for the article, but what you did you not explain is: Was leaving your novel unfinished good or bad? I also wondered which one is good for me? Spending more time in developing my script or finish it as soon as possible and go back to my writing, I decided to finish the script very soon and the security issues will be the last to finish

    • David Shirey

      You know I am not really sure. As for you, it’s hard to say. I guess it depends on how much pleasure or pain the writing brings you.

  • Redrazor

    Brilliantly written, very informative and a great job altogether. Thank you so much.

    • david Shirey

      Thanks. If I do ever finish my novel I will be contact you to write some reviews for the cover.

  • http://twitter.com/emptyprmises Jake

    I’m kind of surprised to not see the PHP ESAPI library mentioned here. Any chance of a follow-up article to introduce the crowd to the ESAPI?

    • David Shirey

      That is a good question. I will check with my handlers and see if this is something that we should do. Thanks.

  • Fadhil

    My comment wasn’t finished, perhaps because of input chars limit. I asked if it more safe to mask a URL like http://www.site.com/page.php?95034859.html to be ww.site.com/95034859.html or it is the same. Go ahead and restart you novel.. writing novels is a great pleasure.

  • shivasurya

    nice helpful!