在进行Web应用安全测试时,一个常见的接口参数往往隐藏着意想不到的风险。最近遇到的一个真实案例,就涉及到一个需要绕过双重防御机制的MySQLSQL注入漏洞。
测试的起点是一个查询用户信息的API接口,其请求示例如下:
POST /api/userInfo
...
userId=100001
服务器返回了一个标准的JSON响应,状态为200 OK,由nginx提供服务,内容显示操作成功:
{
“success”: true,
“errorCode”: -1,
“message”: “操作成功”
}
初步测试,如修改userId值尝试越权,或将其置空,均未发现异常。然而,当在参数值中意外加入一个单引号时,情况发生了变化。服务器返回了“获取数据失败”的错误信息。
这一错误响应立刻引发了是否存在SQL注入的猜想。随后的测试证实了这一点,后端数据库为MySQL。但漏洞的利用之路并非坦途。
首先遇到的是来自应用程序代码层面的拦截。当尝试使用and、or等基础布尔逻辑进行探测时,请求被拦截,服务器返回了明确的警告:“参数非法,已记录您的IP”。
这迫使测试转向寻找代码过滤规则的边界。测试发现,使用基于时间的盲注函数sleep()会触发另一个截然不同的拦截页面。该页面提示“您的请求带有不合法参数,已被网站管理员设置拦截!”,其样式与常见的宝塔等软WAF的拦截页面高度相似,这证实了目标系统部署了软硬件WAF作为第二道防线。
面对双重防御,需要仔细分析每一层的过滤逻辑。经过一系列测试,发现了以下规律:
-
拦截空格:简单的or 1=1被代码层WAF拦截。尝试将or改为大写oR同样失败。然而,当使用URL编码的换行符%0a替代空格时,绕过了拦截,这暗示代码层规则可能拦截了特定的空格字符。
测试Payload:userId=100001' oR%0A' 1 =' 1
此时服务器返回了“操作成功”的响应,但并未触发预期的SQL错误,说明语法可能被应用层处理或未正确闭合。
-
绕过函数黑名单:尝试使用exp()函数触发除零错误时,发现exp(710)能正常执行(返回成功),但竖杠||逻辑运算符却未生效,表明存在特殊的字符处理或过滤。
-
组合绕过策略:综合以上信息,测试人员开始组合使用换行符%0a、等号URL编码%3d以及MySQL特有的内联注释/*!...*/来构造更复杂的Payload。内联注释可用于包裹关键字,有时能绕过简单的正则匹配。
经过反复尝试,最终构造出了能够同时绕过两层防护并触发数据库报错的Payload。一个成功的触发示例如下:
userId=100001'/*!and*//**/%3d%0Aexp(709)/*!or*//**/'1%3d'1
对应的服务器响应表明注入成功,返回了“操作成功”。而当将exp(709)修改为exp(710)(一个在MySQL中会导致溢出错误的参数)时,则成功触发报错,响应变更为“获取数据失败”,从而验证了基于报错的注入点可利用。
这个案例清晰地展示了当面对“代码层过滤+软WAF”的复合防御体系时,攻击者(或安全测试人员)需要采用的迂回策略:首先通过模糊测试探测出每一层防护的具体拦截规则(如拦截空格字符、特定函数),然后利用MySQL语法的特性(如%0a作为空白符、内联注释)和编码技巧,精心拼接Payload,最终实现绕过。
参考资料
[1] 实战SQL注入之绕过代码拦截+软waf, 微信公众号:mp.weixin.qq.com/s/Nm9ZikqVEZ-_S9cv9_tvRQ
版权声明:本文由 云栈社区 整理发布,版权归原作者所有。