Best way to prevent SQL Injection when preparing statement is impossible
I have to work on an old site with major security issues : SQL Injections are really easy to perform.
Obviously, the best way to prevent this kind of attacks is to escape what is used in query (prepare statements with PDO, mysql_real_escape_string with MySql, etc.) but we can't do that quickly : the whole site is procedural PHP (no class), the queries are "prepared" everywhere, there are hundreds of pages and thousands of users everyday, and a new version wil come as soon as possible.
So since this morning the following function is called on each request to detect suspicious POST or GET parameters based on keywords.
开发者_运维问答const SQLI_UNSAFE = 3;
const SQLI_WARNING = 2;
const SQLI_SAFE = 1;
const SQLI_MAIL_DEST = 'monmail@mondest.com';
function sqlicheck() {
$params = array_merge($_GET, $_POST);
$is_warning = false;
foreach($params as $key=>$param) {
switch(getSafeLevel($param)) {
case SQLI_SAFE:
break;
case SQLI_WARNING:
$is_warning = true;
break;
case SQLI_UNSAFE:
mail(SQLI_MAIL_DEST, 'SQL INJECTION ATTACK', print_r($_REQUEST, true).' '.print_r($_SERVER, true));
header('Location: http://monsite/404.php');
exit();
}
}
if($is_warning === true) {
mail(SQLI_MAIL_DEST, 'SQL INJECTION WARNING', print_r($_REQUEST, true).print_r($_SERVER, true));
}
}
function getSafeLevel($param) {
$error_words = array('select%20','drop%20','delete%20','truncate%20','insert%20','%20tbclient','select ','drop ','delete ','truncate ','insert ',);
$warning_words = array('%20','select','drop','delete','truncate', ';','union');
foreach($error_words as $error_word) {
if(stripos($param, $error_word) !== false) return SQLI_UNSAFE;
}
foreach($warning_words as $warning_word) {
if(stripos($param, $warning_word) !== false) return SQLI_WARNING;
}
return SQLI_SAFE;
}
This seems to detect some kinds of attacks but it's clearly very basic. Any ideas to improve it? Any major issue ?
First, make sure that the database user executing the queries only has select, update, delete permissions. If the user can't execute drop, there's no way it'll happen (this assumes that your users will never need to create or drop tables, but if they do, you can create table level permissions to protect the big tables).
Second, your script will only tell you what people are using; it won't do a site wide check of what queries are possible; if there's a section of your site that isn't used much, you won't get any mail telling you. Better to just comb through the code with a search tool.
After that, you have to start modifying the code and doing escaping and validation, and that's just going to take a while.
Why not just use real_escape_string()
htmlentities()
stripslashes and filter classes of php and log the SQL queries so that you can see what people are sending you, use sha256 with some md5 you will be ok other thing is for quick action just send login data in binary format
精彩评论