用户控制数据的反序列化¶
ID: java/unsafe-deserialization
Kind: path-problem
Security severity: 9.8
Severity: error
Precision: high
Tags:
- security
- external/cwe/cwe-502
Query suites:
- java-code-scanning.qls
- java-security-extended.qls
- java-security-and-quality.qls
使用允许构建任意可序列化对象的任何反序列化框架反序列化不受信任的数据很容易被利用,并且在许多情况下允许攻击者执行任意代码。甚至在反序列化对象返回给反序列化方法的调用者之前,也可能执行了很多代码,包括静态初始化程序、构造函数和终结器。字段的自动反序列化意味着攻击者可以制作嵌套的对象组合,在这些对象上执行的初始化代码可能会产生意想不到的影响,例如执行任意代码。
有很多不同的序列化框架。此查询目前支持 Kryo、XmlDecoder、XStream、SnakeYaml、JYaml、JsonIO、YAMLBeans、HessianBurlap、Castor、Burlap、Jackson、Jabsorb、Jodd JSON、Flexjson、Gson、JMS 和通过 ObjectInputStream
/ObjectOutputStream
进行的 Java IO 序列化。
建议¶
如果可能,请避免反序列化不受信任的数据。如果架构允许,那么使用其他格式而不是序列化对象,例如 JSON 或 XML。但是,这些格式不应反序列化为复杂对象,因为这会提供进一步的攻击机会。例如,可以通过 XStream 和 XmlDecoder 等库进行基于 XML 的反序列化攻击。
或者,严格控制的白名单可以限制代码的漏洞,但请注意所谓的绕过小工具的存在,它可以规避此类保护措施。
此查询支持的特定框架的建议
FastJson - com.alibaba:fastjson
默认安全:部分
建议:在反序列化不受信任的数据之前,使用参数
true
调用com.alibaba.fastjson.parser.ParserConfig#setSafeMode
。
FasterXML - com.fasterxml.jackson.core:jackson-databind
默认安全:是
建议:不要调用
com.fasterxml.jackson.databind.ObjectMapper#enableDefaultTyping
,也不要使用com.fasterxml.jackson.annotation.JsonTypeInfo
注释任何对象字段,并向注释传递CLASS
或MINIMAL_CLASS
值。阅读 本指南。
Kryo - com.esotericsoftware:kryo
和 com.esotericsoftware:kryo5
默认安全:
com.esotericsoftware:kryo5
为是,com.esotericsoftware:kryo
>= v5.0.0 为是建议:不要在任何可能反序列化不受信任数据的
Kryo
实例上使用参数false
调用com.esotericsoftware.kryo(5).Kryo#setRegistrationRequired
。
ObjectInputStream - Java 标准 库
默认安全:否
建议:使用验证输入流,例如
org.apache.commons.io.serialization.ValidatingObjectInputStream
。
SnakeYAML - org.yaml:snakeyaml
默认安全:否
建议:在使用
org.yaml.snakeyaml.Yaml
的构造函数反序列化不受信任的数据之前,向其传递org.yaml.snakeyaml.constructor.SafeConstructor
的实例。
XML Decoder - 标准 Java 库
默认安全:否
建议:不要与不受信任的用户输入一起使用。
ObjectMesssage - Java EE/Jakarta EE
默认安全:取决于 JMS 实现。
建议:不要与不受信任的用户输入一起使用。
示例¶
以下示例直接在从不受信任数据构建的 ObjectInputStream
上调用 readObject
,因此本质上是不安全的。
public MyObject {
public int field;
MyObject(int field) {
this.field = field;
}
}
public MyObject deserialize(Socket sock) {
try(ObjectInputStream in = new ObjectInputStream(sock.getInputStream())) {
return (MyObject)in.readObject(); // unsafe
}
}
将通信协议重写为仅依赖从输入流读取原始类型,即可消除漏洞。
public MyObject deserialize(Socket sock) {
try(DataInputStream in = new DataInputStream(sock.getInputStream())) {
return new MyObject(in.readInt());
}
}
参考¶
OWASP 漏洞说明:反序列化不受信任的数据。
OWASP 关于反序列化对象的指导:反序列化备忘单。
Chris Frohoff 和 Gabriel Lawrence 的演讲:AppSecCali 2015:序列化 Pickles - 反序列化对象如何毁掉你的美好一天,OWASP SD:反序列化我的短裤:或者我如何开始担心并讨厌 Java 对象反序列化。
Alvaro Muñoz 和 Christian Schneider,RSAConference 2016:串行杀手:静默地控制你的 Java 端点。
SnakeYaml 关于反序列化的文档:SnakeYaml 反序列化。
Hessian 反序列化和相关小工具链:Hessian 反序列化。
Castor 和 Hessian java 反序列化漏洞:Castor 和 Hessian 反序列化。
JYaml 库中的远程代码执行:JYaml 反序列化。
JsonIO 反序列化漏洞:JsonIO 反序列化。
Moritz Bechler 的研究:Java Unmarshaller 安全性 - 将你的数据变成代码执行
Jackson 库开发人员的博客文章:关于 Jackson CVE:不要惊慌 - 这是你需要了解的内容 Jackson 2.10:安全的默认类型
Jabsorb 关于反序列化的文档:Jabsorb JSON 序列化器。
Jodd JSON 关于反序列化的文档:JoddJson 解析器。
Flexjson 中的 RCE:Flexjson 反序列化。
使用 GSON 解析器的 Android Intent 反序列化漏洞:不安全的 JSON 解析器使用。
Matthias Kaiser 的研究:利用反序列化漏洞攻击您的 Java 消息传递。
常见弱点枚举:CWE-502。