Programming Forums
User Name Password Register
 

RSS Feed
FORUM INDEX | TODAY'S POSTS | UNANSWERED THREADS | ADVANCED SEARCH

Reply
 
Thread Tools Display Modes
Old Dec 10th, 2005, 1:16 PM   #1
Darkhack
Hobbyist Programmer
 
Darkhack's Avatar
 
Join Date: Dec 2005
Location: Kansas City
Posts: 105
Rep Power: 3 Darkhack is on a distinguished road
Send a message via AIM to Darkhack
Tutorial - PHP Security

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 = "&amp;"

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!
Darkhack is offline   Reply With Quote
Old Dec 10th, 2005, 6:09 PM   #2
Ooble
I eat cake for breakfast.
 
Ooble's Avatar
 
Join Date: Jul 2004
Location: In my box.
Posts: 4,434
Rep Power: 9 Ooble is on a distinguished road
Great tutorial. Couple things I'd forgotten in there - ta very much.
__________________
Me :: You :: Them
Ooble is offline   Reply With Quote
Old Dec 10th, 2005, 6:33 PM   #3
Intimidat0r
Hobbyist Programmer
 
Intimidat0r's Avatar
 
Join Date: May 2005
Location: Don't know, but the padded walls are a nice touch.
Posts: 126
Rep Power: 0 Intimidat0r is an unknown quantity at this point
Send a message via ICQ to Intimidat0r Send a message via AIM to Intimidat0r Send a message via MSN to Intimidat0r Send a message via Yahoo to Intimidat0r
nice job.

did you mention that people can also use sql injection with getvars? like

stuff.php?id=1
stuff.php?id=1' OR '1'

also, i have a question, is it possible to inject sql using cookies? like if they have

"SELECT * FROM users WHERE username='".$_COOKIE['username']."'"

you could change the value of the cookie to contain sql in it.

just a few pointers
__________________
Children in the dark cause accidents, and accidents in the dark cause children.

http://www.ronincoders.org
Intimidat0r is offline   Reply With Quote
Old Dec 10th, 2005, 6:50 PM   #4
Darkhack
Hobbyist Programmer
 
Darkhack's Avatar
 
Join Date: Dec 2005
Location: Kansas City
Posts: 105
Rep Power: 3 Darkhack is on a distinguished road
Send a message via AIM to Darkhack
Yes, you can use SQL injection through GET and Cookies. Pretty much anything. ALL information coming from the client that is going to be processed in a query should be put through some kind of filter such as the one I provided. My advice is if you are using cookies is when a user first visits a page to 1. pull the cookie. 2. filter it. 3. assign it to a session. I'm kinda bias, but I always find sessions to be easier to handle and once you've assigned a session you no longer have to worry so much about security as you would if you kept the cookie the whole way through; you would have to keep checking it.
Darkhack is offline   Reply With Quote
Old Dec 10th, 2005, 6:58 PM   #5
DaWei
Resident Grouch
 
DaWei's Avatar
 
Join Date: Jun 2005
Posts: 6,453
Rep Power: 10 DaWei is on a distinguished road
Quote:
A common (yet very unknown) flaw is the use of MySQL Injection.
Quote:
I've created a filter script that will cancel out any quotes or other things the user tries to enter.
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;
}
Your tutorials are very nice, knowledgeable, well-written, all that stuff. Nevertheless, you are leading novices to believe you have discovered or invented things that you have neither discovered nor invented. That's not nice.
__________________
Abstraction doesn't make it impossible to write bad code; it makes it possible to write superior code.
Contributor's Corner: Grumpy on C++ Exceptions DaWei on Pointers
DaWei is offline   Reply With Quote
Old Dec 10th, 2005, 7:11 PM   #6
Darkhack
Hobbyist Programmer
 
Darkhack's Avatar
 
Join Date: Dec 2005
Location: Kansas City
Posts: 105
Rep Power: 3 Darkhack is on a distinguished road
Send a message via AIM to Darkhack
To be honest SQL Injection is quite unknown. I find it a LOT in php code. Infact thats how I joined my school's website staff. I found a flaw in there login script which made it prone to SQL-Injection and no one on the team at the time had even heard of it. Also, I did create that script. Obviously, using common php functions but I did make it by knowing in advanced what needed to be removed and what needed to be checked to make sure text was properly formatted before use.

Sorry if I acted like I discovered or invented something new, because I havn't done anything that hasn't been done before. SQL-Injection is NOT new and neither is my code, although I did happen to write that paticular function though. But yes, NOTHING I wrote about in my tutorial is invented or discovered by me or anything like that. It's just a collection of information I've learned through various articles and things that I've coded.

Again my apologies. The last thing I want to do is try to take credit for something I did not do. Simply passing on the knowledge is my only intention.
Darkhack is offline   Reply With Quote
Old Dec 10th, 2005, 7:34 PM   #7
Arevos
Programming Guru
 
Arevos's Avatar
 
Join Date: Aug 2005
Location: England
Posts: 1,499
Rep Power: 5 Arevos is on a distinguished road
For PHP >= 4.3.0, it's recommended that for MySQL queries, the mysql_real_escape_string function is used. mysql_real_escape_string escapes a few more characters than addslashes does; I'm not sure how significant this is, but it seems like a good idea to use this function over addslashes.
Arevos is offline   Reply With Quote
Old Dec 10th, 2005, 7:58 PM   #8
Darkhack
Hobbyist Programmer
 
Darkhack's Avatar
 
Join Date: Dec 2005
Location: Kansas City
Posts: 105
Rep Power: 3 Darkhack is on a distinguished road
Send a message via AIM to Darkhack
Good find Arevos! I looked at the php.net page for mysql_real_escape_string and it does look to be a bit better than addslashes. Just remember to check the status of magic_quotes though. Sometimes programmers will assume a certain setting and if it should ever change it renders their script useless.

Truthfully though, it isnt critical that you use mysql_real_escape_string over the others. Although if your using a newer version of php, go for it! If not, don't sweat it, the important thing is that the quotes are escaped.

Nice find Arevos! ;-)
Darkhack is offline   Reply With Quote
Old Dec 10th, 2005, 11:34 PM   #9
Lich
Professional Programmer
 
Lich's Avatar
 
Join Date: May 2005
Location: Detroit
Posts: 254
Rep Power: 4 Lich is on a distinguished road
Send a message via AIM to Lich Send a message via MSN to Lich
Thanks a lot, this is a great reference point, the SQL injunction thing is always something that skips my mind
__________________
--John Cruz
Web Developer
www.cruzweb.net
Lich is offline   Reply With Quote
Old Dec 11th, 2005, 5:24 PM   #10
Ooble
I eat cake for breakfast.
 
Ooble's Avatar
 
Join Date: Jul 2004
Location: In my box.
Posts: 4,434
Rep Power: 9 Ooble is on a distinguished road
You also need to backslash-out hyphens, as -- is a comment marker in SQL:
SELECT * FROM mytable; -- this is a comment
In the following code, the password check is commented out, letting people log on as anyone, as long as they know their username.
Username: me' --
Password: lalala
mysql_query("SELECT userid FROM users WHERE username = '$username' AND password = '$password'");
// SELECT userid FROM user WHERE username = 'me' --' AND password = 'lalala'
__________________
Me :: You :: Them
Ooble is offline   Reply With Quote
Reply

Bookmarks

« Previous Thread in Forum | Next Thread in Forum »

Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump




DaniWeb IT Discussion Community
All times are GMT -5. The time now is 12:32 AM.

Powered by vBulletin® Version 3.7.0, Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Copyright ©2007 DaniWeb® LLC