2021年11月24日,阿里云安全团队向Apache官方报告了Apache Log4j2远程代码执行漏洞。2021年12月10日,阿里云安全团队发现 Apache Log4j 2.15.0-rc1 版本存在漏洞绕过,请及时更新至 Apache Log4j 2.15.0 正式版本。
资料来源:
阿里云漏洞预警
360安全漏洞报告
腾讯安全
1.预备知识
1.1 Apache
Apache是世界使用排名第一的Web服务器软件。它可以运行在几乎所有广泛使用的计算机平台上,由于其跨平台和安全性被广泛使用,是最流行的Web服务器端软件之一。它快速、可靠并且可通过简单的API扩充,将Perl/Python等解释器编译到服务器中。
1.2 log4j
Log4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件,甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。
1.3 JNDI注入
1.3.1 JNDI
JNDI(全称Java Naming and Directory Interface
)是用于目录服务的Java API,它允许Java客户端通过名称发现和查找数据和资源(以Java对象的形式)。与与主机系统接口的所有Java api一样,JNDI独立于底层实现。此外,它指定了一个服务提供者接口(SPI),该接口允许将目录服务实现插入到框架中。通过JNDI查询的信息可能由服务器、文件或数据库提供,选择取决于所使用的实现。
1.3.2 JNDI注入
JNDI
注入简单来说就是在JNDI
接口在初始化时,如:InitialContext.lookup(URI)
,如果URI可控,那么客户端就可能会被攻击
1.3.3 RMI
通过RMI进行JNDI注入,攻击者构造的恶意RMI服务器向客户端返回一个Reference
对象,Reference
对象中指定从远程加载构造的恶意Factory
类,客户端在进行lookup
的时候,会从远程动态加载攻击者构造的恶意Factory
类并实例化,攻击者可以在构造方法或者是静态代码等地方加入恶意代码。
javax.naming.Reference
构造方法为:Reference(String className, String factory, String factoryLocation)
,
className
- 远程加载时所使用的类名classFactory
- 加载的class
中需要实例化类的名称classFactoryLocation
- 提供classes
数据的地址可以是file/ftp/http
等协议
因为Reference
没有实现Remote
接口也没有继承UnicastRemoteObject
类,故不能作为远程对象bind到注册中心,所以需要使用ReferenceWrapper
对Reference
的实例进行一个封装。
服务端代码如下
package demo;
import com.sun.jndi.rmi.registry.ReferenceWrapper;
import javax.naming.Reference;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class RMIServer {
public static void main(String[] args