记一次授权网络攻防演练(上)

2022-05-14|

零基础学黑客领资料

搜公众号:白帽子左一

完整攻击链大概包括信息搜集、漏洞利用、建立据点、权限提升、权限维持、横向移动、痕迹清除等七步,虽然这个站点只经历了前四步,但也具有较强的代表性,组合利用漏洞形成攻击链,拿下管理权限。


事情缘起

杜兄弟在某旅游集团公司任职 IT 技术主管,有两家驻场安全厂商为其提供安全服务,一家负责业务相关的渗透测试,一家负责网络访问、流量监测的安全管控,上周和他吃了个串串,整个饭局除了刚开始的寒喧,大部份时间就是布道,在他的管理下,生产系统做到了绝对安全。


well,你知道的,虽然我在蓝队,但一直有颗红心。自然得怼一下,“这个还是要看攻击者哟,攻防演练没丢分,说明不了啥子三”,杜兄弟不高兴了,在酒精的作用下,他开腔了,“这样,我帮你申请 5K 的漏洞赏金,你看哈能找到啥问题不”。


对嘛,找得到,挣点油钱,找不到,当学习,于是就应下来了。


杜兄弟看我敢接招,临走前点了根烟,猛吸了两口,思索片刻后又给我加了两个限定条件:


一是,每步实质攻击前,必须先得到他的授权,



二是,单个漏洞不算完成任务,必须拿到操作系统 root。


wow,挺大的挑战,拿不下就打脸,我陷入激烈的思想斗争,wait、wait,我不是应该向钱看么,脸面不重要,ok,一下就想通了。


初步刺探


拿到的目标是个供应商管理系统,访问之,自动跳转至登录页面:



正准备启动信息收集工作,页面上有三个地方引起了我的注意:.do 的接口地址、登录功能、密码找回功能。


审查 .do 接口。看到 .do 自然联想到 struts2 命令执行全家桶。

看下用的哪种脚本语言:



的确是 java,用安恒出品的 S2 漏洞验证工具扫描下:


无果。


审查登录功能。登录功能的审查点很多,比如账号是否可枚举、密码是否可暴破,但前提是没有验证码,显然这里存在图片验证码,所以,我先确认验证码是否可绕过。


拦截登录请求:



应答标志为 2,第二次重发,应答标志变为 1:



显然,验证码防御机制有效,虽然 python 调用 tesseract 识别图片的手法可有效攻击图片验证码,但需要我爬取该站的大量图片来训练,这个阶段无需太深入,暂时放一放。


审查密码找回功能。密码找回功能很容易出现逻辑错误,经验来看,至少可从七个方面攻击密码找回功能:重置凭证接收端可篡改、重置凭证泄漏、重置凭证未校验、重置凭证可暴破、用户混淆、应答中存在影响后续逻辑的状态参数、token 可预测。


访问密码找回页面:



拦截密码找回的请求:



从应答描述可知,提示该用户不存在,重发几次,结果相同,说明图片验证码未生效,好了,第一个洞,用户名可枚举。


显然,用户名在该请求的 params 参数中,URL 解码可得明文:



于是,将 root 设定为枚举变量,加载中国人姓名(top500)、后台账号两个字典,进行枚举:



得到三个有效账号:nana、admin、liufei。


随意选个账号进入密码找回流程,liufei,应答为 JSON 数据,格式化后吓我一跳:


敏感信息大赠送!有邮箱,甚至有哈希密码。记下来,第二个漏洞,账号相关敏感信息泄漏。


我的目的很明确,获取登录密码,所以,我计划利用泄漏信息,从信息库和哈希反解两方面达到目的。

信息库。提取邮箱中的用户名,liufei 的 liufei、nana 的 18xxxxxx56、admin 的 legxxxxxxng,在信息库中查询历史密码。


只找到 liufei 相关的多个历史密码,逐一验证,均错误。


哈希反解。提取三个账号的哈希密码,liufei 的
a1e0476879cab2a76cc22c80bbf364dd、nana 的
208f0aba4a6d4b9afe94207e6c57d594、admin 的
3faf009c43bb39c5a37859bc48feaff3。


有了哈希密码,第一时间查彩虹表,反解明文密码:



只有账号 liufei 的密码解出为 !QAZ2wsx,nana、admin 无解,暂时放下。第三个漏洞,业务系统存在弱口令账号 liufei。


低权进站


通过 liufei / !QAZ2wsx 登录网站:



