tags:

views:

548

answers:

16

I just starting out learning PHP, I've been developing web apps in ASP.Net for a long while. I was wondering if there are any PHP specific security mistakes that I should be looking out for.

So, my question is what are the top security tips that every PHP developer should know.

Please keep it to one tip per answer so people can vote up down effectively.

+7  A: 

here is a link of good PHP security programming practices.

http://phpsec.org/

Most of the security issues revolve around user input (naturally) and making sure they don't screw you over. Always make sure you validate your input.

http://htmlfixit.com/cgi-tutes/tutorial_PHP_Security_Issues.php

Robert Greiner
Very nice. You can read a security guide in english, french, romania and serbian.
Luc M
Question: has phpsec.org produced anything lately? (2008,9)
dimitris mistriotis
+11  A: 

Avoid using register_globals

Greg
Not hard, its disabled by default and being removed in PHP6.
Rook
+1  A: 

Most of the security issues related to PHP come from using unparsed "outside" (GET/POST/COOKIE) variables. People put that kind of data directly into file paths or sql queries, resulting in file leakage or sql injections.

leafnode
+4  A: 

If you're using a mysql database make sure you call mysql_real_escape_string when sending data to the database

David Archer
Interesting name, was there a mysql_imaginary_escape_string function at some point?
Martin Brown
mysql_phantasmal_escapist_wormhole was deprecated, if that's what you're thinking of ...
Smandoli
+2  A: 

Have a look at the Suhosin Hardening Patch, and check out the security vulnerabilities that it addresses.

karim79
A: 

Often introductory tutorials don't talk at all about checking data from users. Like all programming environments, never trust the data you get from users. Learn to use functions like is_numeric(), isset(), and mysql_real_escape_string() to protect your system.

There are also features that allow you to access remote files, and other creative things. I'd avoid those until you have a good understand of how and when they work (often they are disabled for security reasons).

acrosman
+1  A: 

OWASP provides a lot of insight into security issues that are the biggest problems in applications today. It is nice to see that they have a PHP dedicated page available

http://www.owasp.org/index.php/PHP_Top_5

shambleh
+5  A: 

don't use "Register Global Variables" and filter user input for xss and injections

antpaw
+5  A: 

Language Vs Programmer. You can write the most serious vulnerability and you won't get a warning or error message. Vulnerabilities can be as simple as adding or removing 2 characters in your code. There are hundreds of different types of vulnerabilities that affect PHP applications. Most people think of XSS and Sql Injection because they are the most popular.

Read the OWASP top 10.

Rook
+6  A: 
  1. Always sanitize and validate data passed from the page
  2. In conjunction with #1, always properly escape your output
  3. Always turn display_errors off in production
  4. If using a DB backend use a driver that supports/emulates prepared statements and use without prejudice :-)
