刚看到TP 的注入补丁..防sql注入

浏览:4131 发布日期:2014/12/24 分类:技术分享
刚看到TP的SQL注入的补丁,突然发现有种不好的预感,马上测试的下自己正在弄的项目 因为也有很多字符串拼接的查询,,不试不知道,一试吓一跳啊....尼玛太坑爹了.立马想办法解决
怎么解决..这个东西自己写不太可能啊,最直接的方法,把Discuz 的代码拿来,在查询的几个地方 判断下,就行行了..

这个代码大家也可以直接拿去用,我基本没改class sqlsave {

    protected static $checkcmd = array('SEL'=>1, 'UPD'=>1, 'INS'=>1, 'REP'=>1, 'DEL'=>1);
    protected static $config = array(
            'status'=>1,
            'dfunction'=>array('load_file','hex','substring','if','ord','char'),
            'daction'=>array('@','intooutfile','intodumpfile','unionselect','(select','unionall','uniondistinct'),
            'dnote'=>array('/*','*/','#','--','"',''),
            'dlikehex'=>1,
            'afullnote'=>'0',
        );

    public static function checkquery($sql) {
        if (self::$config['status']) {
            $check = 1;
            $cmd = strtoupper(substr(trim($sql), 0, 3));
            if(isset(self::$checkcmd[$cmd])) {
                $check = self::_do_query_safe($sql);
            } elseif(substr($cmd, 0, 2) === '/*') {
                $check = -1;
            }

            if ($check < 1) {
                           return false;
            }
        }
        return true;
    }

    private static function _do_query_safe($sql) {
        $sql = str_replace(array('\\\\', '\\\'', '\\"', '\'\''), '', $sql);
        $mark = $clean = '';
        if (strpos($sql, '/') === false && strpos($sql, '#') === false && strpos($sql, '-- ') === false && strpos($sql, '@') === false && strpos($sql, '`') === false) {
            $clean = preg_replace("/'(.+?)'/s", '', $sql);
        } else {
            $len = strlen($sql);
            $mark = $clean = '';
            for ($i = 0; $i < $len; $i++) {
                $str = $sql[$i];
                switch ($str) {
                    case '`':
                        if(!$mark) {
                            $mark = '`';
                            $clean .= $str;
                        } elseif ($mark == '`') {
                            $mark = '';
                        }
                        break;
                    case '\'':
                        if (!$mark) {
                            $mark = '\'';
                            $clean .= $str;
                        } elseif ($mark == '\'') {
                            $mark = '';
                        }
                        break;
                    case '/':
                        if (empty($mark) && $sql[$i + 1] == '*') {
                            $mark = '/*';
                            $clean .= $mark;
                            $i++;
                        } elseif ($mark == '/*' && $sql[$i - 1] == '*') {
                            $mark = '';
                            $clean .= '*';
                        }
                        break;
                    case '#':
                        if (empty($mark)) {
                            $mark = $str;
                            $clean .= $str;
                        }
                        break;
                    case "\n":
                        if ($mark == '#' || $mark == '--') {
                            $mark = '';
                        }
                        break;
                    case '-':
                        if (empty($mark) && substr($sql, $i, 3) == '-- ') {
                            $mark = '-- ';
                            $clean .= $mark;
                        }
                        break;

                    default:

                        break;
                }
                $clean .= $mark ? '' : $str;
            }
        }

        if(strpos($clean, '@') !== false) {
            return '-3';
        }

        $clean = preg_replace("/[^a-z0-9_\-\(\)#\*\/\"]+/is", "", strtolower($clean));

        if (self::$config['afullnote']) {
            $clean = str_replace('/**/', '', $clean);
        }

        if (is_array(self::$config['dfunction'])) {
            foreach (self::$config['dfunction'] as $fun) {
                if (strpos($clean, $fun . '(') !== false)
                    return '-1';
            }
        }

        if (is_array(self::$config['daction'])) {
            foreach (self::$config['daction'] as $action) {
                if (strpos($clean, $action) !== false)
                    return '-3';
            }
        }

        if (self::$config['dlikehex'] && strpos($clean, 'like0x')) {
            return '-2';
        }

        if (is_array(self::$config['dnote'])) {
            foreach (self::$config['dnote'] as $note) {
                if (strpos($clean, $note) !== false)
                    return '-4';
            }
        }

        return 1;
    }

    public static function setconfigstatus($data) {
        self::$config['status'] = $data ? 1 : 0;
    }

}
用的时候 if (true !== sqlsave::checkquery($sql)) {
            redirect(config('site_url'));
        }
本来想如果检测不通过,就报个异常或者写个日志啥的,不过觉得不太合适..干脆直接跳转到首页拉倒了
最佳答案
评论( 相关
后面还有条评论,点击查看>>