PHP MySQL $_GET Hack prevention
Solution 1
The first and foremost rule with ANY input, not just $_GET but even with $_POST, $_FILES and anything you read from disk or from a stream you should always VALIDATE.
Now to answer your question in more details, you have several HACKS that exist in this world. Let me show you some:
XSS injections
If you accept data from the URL such as from the $_GET and output this data without stripping out possible tags, you might render your site prone to XSS injection or code injection. For example:
http://myhoturl.com/?search=<script>window.location.href="http://thisisahack.com/"</script>
This would output a hack to your site and people would be redirected to another page. This page could be a phishing attempt to steal credentials
SQL Injection
It is possible to inject SQL to your application. For example:
http://myhoturl.com/?search=%'; UPDATE users SET password=MD5('hello'); SELECT * FROM users WHERE username LIKE '%
Would make your SQL look like this:
SELECT * FROM articles WHERE title LIKE '%%'; UPDATE users SET password=MD5('hello'); SELECT * FROM users WHERE username LIKE '%%';
And thus you'd update all your user's password to Hello and then return something that doesn't match.
This is only a brief overview of what you can do with SQL injection. To protect yourself, use mysql_real_escape_string or PDO or any good DB abstraction layer.
Code injection
Lots of people like to include data from somewhere on the disk and allow uploads of files. For example:
//File igotuploaded.txt
<?php echo 'helloworld'; ?>
And the url allows you to INCLUDE a file by name. ?show=myhotfile.txt
//In this file we include myhotfile.txt
include($_GET['show']);
The person changes that to ?show=../uploads/igotuploaded.txt and you will run echo 'Hello world';
That is dangerous.
rule of thumb... NEVER TRUST USER INPUT, always validate, prevent, validate, fix, validate and again correct...
Good luck
Solution 2
That totally depends on what you are going to do with it:
- MySQL: mysql_real_escape_string / PDO / mysqli
- html: htmlspecialchars
- etc.
Without knowing what you are going to do with your data, it is impossible to say what would make it safe.
Solution 3
The two greatest risks you face when using user input (any HTTP request counts as user input) are:
- SQL Injection
- Cross-Site Scripting
You should get familiar with the risks and the defenses. The defenses for each of these threats are different. Using addslashes() is not a complete defense.
A great resource for learning more about secure web programming is the OWASP Top Ten project.
I've done a presentation about SQL Injection Myths and Fallacies that I hope is helpful for you.
Comments
-
Albert Renshaw almost 2 years
Possible Duplicate:
Best way to stop SQL Injection in PHPIf I were to use the $_GET function to retrieve a variable from the URL how can I make it hack proof? Right now I just have addSlashes, what else should I add?
$variable1 = addslashes($_GET['variable1']); //www.xxxxx.com/GetTest.php?variable1=xxxx
-
kba over 12 years-1.
mysql_real_escape_string()
doesn't always prevent injections. This might give OP the idea that if he just escapes input, he won't ever have to worry about SQL injections. -
Albert Renshaw over 12 yearsLet's say I was using it the way the person below stated it (I don't currently have a specific use I'm just trying to learn so when I do decide to use get in the future I will use it safely... Anyways, let's say: mysql_query("SELECT userid FROM user WHERE password='".$_GET["variable1"]."';");
-
Albert Renshaw over 12 yearsmysql_real_escape_string is good! Also, what other ways are common means of prevention Kristian Antonsen?
-
Albert Renshaw over 12 yearsSo how can I make it so my php script will ignore SQL queries that are retrieved via $_get? Thanks for all the examples too!
-
Dion over 12 yearsPasswords you should generally don't read from GET-Variables. Use a password field in POST Form (HTML) instead. And passwords should always be md5()-secured. (For a password you would only need
mysql_real_escape_string();
because you won't print it out. -
Mathieu Dumoulin over 12 yearsmysql_real_escape_string or if you use PDO or a good DB layer it usually does it for you...
-
Albert Renshaw over 12 yearsOkay great! Now what about something like viewing a user's profile page and it wasn't a password just an number... like 54038. And I was retrieving and displaying all table entries where that user's number was in a field called "userID" What type of injection could be harmful there and how could I prevent it?
-
kba over 12 years@AlbertRenshaw
mysql_real_escape_string()
only escapes ticks, quotation marks and the like. Assuming there are none, it isn't helpful at all. An example is withLIMIT 10, $page
for pagination. If$page
contains1; DROP TABLE tbl --
, escaping wouldn't help a bit. Always validate your input and make sure you have the right value (e.g.is_numeric
andintval
). -
Albert Renshaw over 12 yearsI noticed in another user's comment they said "XSS injection" does that stand for Cross Site Scripting Injection?
-
jeroen over 12 years@Albert Renshaw You have to know your data, if a field is supposed to be an integer, you'd best cast it to an integer:
(int) $_GET['...']
. -
Albert Renshaw over 12 yearsWhat is the intuition behind "' OR 1=1 --"? I've seen this statement (or one similar) written before on hack prevention articles.. It makes an error via logic right? Does this intern display an error message with sensitive info?
-
Albert Renshaw over 12 yearsis_numeric! Wow! That is great! Ahhh, that is nice! Thankyou! That will help a lot with thing like page numbers! Sweet! Thankyou! +1
-
Albert Renshaw over 12 yearsWhat is "PDO" What does it stand for and how do I use it? I've seen this coming up a lot! Thanks again for all the help so far!
-
kba over 12 years@AlbertRenshaw No, it makes no error it just returns true. Consider a bad login system,
SELECT username FROM tbl WHERE username='$user' AND password='$pass'
. If $pass is' OR 1=1 --
, the query would beSELECT username FROM tbl WHERE username='$user' AND password='' OR 1=1 --'
, thus return the username and lead the application to believe the correct password was entered. -
Albert Renshaw over 12 yearsThat's great advice! Is there anything to make it AlphaNumeric values only?
-
Albert Renshaw over 12 yearsSo something like <b><center>hello</center></b> would just show up as "bcenterhellocenterb" Also, I think I recall something about stripping off just html tags so it will just show up as "hello", how do I do that?
-
jeroen over 12 years@Albert Renshaw You'd probably have to resort to regular expressions like
[\w\d]+
but if you get stuck there, you'd better ask a more specific question on SO. -
jeroen over 12 years@Albert Renshaw
strip_tags($string)
-
Mathieu Dumoulin over 12 yearsphp.net/manual/fr/book.pdo.php - PHP Data Objects
-
Albert Renshaw over 12 yearsOhhhhh!!! That makes much more sense! Okay, thats good advice, so mysql_real_escape_string(); will prevent this type of hacking?
-
Albert Renshaw over 12 yearsAnd does "XSS" stand for Cross Site Scripting? I saw that in another user's response.
-
Mathieu Dumoulin over 12 yearsYes, XSS is Cross Site Scripting
-
Albert Renshaw over 12 yearsAlso, for future reference of other clueless people like me. (found this with google) if you are trying to use the function Kristian gave, "intval();" and you have a number but it isn't an integer (e.g 4.389) intval will return 4, but if you want to keep the full numeric value but still strip away things like letters and SQL queries you can use "floatval();"
-
Bill Karwin over 12 yearsYes, XSS is a popular abbreviation for Cross Site Scripting.
-
Bill Karwin over 12 yearsFor proper password security, be sure to read You're Probably Storing Passwords Incorrectly.
-
Bill Karwin over 12 yearsFor filtering in PHP, check out php.net/filter
-
kba over 12 yearsNo, all
mysql_real_escape_string()
does is that it replaces ' with \', etc., so input cannot break encapsulation.'foo \' bar'
won't cause an error, but'foo ' bar'
will. And yes,intval
only returns 4 - obviously it returns the INTeger value, not the floating point value. :) -
Luc Laverdure over 12 yearsI didn't take the time to make this post elaborate, but seeing all the comments, yes, mysql_real_escape_string() will prevent all SQL injections within a string only, for numeric values, you should verify with is_numeric() before executing mysql_query().