prodigitalson
XSRF has nothing to do with escaping. If you do everything on this list you'll can still get hacked to tears.
Rook
@Michael: I didnt say this was the be all end all of the list nor did specifically mention anything about XSRF. In fact every recommend on this list up until now has good info and cautionings.
prodigitalson
Yeah you won some points in my book for parametrized quires. But every answer for this question is far too simplistic. Its really bugs me that all people think about is xss and sqli.
Rook
+5  A: 
  • Cross Site Scripting (XSS) Wiki, Google
  • Cross Site Request Forgery (XSRF/CSRF) Wiki, Google (thanks Rook)
  • SQL Injection (SQLi) Wiki, Google
  • Turn off error messages in Production environments
  • Keep any "include" code in a directory that is not web-accessible (either deny access or keep it outside of the webroot)
  • Here's an article I wrote about storing passwords in a secure way, and if you don't feel like taking my word for it, check the links at the bottom.
  • Also linked in my article, but given its own separate link here, is a paper published by M.I.T. called The DOs and DON'Ts of Client Authentication on the Web [PDF]. While some of its info (recommendation to use MD5 hash, for one) is somewhat out of date simply because of what-we-know-now versus what-we-knew-then, the overall principles are very strong and should be considered.
  • One of Rooks' links reminded me of another important set of restrictions
  • Since I've now mentioned him twice, check out Rooks's Answer (http://stackoverflow.com/questions/2275771/what-are-the-most-important-safety-precautions-that-a-php-developer-needs-to-know#2275788) as it includes a link to a document which contains (Non-PHP-Specific) information on the most important security concerns (and this therefore probably the right answer).
Dereleased
-1 for md5 used in passwords. Overly simplistic answer, and session fixation isn't an issue if you use session_start(). but you just linked to google like a troll.
Rook
@Michael, Where did I ever recommend using MD5 for anything ever? More importantly, given the myriad of potential problems that can arise, what would be more worthwhile, me trying to reproduce hundreds of documents and thousands of man-years worth of research in one SO answer, or linking to enough resources to get you started with the right keywords? Furthermore, I also link to a huge hand-written article that I wrote, as well as an M.I.T. paper on Client Authentication, since they are more specific sources than just google for their respective topics.
Dereleased
Just read something you said: session fixation isn't an issue if you use `session_start()`? Do you know how PHP's session model works? That is PRECISELY the problem with it. Maybe you were thinking of `session_regenerate_id()`? Although, that also introduces Race Conditions in environments where multiple requests may be firing at once (AJAX, for one). I challenge that your suggestion to "just use `session_start()`" is the 'Overly Simplified' answer of the week in terms of PHP security!
Dereleased
Your password storage model is defiantly wrong. Blowfish is really old, use twofish. Block ciphers shouldn't be used for passwords its a violation of CWE-257 http://cwe.mitre.org/data/definitions/257.html.Currently the only NIST certified message digest function for passwords is the sha2 family. Sha256 is a good choice.
Rook
If you think session_start() has a problem with session fixation then you should post it to Bugtraq.
Rook
PHP's crypt, so far as I know, actually uses Eksblowfish, developed in 1999, which allows for scaling with Moore's law. One can literally decide the order of magnitude which determines the expense of the keys generated, whereas Sha256 can be computed hundreds of thousands of times per second. Who does this benefit? I am also still wondering where I recommended the use of MD5 (which is anathema to security)?
Dereleased
It isn't that `session_start()` is inherently weak, it's that session IDs can be "fixated" in various ways (querystring, post parameters, or if you can control cookies), which can give a malicious attacker complete access to an authenticated system. Taking steps to prevent this (e.g., disallowing sesison IDs to be set by POST and GET, rotating session IDs on certain events such as login and purchase) are simple ways to prevent this sort of attack. My question is, in what world is `session_start()` with no other Session Fixation protections considered adequate protection?
Dereleased
I don't think you realize how large sha256 is. Do you have any applications written that uses this password function? Because if you do I'll just go ahead a report the CWE violation and collect a new CVE number. How many exploits have you written? Here are a few of mine: http://milw0rm.com/author/677 .
Rook
I took away the -1. You are trying and you know a whole lot more about secuirty than the average developer. But, I still think you should conform to basic secuirty standards.
Rook
I'd say 256 bits, or 64 bytes if represented as base16. Versus an Eksblowfish hash which is 192 bits, or 32 bytes if represented as base64. I assume you're warning against potential collisions? That's why we don't use MD5/Sha1. If System A (Sha256) can generate 150,000 keys per second, and System B (Eksb) can generate about 80 per second, which is going to be easier to attack? No matter where you try to generate the Eksblowfish key, it will always be just as expensive, and when computing power scales up, you can scale up the key generation expense with it, without invalidating old keys.
Dereleased
Well, I think I've laid out my views pretty clean, but I'd like to take the time to say that I know I don't know everything, and while I'm defending my position I'm going to be looking in to what you've said, because if I'm wrong I need to know now. If you have any other links about why we should use Sha256 over Eksblowfish then I would be very appreciative.
Dereleased
I suspect that Michael Brooks' objections stem primarily from your statement that you should use Blowfish (the reversible block cipher) for password storage, but your later comments on it (particularly with respect to the speed/scaling aspects) make it clear that you actually mean bcrypt (the non-reversible hashing algorithm based on construction of Blowfish frames). Although closely related, Blowfish and bcrypt are not the same thing and he's right that, as a reversible cipher, Blowfish should not be used for password storage. But +1 for endorsing bcrypt, even if you did get the name wrong.
Dave Sherohman
Wow, @Dreleaded. I'm glad we came to an understanding. Actually it is a common misconception that hash functions should be slow. In fact when NIST is selecting a new hash function speed is a very important consideration, faster algorithms score more points and are more likely to be selected. The point is trying to reverse the hash is supposed to take a very long time. A Block Cipher like blowfish *can* be used as a hash function and is therefore keyless. On old *nix systems tri-des is used as a hash function to store passwords.
Rook
@Dreleaded I have another link for you. A lot can go wrong with password storage. Here are the official guidelines: http://cwe.mitre.org/data/definitions/255.html
Rook
Dave, Thanks! I understand the objection now, and the link Michael presented makes much, much more sense. No, I am not advocating the use of a reversible scheme, as that is of course worse than MD5. Thanks, by the way, for taking as much time as you did to make sure I wasn't making a royal mess of things. As I said I will be "back on the prowl" to make sure there isn't any information I missed. And again, thanks for your strict concern, it is very much needed, and hopefully appreciated, in this community.
Dereleased
+3  A: 

There are tons of safety precautions. I can recommend a book Chris Shiflett: PHP and Web Application Security.

http://phpsecurity.org/

Sam Dark
+2  A: 

The PHPSec Guide gives a good overview.

Wim
+5  A: 

(In no particular order)

  1. Always check that register globals are OFF
  2. Always check that magic quotes are OFF
  3. Make sure you understand SQL injection attacks
  4. Turn OFF error reporting in production

EDIT: For the "newbies" out there this is a basic why (and since I have time to explain this):

  1. Register globals is an aberration. It's the ultimate security hole ever. For example, if register_globals is on, the url http://www.yourdomain.com/foo.php?isAdmin=1 will declare $isAdmin as a global variable with no code required. I don't know why this "feature" has made it's way to PHP, but the people behing this should have the following tattooed on their forehead: "I invented PHP Register Globals" so we can flee them like pest when we see them!

  2. Magic quotes is another dumb idea that has made it's way to PHP. Basically, when ON PHP will escape quotes automatically (' become \' and " become \") to help with SQL injection attacks. The concept is not bad (help avoid injection attacks), but escaping all GET, POST and COOKIE values make your code so much complex (for example, have to unescape everytime when displaying and data). Plus if one day you switch this setting OFF without doing any change to your code, all your code and/or data is broken and (even more) vulnerable to injection attacks (yes even when ON you are vulnerable).

  3. Your databse data is your most valuable thing on your site. You don't want people to mess with it, so protect yourself and read things about it and code with this in mind.

  4. Again this can lead to security concerns. The error message can give hints to hackes on how your code works. Also these messages don't mean anything to your visitors, so why sow them?

AlexV
A: 
  1. Always Close you SQL Connection.
  2. Always Release SQL results.
  3. Always Scrub all variables your putting into a database.
  4. When deleteing or dropping from sql use limit 1 just in case.
  5. When developing make sure you have a lock on things to keep the undesirable out. If its open and you know not to load the page right now because it could break something, doesn't mean other people do.
  6. Never use Admin or Root as your server log in name.
Iscariot
A: 

Whenever possible, use prepared statements (tutorial. It's almost a must whenever dealing with user input (I say "almost" because there are a few use cases where they don't work), and even when not dealing with input, they keep you in the habit. Not to mention they can lead to better performance, and are a LOT easier, once you get into the swing of things, than piecemeal sanitizing.

GeminiDomino