0x00 前言
注:本文分两部分讲解,本篇为第一部分,主要是讲解原理、实战以及绕过措施(这里的绕过措施是针对本文提到的实战案例进行的绕过),第二部分主要是对本文进行一下补充。
0x01 探究模糊查询
先简单介绍一下模糊查询的概念,模糊查询是指基于模糊条件在数据库中匹配与之相对应的记录。在实际开发中,模糊查询应用很广泛,例如搜索引擎,商品查询等等。我们在搜索框输入一个字就会匹配到存在这个字的相关记录。这些都用到了模糊查询。
模糊查询在MySQL中主要用like关键字来检索,其他方法在本文不一一列举。
语法如下:
SELECT column1, column2, ...
FROM table_name
WHERE column_name LIKE pattern;
table_name为表名,column_name为列名,pattern表示要查找的模式。
一般与like一起使用的有两个通配符:
百分号(%):表示零个、一个或多个字符
下划线 (_) :表示一个字符
下面我拿一个测试表进行测试说明。
如下图所示是一个students表。
查找表中所有学生:
select * from students where name like '%';
查找所有姓张的学生:
select * from students where name like '张%';
查找所有姓名末尾为飞的学生:
select * from students where name like '%飞';
查找姓名为三个字的并且姓为司的学生:
select * from students where name like '司__';
查找所有姓名为三个字的学生:
select * from students where name like '___';
至此想必大家对模糊查询都有了一定的认识,下文主要以实战案例进行演示模糊查询在渗透当中的实际应用。
0x02 实战
如下图所示是某系统查询被访人的一个功能:
这里直接点搜索是不能进行搜索的,必须得输入内容才能触发。所以我在这里填了一个“王”进行搜索测试,随后数据包返回了所有姓王的人员信息(厚码见谅):
这里就用到了本文的核心内容模糊查询
,其中返回的部分信息具有人员敏感信息。
此刻读者可以思考一下,这算什么漏洞?从严格意义上来讲,这就是一个敏感信息泄露,但是如果表中的个人信息都是脱敏了的,那么就不算是一个洞了;此外,这个洞的范围其实很小,这里为什么说小呢,首先姓名我们需要fuzz,而且如果表中存在admin信息,但我只正常进行了姓名fuzz,是不是就会错过了?所以从范围上来讲,如果我们能获取表中所有被访人的信息,那么漏洞危害就大大提高了。
接着,将值换成百分号:
发包测试:
返回包返回了表中的所有人员信息。
随后我提交了该漏洞,过了不久我发现厂商修复后再次尝试挖掘,发现%号已经被过滤:
不慌,此时将值改为空格尝试绕过:
成功绕过并调用出该表中所有人员信息。
0x03 分析
当参数为%时,猜测数据库执行语句为(为了方便我暂且将json的键名作为列名):
select * from table_name where searchName like '%%';
一个百分号会匹配到所有记录,更何况两个,所以这里会返回所有记录,就拿我们上文中用到的测试表测试:
不过接下来我会重点讲一下为什么我在上文中使用到的空格进行的传参也匹配到了所有记录,这里我测试一下空格在测试表中是否能匹配到:
select * from students where name like ' %';
显而易见是不能的。
我们逐步来分析一下:在MySQL中如果用“空格” + “%”进行模糊查询,是不能匹配到所有记录的,那么可以肯定的是数据库中执行的语句是不带空格的,后端传进数据库的是空字符串,执行的语句就是:
select * from table_name where searchName like '%';
那么我个人认为造成这个原因的有两种可能:
1.json在传递空格时,后端将空格视为空字符串(在文中这里只是作为一种猜测,其实,无论是哪种语言,都不会主动将json中的空格转换为空字符串,后文会进行演示)2.后端在向数据库传参时过滤了空格,导致传进数据库的是空字符串。
我们在进行传参时使用到的是json传参,我们先来测试一下服务端在接受json数据时,值是空格的情况下能不能被正常解析,下文使用node.js进行测试。
如下图所示,客户端使用xhr进行请求,服务端使用的是node.js,我本人不怎么熟悉node.js,所以代码是用GPT写的:
开启服务:
发送请求,点击一下按钮:
成功输出,终止服务,将jack换为空格:
请求:
可见在node.js中并没有将json中空格转换为空字符串,验证一下:
将返回的json放进div中:
以上证明了在node.js中并没有主动将json中的空格转换为空字符串,其他语言也都不会。
所以只剩下一种可能,就是服务端在接受json时将值传递给Mysql时将空格剔除掉了,这里我也不太知道该怎么演示,但是这是唯一的一种可能性。
下面来说一下我本人比较倾向于的一个后端逻辑,第一是没修复前的后端逻辑:原本后端将值传递给MySQL时可能就做了一步过滤,将特殊字符过滤掉了,导致后端执行的就是:
select * from table_name where searchName like '%';
然后我在提交了漏洞之后开发在接受值的时候写了正则,如果发送的数据包含了特殊字符,就返回为空,不去执行数据库语句,恰巧空格不在正则中,所以后端也就去执行了上述操作,所以又返回了所有信息。
这是我目前能想到的最好能诠释为什么空格能在本案例中进行绕过的原因了。读者如有补充,可在本文下方留言。
所以文中在这里大篇幅讲到空格,是因为在后端中如果过滤了特殊字符如我们上文使用到的百分号%,如果空格在没有进行过滤的情况下,我们就可以使用空格进行传参调用,以此来达到获取表中所有记录。
PS:该绕过措施只是针对本案例,如果后端在向数据库传参时并没有做过滤,空格也没有在正则中,就算传递了空格,也不会在数据库中匹配记录,除非表中有记录开头带了空格,否则返回的肯定是空记录:
原文始发于微信公众号(暮秋初九的小屋):MySQL的模糊查询在渗透测试当中的实际应用(其一)
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论