在准备语句时防止SQL注入的最佳方法是不可能的

时间:2011-06-09 13:56:21

标签: php sql-injection

我必须处理一个存在重大安全问题的旧网站:SQL注入非常容易执行。

显然,防止这种攻击的最好方法是逃避查询中使用的内容(使用PDO编写语句,使用MySql编写mysql_real_escape_string等),但我们不能快速做到:整个站点都是程序性PHP (没有上课),查询在任何地方“准备好”,每天有数百个页面和数千个用户,新版本将尽快出现。

因此,从今天早晨开始,每个请求都会调用以下函数来检测基于关键字的可疑POST或GET参数。

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; 
}

这似乎可以检测到某些类型的攻击,但它显然非常基本。有什么改进的想法吗?任何重大问题?

2 个答案:

答案 0 :(得分:2)

首先,确保执行查询的数据库用户只具有选择,更新,删除权限。如果用户无法执行drop,则不会发生这种情况(这假设您的用户永远不需要创建或删除表,但如果他们这样做,您可以创建表级权限来保护大表)。 / p>

其次,您的脚本只会告诉您人们使用的是什么;它不会在网站范围内检查可能的查询;如果您网站的某个部分使用不多,您将不会收到任何邮件告诉您。最好只使用搜索工具梳理代码。

之后,你必须开始修改代码并进行转义和验证,这只需要一段时间。

答案 1 :(得分:0)

为什么不使用real_escape_string() htmlentities() stripslashes和过滤类的php并记录SQL查询,以便你可以看到人们发送给你的东西,使用sha256和一些md5你会没事的其他东西用于快速操作只需以二进制格式发送登录数据