Security is a big concern for any webmaster. However some people don't realize how much of a security risk php can really be. I've even seen some people be able to take over an entire system through php because of a critical flaw that someone didn't think through very well. I'm going to list some tips and fixes so that your php code will be much more secure!
1. Never include/require a page based on user input. The only exception to this is if you are using an if-else checking mechanism and the pages being opened are statically assigned.
2. Never use eval(), its basically the equilvent of System() for C++ programmers and allows you to run any command you want. Even if its use is always the same and unchangable, there should be no reason to use it, unless of course you want to be able to control an entire system through php. But in all honesty if your doing that you'd better make sure everything else is secure and quite truthfully, you should be using something like ssh instead of php.
3. Always check your forms. If your using a page that accesses a database such as MySQL you need to check the users input. A common (yet very unknown) flaw is the use of MySQL Injection. Take a login system for instance. Lets see how it would work normally...
username: Joe
password: Smith
-----------------------------
<?php
mysql_query("SELECT * FROM accounts WHERE username='{$user}' && password='{$pass}'");
?>
Now lets substitute the variables with the user input and see how it looks...
mysql_query("SELECT * FROM accounts WHERE username='Joe' && password='Smith'");
Seems ok... but now lets alter our username and password that our user enters. Suppose they enter something different? What will our new query look like then?
username: Admin
password: ' OR 'K'='K
------------------------------
mysql_query("SELECT * FROM accounts WHERE username='Admin' && password='' OR 'K'='K' ");
Doesn't look too good now does it? When a user enters in input thats going into a query it is basically directly substituted. By cancelling out the original quote and providing the K=K scenerio, the query will always be true. We simply enter a target username that we know exists and if we dont know the screenname at all, we simply use the K=K trick that we did on our password. You might have seen this same trick done on other sites with 1=1. That might work some of the time but if you test it out you'll see that you still have an extra quote to deal with. By using K=K but leaving off the end quote in our input, we have a valid statement.
Thankfully there is a fix for it!! I've created a filter script that will cancel out any quotes or other things the user tries to enter. It will also remove any html tags. Always run your input through this script before putting it, or checking it against an SQL query.
function apiFilter($filterString)
{
$filterString = trim($filterString);
$filterString = strip_tags($filterString);
$filterString = htmlspecialchars($filterString);
// check for magic_quotes prior to adding more slashes
if ( !get_magic_quotes_gpc() )
$filterString = addslashes($filterString);
return $filterString;
}
4. On secure pages be sure to validate the login EVERY time. Here is a common error made by beginners.
if($username == "Joe" && password="Smith")
$admin = true;
.... *later* ....
if($admin)
DisplayCP();
Not very secure at all. All one would have to do is find the admin url and simply do... admin.php?admin=true;
5. MD5 your passwords. If you or someone on your web-dev team should happen to forget to run the apiFilter script that I gave on some input and someone does manage to bypass your database, don't let them ruin your entire online life. MD5'ed passwords mean very little to anyone. If your passwords aren't encrypted at all, then you risk someone trying out those passwords on your email or IM accounts and such. Although one would use a different password for each and every service they sign up for, I think we can all say that there has been a time or two where our lazy minds simply couldnt remember another password and we used one that we were using somewhere else. I too am guilty of this. When I remember, I change my passwords and come up with new ones.
6. Always be extremely careful with upload scripts. If possible don't use them, but sometimes you simply do need one. Always check the file extension. Either read the string backwords or look for the last occurence of a dot/period. do NOT except the first thing that comes along. This is what leads users to upload crap like "CutePetPicture.jpg.exe".
7. Some of you using flat-file databases might be snickering at the long tip about SQL security. Don't get to smart yet! Be sure that your flat file databases can't be changed or renamed and accessed through any part of your code and be seen by the user. Just use your brain when working with any kind of file or database. We don't wont some faulty input to have our entire database file be echoed back to the user.
8. Not really an issue but I would recommend removing phpsessid from the url. its ugly and more importantly its almost never needs to be seen by the end user and the number one reason to do it is that it can cause compatibility problems with xhtml and they wont validate correctly. Add these two lines at the very top of your page (or edit the php.ini file if you have access to it.)
ini_set("url_rewriter.tags","");
ini_set("session.use_trans_sid", false);
OR... if you NEED to have phpsessid in the URL yet still want xhtml compatibility then alter your php.ini file like so...
arg_separator.output = "&"
Well thats about all. I am sure there is a bunch of other things you need to remember as well, but this covers the major stuff atleast. If there is something I missed please let me know. I dont know a whole lot about session or cookie security simply because there is just so much to know, so please see
PHP: Sessions. Also I sometime make mistakes. If I said something that was completely wrong or you disagree with me, let me know. Sometimes I simply get off track without realizing it or make a typo like forgetting to leave out the word "not" (very bad thing to do). :o
Thanks again!