功能非常有限,只有个回收站,里面没有业务任何数据。


上图中有几个输入框,应该是个查询功能,但是找不到查询按钮,尝试在前端 HTML 源码中翻找查询接口,无果;在 burp 的报文历史中审查 JS,也没找到有用的接口。看来,还得找个高权限的账号。


回到先前未反解出来的两个账号,nana 的
208f0aba4a6d4b9afe94207e6c57d594、admin 的
3faf009c43bb39c5a37859bc48feaff3。


https://www.cmd5.com/拥有海量的彩虹表数据,它反解不出来,很可能是个强口令。对于强口令的暴破,我习惯围绕用户名,制作具有社工属性的密码字典,如,用户名 nana,社工属性密码可能为 NaNa、na520na、[email protected]。如何生成社工属性密码字典?


hashcat!对滴,hashcat 不仅是哈希暴破神器,也支持基于规则生成密码字典,规则库位于 hashcat/rules/:



其中,dive.rule 含有我需要的规则,选之。我把 nana 视为基础信息存入 base.txt 中作为输入,让 dive.rule 模仿学习生成类似的密码字典,保存至 se_passwds.txt:



接着用社工字典暴破哈希密码:



7 秒出结果,得到 nana 的密码 nanacnacnanac,第四个漏洞,业务系统存在社工属性口令账号 nana。用类似的手法,制作了账号 admin 的社工密码字典,遗憾,并未暴出 admin 的密码。没关系,用 nana / nanacnacnanac 登录系统,或许有新发现。


一旦进入后台,习惯上先找三类功能:上传功能、查询功能、命令功能。上传功能,通过各种任意文件上传攻击手法,上传 webshell;


查询功能,审查是否存在 SQL 注入,拿数据(如,哈希密码);


命令功能,指那些有著名工具实现的功能,比如,输入个 IP,业务功能探测该 IP 是否存活,服务端可能执行了 ping 命令,又如,上传个压缩包,页面显示压缩包内容,服务端可能执行了 unzip 命令,这时,用命令注入或命令选项注入的手法,攻击服务端。


登录 nana 账号,业务功能也不多,但有个上传功能:



我得深入审查它,或许是 getshell 的唯一通道。


先上传一个正常的 PNG 图片,页面报错,提示非管理员禁止上传:



这可不好玩了,admin 的哈希密码之前用彩虹表、社工字典都尝试过,无法反解,前进步伐再次受阻。


逻辑漏洞


回想之前刺探过的密码找回功能,发现泄漏用户哈希密码就未再深入,应该再审查下,或许能重置 admin 密码。


用 admin 进入密码找回流程,先顺利通过服务端用户名是否存在的校验,然后向该账号绑定的邮箱地址发送密码重置 URL,请求如下:



显然,参数 email 存在不安全的直接对象引用(IDOR)问题,将其替换为攻击者的邮箱,90% 的概率会收到重置邮件。


(IDOR,国内外厂商对它完全是两个态度,一次给国外电商平台提交了个 IDOR 漏洞,可导致全量用户邮箱泄漏,拿了 3K,美刀,类似漏洞提交给国内厂商,可导致政企用户个人信息泄漏、可增删改用户家庭住址,奖励了 2K,还是购物卡,T_T)


于是,我找了个匿名邮箱,尝试劫持 admin 的密码找回邮件:



很快,匿名邮箱收到来信:



访问带 token 的密码重置链接,还真能修改密码:



洋气!第五个漏洞,任意用户密码重置。


呵呵,小激动,喝口茶,刷刷微信休息下,刚好看到杜兄弟留言:




茶吐了一地,到手的 admin 又飞了。没办法,人家先就说清楚了,“每步实质攻击前,必须先得到授权”。


我不得不去找寻其他攻击路径!


垂直越权


焦点回到 nana 账号的上传功能上,虽然服务端报错禁止非 admin 上传,但仔细审查请求报文,看到存在 token:



这个 token 让我觉得很突兀,通常 token 要么用作身份凭证、要么用于防 CSRF,若是前者,就不应该与同样表示身份凭证的 cookie 同时存在,若是后者,通常为 16 位或 32 位的哈希值,而非用点号分隔的三段 base64。

于是,我依次将每段解码:

第一段解码看到 JWT,第二段解码发现用户名,第三段因下划线导致解码失败。


