*************************************************
** 本教程基于版本:Discuz! X 2.0 **
*************************************************
class_core.php 里面 DB 类里 fetch_first、result_first、query 等方法里面首先会调用 checkquery 方法对需要执行的 sql 进行处理过滤判断。
这里说一下 checkquery 方法的处理判断 sql 的过程- function checkquery($sql) {
- static $status = null, $checkcmd = array('SELECT', 'UPDATE', 'INSERT', 'REPLACE', 'DELETE');
- if($status === null) $status = getglobal('config/security/querysafe/status');
- if($status) {
- $cmd = trim(strtoupper(substr($sql, 0, strpos($sql, ' '))));
- if(in_array($cmd, $checkcmd)) {
- $test = DB::_do_query_safe($sql);
- if($test < 1) DB::_execute('halt', 'security_error', $sql);
- }
- }
- return true;
- }
复制代码 该方法定义了一个需要进行判断的 sql 语句的命令关键词的数组,并且 需要 config_global.php 里面 开启了安全 sql 过滤设置 即- $_config['security']['querysafe']['status'] = 1;
复制代码 时,方法会调用一个内部的函数 _do_query_safe() (参考 class_core.php 文件中的该方法)对需要执行的 sql 进行安全检查
_do_query_safe 方法所要做的就是去掉一些 mysql 注释掉的字符串,去掉 sql 中被一对引号包含的字符串,去掉空格,然后对剩下的纯的sql 命令和字段等字符进行判断
_do_query_safe 首先过滤去掉被转义掉的 单号号,然后判断去掉转义掉的单号的sql 里面是否含有 mysql 的注释符等特殊符号
如果 sql 语句中不含有 mysql 注释符 则程序去掉一对单引号及其包含的起来的字符串
如果 sql 语句中含有一些 mysql 的注释符等字符串,程序就会对该条 sql 逐个字符的遍历,判断并处理去掉注释掉的内容,单引号中的内容
剩下的 sql 字符串使用- $clean = preg_replace("/[^a-z0-9_\-\(\)#\*\/"]+/is", "", strtolower($clean));
复制代码 去掉非常规的一些字符串
在该 _do_query_safe 方法最开始读取了config_global.php 中的 $_config['security']['querysafe'] 数组- if(is_array($_CONFIG['dfunction'])) {
- foreach($_CONFIG['dfunction'] as $fun) {
- if(strpos($clean, $fun.'(') !== false) return '-1';
- }
- }
- if(is_array($_CONFIG['daction'])) {
- foreach($_CONFIG['daction'] as $action) {
- if(strpos($clean,$action) !== false) return '-3';
- }
- }
- if($_CONFIG['dlikehex'] && strpos($clean, 'like0x')) {
- return '-2';
- }
- if(is_array($_CONFIG['dnote'])) {
- foreach($_CONFIG['dnote'] as $note) {
- if(strpos($clean,$note) !== false) return '-4';
- }
- }
复制代码 通过该数组对以上过滤处理后的sql 进行查找,是否存在 $_config['security']['querysafe'] 数组中的危险的命令字符串
如果存在,则根据不同的类型的危险字符串,返回一个相应的负值
checkquery 就是根据该负值 来判断对 sql 执行 进行中断
这里需要注意的是 config_global.php 中安全设置必须为1- $_config['security']['querysafe']['status'] = 1;
复制代码 才会判断安全性,所以平常需要检查 该文件是否被非法修改 |