![]() |
![]() |
![]() |
||||
Welcome to the GoFuckYourself.com - Adult Webmaster Forum forums. You are currently viewing our boards as a guest which gives you limited access to view most discussions and access our other features. By joining our free community you will have access to post topics, communicate privately with other members (PM), respond to polls, upload content and access many other special features. Registration is fast, simple and absolutely free so please, join our community today! If you have any problems with the registration process or your account login, please contact us. |
![]() ![]() |
|
Discuss what's fucking going on, and which programs are best and worst. One-time "program" announcements from "established" webmasters are allowed. |
|
Thread Tools |
![]() |
#1 |
Confirmed User
Join Date: Aug 2002
Posts: 1,844
|
![]() hi
i've got some old mainstream sites that were getting hacked with sql injection (only turkish script kiddies), as a temporary measure i removed some functionality of the site to prevent it happening again. i want to get the sites working properly again. i found this code snippet while i was searching for a solution, is this all i need to prevent an sql injection attack using post or get happening again? Code:
//This stops SQL Injection in POST vars foreach ($_POST as $key => $value) { $_POST[$key] = mysql_real_escape_string($value); } //This stops SQL Injection in GET vars foreach ($_GET as $key => $value) { $_GET[$key] = mysql_real_escape_string($value); } thanks in advance |
![]() |
![]() ![]() ![]() ![]() ![]() |
![]() |
#2 |
Too lazy to set a custom title
Industry Role:
Join Date: May 2004
Location: West Coast, Canada.
Posts: 10,217
|
Yes, that will help. However, all the values should be validated if you want to stop all potential issues as it will also depend on how the sql statements are done.
You want to do something like this on the post values. And I think it needs to be done after you're connected to the database for mysql_real_escape_string to work. Code:
foreach($_POST as $key => $val){ if( is_array($val) ){ for($i = 0; $i < count($val); $i++){ $_POST[$key][$i] = mysql_real_escape_string(get_magic_quotes_gpc() ? stripslashes($val[$i]) : $val[$i]); } }else{ $_POST[$key] = mysql_real_escape_string(get_magic_quotes_gpc() ? stripslashes($val) : $val); } } |
![]() |
![]() ![]() ![]() ![]() ![]() |
![]() |
#3 |
Confirmed User
Industry Role:
Join Date: Aug 2001
Posts: 832
|
Using mysql_real_escape_string() is a good start but it is far from being enough. Next you should make sure that you use ' around all values in SQL, both strings and numbers. Remove words such as UNION, SELECT, DROP, LOAD, BENCHMARK # -- /* and so on.
There are so many possible ways of injection that it is close to impossible to make it really bulletproof. You should make a read-only SQL user with only read rights (for that particular database) which you use for your SELECT statements. Never use the root mysql user. Then have one user with write-only rights for UPDATE. Delete-only for DELETE. etc If you are even more paranoid you could lock certain SQL commands to certain tables to mitigate the potential damage. Doing this approach with multiple sql-connections can be difficult on premade scripts. I am sure there are many more things to do. But for sure you are not protected if you only rely on that PHP code. Maybe someone else can chime in with more and better suggestions. ![]() |
![]() |
![]() ![]() ![]() ![]() ![]() |
![]() |
#4 | |
Confirmed User
Join Date: Jun 2009
Location: Asheville, NC
Posts: 2,277
|
Quote:
e.g. You have pagination that uses GET parameters like: /models?page=1&hair=blue While the user may not have had the option of typing in "blue" they could still override the GET param with some sort of SQL injection string... so it needs to be escaped. The proper solution... and here is why the MVC Model/View/Controller design pattern is so damned handy ;) is to escape each field being queried for or updated using the aforementioned real escape string function/method. If your code base is MVC your Model (the database) logic will be split out so adding in this check for each field should be simple. If you're using something procedural or even OO and the Model is not split out correctly you'll be doing a LOT of search/replace action to find every place one of the queries is done and escape each individual field... I WOULD NOT recommend doing something on every POST field unless each field is not used anywhere else in the code base. Otherwise you'll end up with lots of issues with variables no longer matching was was expected... Imagine $modelName="April O'niel" vs = "April O\'Neil"... Long story short it can either be a huge pain in the ass or not that big of a deal depending on the competency level of the developer who originally wrote the script :P Hope that helps clarify that a bit for you ;)
__________________
ICQ: 258-202-811 | Email: eric{at}bestxxxporn.com |
|
![]() |
![]() ![]() ![]() ![]() ![]() |
![]() |
#5 | |
Confirmed User
Join Date: Jun 2009
Location: Asheville, NC
Posts: 2,277
|
Quote:
Best practices dictate a MySQL user should ONLY have the finite privileges it requires. All other privileges should be revoked for that user. Those privileges should also only apply to the DB(s) that user needs to access (they should not be global privileges).
__________________
ICQ: 258-202-811 | Email: eric{at}bestxxxporn.com |
|
![]() |
![]() ![]() ![]() ![]() ![]() |
![]() |
#6 |
Confirmed User
Industry Role:
Join Date: Aug 2001
Posts: 832
|
You should sanitize $_GET, $_POST and $_COOKIE and also be paranoid about values from HTTP Headers (if you use them in SQL, for example HTTP_REFERER)
Good luck ;) |
![]() |
![]() ![]() ![]() ![]() ![]() |
![]() |
#7 |
Confirmed User
Industry Role:
Join Date: Aug 2001
Posts: 832
|
And one more thing, make sure that neither PHP nor MySQL is allowed to give error messages. No error message should be sent to the screen. It makes it harder for the attacker to see what he is doing as he will have to operate blindly.
|
![]() |
![]() ![]() ![]() ![]() ![]() |
![]() |
#8 |
Confirmed User
Industry Role:
Join Date: Aug 2001
Posts: 832
|
![]() You can also move some of the logic to PHP instead of MySQL. For example you can compare values in PHP arrays instead of sending them to MySQL.
SQL for authentication (unsafe) Code:
SELECT 1 FROM users WHERE username='$username' AND password='$password' SQL to preload PHP array Code:
SELECT username, password FROM users Code:
if ($passwords[$username] == $password){ return true; } else { return false; } unset($passwords); ![]() |
![]() |
![]() ![]() ![]() ![]() ![]() |
![]() |
#10 | |
Confirmed User
Industry Role:
Join Date: Jun 2004
Location: New York, NY
Posts: 6,890
|
Quote:
Also for putting quotes around integers, that is not a great idea either. While MySQL has advanced to the point it doesn't make a huge speed difference anymore, it still does slow-down queries on extremely large tables or involving complex joins and it still slows queries down quite a bit in PostgreSQL. The proper thing to do would just be to properly sanitize all variables that are involved in your queries. If everything is sanitized, there will be no injection. For example, instead of putting quotes around an integer like age, you can verify it's of the proper type and within a specific range. The rest of your advice I can agree with though ![]()
__________________
Skype variuscr - Email varius AT gmail |
|
![]() |
![]() ![]() ![]() ![]() ![]() |
![]() |
#11 | |
Confirmed User
Industry Role:
Join Date: Aug 2001
Posts: 832
|
Quote:
|
|
![]() |
![]() ![]() ![]() ![]() ![]() |
![]() |
#12 |
Confirmed User
Industry Role:
Join Date: Aug 2001
Posts: 832
|
Oh, I almost forgot one important thing.
MySQL accepts both ASCII and HEX values. Someone could write their payload as 0x6e6f7468696e67206865726520746f20736565 That string could contain anything... Such strings could possibly go undetected by type-validation as all the ASCII chars look harmless. Making proper sanitation is really hard, and there is always the risk that you have missed something. In my opinion one should be extra paranoid with databases. They are like Swiss cheese.. |
![]() |
![]() ![]() ![]() ![]() ![]() |
![]() |
#13 |
Too lazy to set a custom title
Join Date: Mar 2002
Location: Australia
Posts: 17,393
|
Quick tip: if the value you're expecting should be an integer, you can force PHP to treat it as such like this:
$val = 0 + $_POST["variable"]; |
![]() |
![]() ![]() ![]() ![]() ![]() |
![]() |
#14 | |
Confirmed User
Join Date: Jun 2009
Location: Asheville, NC
Posts: 2,277
|
Quote:
$val = intval($_POST['variable']); And always use single quotes unless you need special escaped chars... Every time you use double quotes for a string in PHP you cause the string interpreter to parse the entire string looking for variables, special chars, etc... Using single quotes instead ensures that doesn't happen... ![]()
__________________
ICQ: 258-202-811 | Email: eric{at}bestxxxporn.com |
|
![]() |
![]() ![]() ![]() ![]() ![]() |
![]() |
#15 |
So Fucking Banned
Industry Role:
Join Date: Sep 2009
Posts: 1,732
|
if you use wordpress, this is prevented by default on their CMS.
. |
![]() |
![]() ![]() ![]() ![]() ![]() |
![]() |
#16 | |
Too lazy to set a custom title
Industry Role:
Join Date: May 2004
Location: West Coast, Canada.
Posts: 10,217
|
Quote:
As for the int thing, let's all argue about how best to handle them lol... I actually do a preg_match on all values that are supposed to be pure integers so I can catch invalid data. i.e.: preg_match('/^[+-]?\d+$/', (string)$value) |
|
![]() |
![]() ![]() ![]() ![]() ![]() |
![]() |
#17 |
Coupon Guru
Industry Role:
Join Date: Mar 2009
Location: Minneapolis
Posts: 10,973
|
__________________
Webmaster Coupons Coupons and discounts for hosting, domains, SSL Certs, and more! AmeriNOC Coupons | Certified Hosting Coupons | Hosting Coupons | Domain Name Coupons ![]() |
![]() |
![]() ![]() ![]() ![]() ![]() |
![]() |
#18 | |
Confirmed User
Industry Role:
Join Date: Jun 2004
Location: New York, NY
Posts: 6,890
|
Quote:
same goes for the split() function, which is very common across people's code so better off with explode in most cases.
__________________
Skype variuscr - Email varius AT gmail |
|
![]() |
![]() ![]() ![]() ![]() ![]() |
![]() |
#19 | |
Confirmed User
Join Date: Aug 2002
Posts: 1,844
|
Quote:
![]() I've got a lot of sites using variations of this (very old) script, its not suported anymore and i don't have the time to find an alternative and switch to that. so i've just got to try and patch it up as best as possible. they were using something along the lines of this to hack the script: Code:
page.php?id=-999999999+union+select+concat(login,0x3a,password),1,2,3,4,5+from+adminlogin/ |
|
![]() |
![]() ![]() ![]() ![]() ![]() |
![]() |
#20 |
Confirmed User
Industry Role:
Join Date: Jul 2010
Posts: 143
|
PHP's website has good examples for you.
php.net/manual/en/security.database.sql-injection.php ![]()
__________________
loiro.sampa at gmail dot com |
![]() |
![]() ![]() ![]() ![]() ![]() |
![]() |
#21 | |
Confirmed User
Industry Role:
Join Date: Aug 2001
Posts: 832
|
Quote:
![]() CONCAT is also a naughty word as you found out. |
|
![]() |
![]() ![]() ![]() ![]() ![]() |
![]() |
#22 | |
Too lazy to set a custom title
Industry Role:
Join Date: May 2004
Location: West Coast, Canada.
Posts: 10,217
|
Quote:
|
|
![]() |
![]() ![]() ![]() ![]() ![]() |
![]() |
#23 |
Confirmed User
Industry Role:
Join Date: Aug 2001
Posts: 832
|
A safer practise is to use parameterized SQL queries. It also has performance benefits.
The negative thing is that makes your code more complex, and thus less pretty. See example here (note MySQLi and not MySQL) http://www.php.net/manual/en/mysqli.prepare.php |
![]() |
![]() ![]() ![]() ![]() ![]() |
![]() |
#24 |
♥♥♥ Likes Hugs ♥♥♥
Industry Role:
Join Date: Nov 2001
Location: /home
Posts: 15,841
|
Use a mysql class. I've been using the mysql class at ricocheting.com/code/php/mysql-database-class-wrapper-v3 and modified it a little bit to add some functionality that I needed. It's good protection for lazy coders like me.
__________________
I like pie. |
![]() |
![]() ![]() ![]() ![]() ![]() |