34

I just starting out learning PHP, I've been developing web apps in ASP.Net for a long time. 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.

Script47
  • 14,230
  • 4
  • 45
  • 66
Martin Brown
  • 24,692
  • 14
  • 77
  • 122

18 Answers18

17

(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 behind 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 show them?

Script47
  • 14,230
  • 4
  • 45
  • 66
AlexV
  • 22,658
  • 18
  • 85
  • 122
16

Avoid using register_globals.

Warning: This feature has been DEPRECATED as of PHP 5.3.0 and REMOVED as of PHP 5.4.0.

Script47
  • 14,230
  • 4
  • 45
  • 66
Greg
  • 316,276
  • 54
  • 369
  • 333
12
Community
  • 1
  • 1
Dereleased
  • 9,939
  • 3
  • 35
  • 51
  • -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 Feb 16 '10 at 19:55
  • 1
    @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 Feb 16 '10 at 19:59
  • 1
    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 Feb 16 '10 at 20:01
  • 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 Feb 16 '10 at 20:04
  • If you think session_start() has a problem with session fixation then you should post it to Bugtraq. – rook Feb 16 '10 at 20:08
  • 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 Feb 16 '10 at 20:12
  • 1
    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 Feb 16 '10 at 20:15
  • 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 Feb 16 '10 at 20:16
  • 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 Feb 16 '10 at 20:21
  • 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 Feb 16 '10 at 20:23
  • 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 Feb 16 '10 at 20:25
  • 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 Feb 16 '10 at 20:37
  • 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 Feb 16 '10 at 20:40
  • @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 Feb 16 '10 at 20:44
  • 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 Feb 16 '10 at 20:49
8

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
  • 29,049
  • 9
  • 65
  • 85
7
  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
  • 60,050
  • 10
  • 100
  • 114
  • 1
    XSRF has nothing to do with escaping. If you do everything on this list you'll can still get hacked to tears. – rook Feb 16 '10 at 19:49
  • @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 Feb 16 '10 at 19:50
  • 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 Feb 16 '10 at 19:53
5

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

antpaw
  • 15,444
  • 11
  • 59
  • 88
5

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
  • 66,304
  • 38
  • 162
  • 239
4

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

Dave Archer
  • 3,022
  • 20
  • 23
3

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

http://phpsecurity.org/

Sam Dark
  • 5,291
  • 1
  • 34
  • 52
2

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

karim79
  • 339,989
  • 67
  • 413
  • 406
2

The PHPSec Guide gives a good overview.

Wim
  • 11,091
  • 41
  • 58
1

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
  • 1,382
  • 7
  • 15
1

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

Steven
  • 3,813
  • 2
  • 22
  • 27
1
  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.
Case
  • 4,244
  • 5
  • 35
  • 53
1

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
  • 451
  • 1
  • 5
  • 19
0

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
  • 12,814
  • 10
  • 39
  • 55
  • is_numeric() should not be used because values like `1.234` will slip through, which is almost always not what you want since you are going to use those values in an SQL query most of the time. Instead, see [this](https://stackoverflow.com/questions/6416763/checking-if-a-variable-is-an-integer-in-php#answer-29018655) answer. – doubleOrt Jul 09 '17 at 19:52
-1

Use POST method for data passing from one page to another.

Use trim while getting data like trim($_POST). Also, use strip_tags for variables before you passing into the queries.

I am suggesting you use any framework link Codeigniter, Laravel, YII, Cake PHP because they maid framework with all securities

I suggest Codeigniter for small projects and Laravel for big projects.

-2

Always use POST and not GET for important Data...

Milan
  • 97
  • 1
  • 12