原来是 JWT 啊!老朋友了,全称叫 JSON Web Token,现代 web 应用中替代 cookie 表示用户身份凭证的载体。


形式类似 base64,但使用了 base64 可用字符空间之外的点字符,且无法直接解码。HTTP 报文中一旦发现 JWT,应重点关注。


一时没想起,这不就是现代 web 常用的 JWT 么,服务端对 JWT 实现不好,容易导致垂直越权,比如,把第二段的 user 字段值从 nana 篡改 admin。


但是,JWT 的签名(也就是上面的第三部分),是对信息头和数据两部分结合密钥进行哈希而得,服务端通过签名来确保数据的完整性和有效性,正因如此,由于我无法提供密钥,所以,篡改后的 token 到达服务端后,无法通过签名校验,导致越权失败。


攻击 JWT,我常用三种手法:未校验签名、禁用哈希、暴破弱密钥。


未校验签名。某些服务端并未校验 JWT 签名,所以,尝试修改 token 后直接发给服务端,查看结果。


于是,我将 user 字段值从 nana 改为 admin 后,重新生成新 token:



由于未填写正确密钥,即便生成格式正确的新 token,但提示无效签名(invalid signature),没事,放入上传请求报文中,发给服务端,试试手气:



bad news:


没关系,继续尝试其他攻击手法。


禁用哈希。JWT 第一部分含有 alg 字段,该字段指定生成签名采用哪种哈希算法,该站使用的是 HS256,可将该字段篡改为none,某些 JWT 的实现,一旦发现 alg 为 none,将不再生成哈希签名,自然不存在校验签名一说。


https://jwt.io/#debugger将 alg 为 none 视为恶意行为,所以,无法通过在线工具生成 JWT:



我只得用 python 的 pyjwt 库来实现:



你看,用 none 算法生成的 JWT 只有两部分了,根本连签名都没生成。将新的 token 发给服务端,仍然报错“wrong signature”。另外,某些 JWT 实现对大小写敏感,所以,我继续尝试了 None、nOne、NONE,均报错。


暴破弱密钥。别放弃,哪怕最后一招也得尝试,希望该站用的是个弱密钥,暴破。


我在 github 上找了个 JWT 密钥暴破工具
https://github.com/lmammino/jwt-cracker
,但只支持字符序列穷举方式暴破,无法加载字典:



不得不自己写个脚本。


前面提到的 pyjwt 库,不仅可用于生成 JWT,也可通过 jwt.decode(jwt_str, verify=True, key=key_) 进行签名校验,但,导致校验失败的因素不仅密钥错误,还可能是数据部分中预定义字段错误(如,当前时间超过 exp),也可能是 JWT 字符串格式错误等等


所以,借助 jwt.decode(jwt_str, verify=True, key=key_) 验证密钥 key_:


1.若签名直接校验失败,则 key_ 为有效密钥;

2.若因数据部分预定义字段错误(
jwt.exceptions.ExpiredSignatureError,
jwt.exceptions.InvalidAudienceError,
jwt.exceptions.InvalidIssuedAtError,
jwt.exceptions.InvalidIssuedAtError,
jwt.exceptions.ImmatureSignatureError)导致校验失败,说明并非密钥错误导致,则 key_ 也为有效密钥;

3.若因密钥错误(
jwt.exceptions.InvalidSignatureError)导致校验失败,则 key_ 为无效密钥;

4.若为其他原因(如,JWT 字符串格式错误)导致校验失败,根本无法验证当前 key_ 是否有效。

按此逻辑,快速实现 JWT 密钥暴破功能,代码如下:



运行脚本,很快找到密钥:



哈哈,哈哈哈哈,密钥到手,高权我有!


接下来,我将 user 字段从 nana 改为 admin,并提供有效密钥

$admin$:



生成了具备有效签名的新 JWT 值。


尝试用伪造成 admin 的新 JWT 上传图片:


哈哈哈哈,成功上传图片。第六个漏洞,JWT 使用弱密钥,可导致垂直越权。

(后续如何,下回分解)

作者:yangyangwithgnu

原文地址:
https://www.freebuf.com/vuls/211842.html


标签: 哈希 密码 密钥 社工 功能 JWT 校验 账号 重置 漏洞
出处: https://www.toutiao.com/article/7097098866209784335/

文明发言,请先登录

文明上网理性发言,请遵守国家法律法规。

最新评论

©2003- 黑基网 黑名单存档手机版网站地图免责条款法律声明隐私保护