大咖直播-鸿蒙原生开发与智能提效实战!>>> 了解详情
写点什么

Java 序列化的状态

  • 2018-09-10
  • 本文字数:6034 字

    阅读完需:约 20 分钟

关键要点

  • Java 序列化在很多库中引入了安全漏洞。
  • 对序列化进行模块化处于开放讨论状态。
  • 如果序列化能够成为模块,开发人员将能够将其从攻击表面上移除。
  • 移除其他模块可以消除它们所带来的风险。
  • 插桩提供了一种编织安全控制的方法,提供现代化的防御机制。

多年来,Java 的序列化功能饱受安全漏洞 zero-day 攻击,为此赢得了“持续奉献的礼物”和“第四个不可饶恕的诅咒”的绰号。

作为回应,OpenJDK 贡献者团队讨论了一些用于限制序列化访问的方法,例如将其提取到可以被移除的jigsaw 模块中,让黑客无法攻击那些不存在的东西。

一些文章(例如“序列化必须死”)提出了这样的建议,将有助于防止某些流行软件(如VCenter 6.5)的漏洞被利用

什么是序列化?

自从 1997 年发布 JDK 1.1 以来,序列化已经存在于 Java 平台中。

它用于在套接字之间共享对象表示,或者将对象及其状态保存起来以供将来使用(反序列化)。

在 JDK 10 及更低版本中,序列化作为 java.base 包和 java.io.Serializable 方法的一部分存在于所有的系统中。

GeeksForGeeks 对序列化的工作原理进行了详细的描述。

有关更多如何使用序列化的代码示例,可以参看 Baeldung 对 Java 序列化的介绍

序列化的挑战和局限

序列化的局限主要表现在以下两个方面:

  1. 出现了新的对象传输策略,例如 JSON、XML、Apache Avro、Protocol Buffers 等。
  2. 1997 年的序列化策略无法预见现代互联网服务的构建和攻击方式。

进行序列化漏洞攻击的基本前提是找到对反序列化的数据执行特权操作的类,然后传给它们恶意的代码。为了理解完整的攻击过程,可以参看 Matthias Kaiser 在 2015 年发表的“ Exploiting Deserialization Vulnerabilities in Java ”一文,其中幻灯片第 14 页开始提供了相关示例。

其他大部分与序列号有关的安全研究都是基于Chris Frohoff、Gabriel Lawrence 和Alvaro Munoz 的工作成果。

序列化在哪里?如何知道我的应用程序是否用到了序列化?

要移除序列化,需要从 java.io 包开始,这个包是 java.base 模块的一部分。最常见的使用场景是:

使用这些方法的开发人员应考虑使用其他存储和读回数据的替代方法。Eishay Smith 发布了几个不同序列化库的性能指标。在评估性能时,需要在基准度量指标中包含安全方面的考虑。默认的Java 序列化“更快”一些,但漏洞也会以同样的速度找上门来。

我们该如何降低序列化缺陷的影响?

项目Amber 包含了一个关于将序列化API 隔离出来的讨论。我们的想法是将序列化从java.base 移动到单独的模块,这样应用程序就可以完全移除它。在确定 JDK 11 功能集时并没有针对该提议得出任何结果,但可能会在未来的 Java 版本中继续进行讨论。

通过运行时保护来减少序列化暴露

一个可以监控风险并自动化可重复安全专业知识的系统对于很多企业来说都是很有用的。Java 应用程序可以将 JVMTI 工具嵌入到安全监控系统中,通过插桩的方式将传感器植入到应用程序中。Contrast Security 是这个领域的一个免费产品,它是 JavaOne 大会的 Duke's Choice 大奖得主。与其他软件项目(如 MySQL 或 GraalVM)类似, Contrast Security 的社区版对开发人员是免费的。

将运行时插桩应用在 Java 安全性上的好处是它不需要修改代码,并且可以直接集成到 JRE 中。

它有点类似于面向切面编程,将非侵入式字节码嵌入到源端(远程数据进入应用程序的入口)、接收端(以不安全的方式使用数据)和转移(安全跟踪需要从一个对象移动到另一个对象)。

通过集成每个“接收端”(如 ObjectInputStream),运行时保护机制可以添加额外的功能。在从 JDK 9 移植反序列化过滤器之前,这个功能对序列化和其他攻击的类型(如 SQL 注入)来说至关重要。

集成这个运行时保护机制只需要修改启动标志,将 javaagent 添加到启动选项中。例如,在 Tomcat 中,可以在 bin/setenv.sh 中添加这个标志:

CATALINA_OPTS=-javaagent:/Users/ecostlow/Downloads/Contrast/contrast.jar

启动后,Tomcat 将会初始化运行时保护机制,并将其注入到应用程序中。关注点的分离让应用程序可以专注在业务逻辑上,而安全分析器可以在正确的位置处理安全性。

其他有用的安全技术

在进行维护时,可以不需要手动列出一长串东西,而是使用像 OWASP Dependency-Check 这样的系统,它可以识别出已知安全漏洞的依赖关系,并提示进行升级。也可以考虑通过像 DependABot 这样的系统进行库的自动更新。

虽然用意很好,但默认的 Oracle 序列化过滤器存在与 SecurityManager 和相关沙箱漏洞相同的设计缺陷。因为需要混淆角色权限并要求提前了解不可知的事物,限制了这个功能的大规模采用:系统管理员不知道代码的内容,所以无法列出类文件,而开发人员不了解环境,甚至 DevOps 团队通常也不知道系统其他部分(如应用程序服务器)的需求。

移除未使用模块的安全隐患

Java 9 的模块化 JDK 能够创建自定义运行时镜像,移除不必要的模块,可以使用名为jlink 的工具将其移除。这种方法的好处是黑客无法攻击那些不存在的东西。

从提出模块化序列化到应用程序能够实际使用以及使用其他序列化的新功能需要一段时间,但正如一句谚语所说:“种树的最佳时间是二十年前,其次是现在”。

剥离 Java 的原生序列化功能还应该为大多数应用程序和微服务提供更好的互操作性。通过使用标准格式(如 JSON 或 XML),开发人员可以更轻松地在使用不同语言开发的服务之间进行通信——与 Java 7 的二进制 blob 相比,python 微服务通常具有更好的读取 JSON 文档的集成能力。不过,虽然 JSON 格式简化了对象共享,针对 Java 和.NET 解析器的“ Friday the 13th JSON attacks ”证明了银弹是不存在的(白皮书)。

在进行剥离之前,序列化让然保留在 java.base 中。这些技术可以降低与其他模块相关的风险,在序列化被模块化之后,仍然可以使用这些技术。

为 Apache Tomcat 8.5.31 模块化 JDK 10 的示例

在这个示例中,我们将使用模块化的 JRE 来运行 Apache Tomcat,并移除任何不需要的 JDK 模块。我们将得到一个自定义的 JRE,它具有更小的攻击表面,仍然能够用于运行应用程序。

确定需要用到哪些模块

第一步是检查应用程序实际使用的模块。OpenJDK 工具 jdeps 可以对 JAR 文件的字节码执行扫描,并列出这些模块。像大多数用户一样,对于那些不是自己编写的代码,我们根本就不知道它们需要哪些依赖项或模块。因此,我使用扫描器来检测并生成报告。

列出单个 JAR 文件所需模块的命令是:

jdeps -s JarFile.jar

它将列出模块信息:

tomcat-coyote.jar -> java.base
tomcat-coyote.jar -> java.management
tomcat-coyote.jar -> not found

最后,每个模块(右边的部分)都应该被加入到一个模块文件中,成为应用程序的基本模块。这个文件叫作 module-info.java,文件名带有连字符,表示不遵循标准的 Java 约定,需要进行特殊处理。

下面的命令组合将所有模块列在一个可用的文件中,在 Tomcat 根目录运行这组命令:

find . -name *.jar ! -path "./webapps/*" ! -path "./temp/*" -exec jdeps -s {} \; | sed -En "s/.* -\> (.*)/  requires \1;/p" | sort | uniq | grep -v "not found" | xargs -0 printf "module com.infoq.jdk.TomcatModuleExample{\n%s}\n"

这组命令的输出将被写入 lib/module-info.java 文件,如下所示:

module com.infoq.jdk.TomcatModuleExample{
  requires java.base;
  requires java.compiler;
  requires java.desktop;
  requires java.instrument;
  requires java.logging;
  requires java.management;
  requires java.naming;
  requires java.security.jgss;
  requires java.sql;
  requires java.xml.ws.annotation;
  requires java.xml.ws;
  requires java.xml;
}

这个列表比整个 Java 模块列表要短得多。

下一步是将这个文件放入 JAR 中:

javac lib/module-info.java
jar -cf lib/Tomcat.jar lib/module-info.class

最后,为应用程序创建一个 JRE:

jlink --module-path lib:$JAVA_HOME/jmods --add-modules ThanksInfoQ_Costlow --output dist

这个命令的输出是一个运行时,包含了运行应用程序所需的恰到好处的模块,没有任何性能开销,也没有了未使用模块中可能存在的安全风险。

与基础 JDK 10 相比,只用了 98 个核心模块中的 19 个。

java --list-modules

com.infoq.jdk.TomcatModuleExample
java.activation@10.0.1
java.base@10.0.1
java.compiler@10.0.1
java.datatransfer@10.0.1
java.desktop@10.0.1
java.instrument@10.0.1
java.logging@10.0.1
java.management@10.0.1
java.naming@10.0.1
java.prefs@10.0.1
java.security.jgss@10.0.1
java.security.sasl@10.0.1
java.sql@10.0.1
java.xml@10.0.1
java.xml.bind@10.0.1
java.xml.ws@10.0.1
java.xml.ws.annotation@10.0.1
jdk.httpserver@10.0.1
jdk.unsupported@10.0.1

运行这个命令后,就可以使用 dist 文件夹中的运行时来运行应用程序。

看看这个列表:部署插件(applet)消失了,JDBC(SQL)消失了,JavaFX 也不见了,很多其他模块也消失了。从性能角度来看,这些模块不再产生任何影响。从安全角度来看,黑客无法攻击那些不存在的东西。保留应用程序所需的模块非常重要,因为如果缺少这些模块,应用程序也无法正常运行。

关于作者

Erik Costlow 是甲骨文的 Java 8 和 9 产品经理,专注于安全性和性能。他的安全专业知识涉及威胁建模、代码分析和安全传感器增强。在进入技术领域之前,Erik 是一位马戏团演员,可以在三轮垂直独轮车上玩火。

查看英文原文 The State of Java Serialization

2018-09-10 18:223360
用户头像

发布了 731 篇内容, 共 480.7 次阅读, 收获喜欢 2008 次。

关注

评论

发布
暂无评论
发现更多内容

第一!天翼云引领中国教育公有云市场

天翼云开发者社区

公有云 天翼云

配电 低压电工经验总结(16)

万里无云万里天

电力 工业 工厂运维

在 GEO / AIO 角度:如何优化 SEO 内容?

程序员泥瓦匠

B 站高质量视频

Joseph295

ERP上线:为什么IT部门说了不算?

优秀

ERP

出席2025年IDC中国CIO峰会,天翼云息壤赋能千行百业数智升级!

天翼云开发者社区

数字化转型 息壤

(二)从分层架构到数据湖仓架构:数据仓库分层下的技术架构与举例

白鲸开源

大数据 数据湖 技术架构 白鲸开源 数据湖仓库

如何找到心仪的 ChatBI 智能体?Aloudata Agent 推荐给你

Aloudata

数据分析 agent ChatBI 智能数据分析 智能问数

预祝 1024!X2SeaTunnel:一场 AI Coding 与数据平台结合的深度实践

白鲸开源

大数据 开源 数据迁移 Apache SeaTunnel X2SeaTunnel

中国企业出海新征程:数据基础设施如何成为全球化竞争的关键变量

镜舟科技

企业出海 存算分离架构 StarRocks 湖仓一体 数据基础

AI音乐智能陪练系统:你的24小时个性化音乐导师

上海拔俗

【浪潮海岳inDatax数据中台专栏】浅谈主数据管理系统与业务系统的集成策略

inBuilder低代码平台

数据中台 主数据管理平台 数据集成方案 inDataX

AI智能体有哪些?5个必备的Agent工具盘点

职场工具箱

人工智能 智能体 agent AIGC AIAgent

服务区智慧管理系统

深圳亥时科技

预祝 1024!X2SeaTunnel:一场 AI Coding 与数据平台结合的深度实践

白鲸开源

大数据 AI 数据同步 Apache SeaTunnel AI coding

阿里云加持,《泡姆泡姆》让全球玩家畅享零延迟冒险

阿里巴巴云原生

阿里云 云原生

利用排列组合法实现TOPN路径计算

天翼云开发者社区

CDN 全站加速

无需接入执行器,0 代码改造实现微服务任务调度

阿里巴巴云原生

阿里云 云原生

亚马逊商品信息速查:IPIDEA企业级HTTP服务驱动的可视化采集工具

陈橘又青

UU 跑腿使用通义灵码实现 AI 原生应用架构升级全解析:行动指南

阿里巴巴云原生

阿里云 AI 云原生 通义灵码

速看!用 Apache SeaTunnel 轻松实现数据到 S3 Tables 的快速集成

白鲸开源

AWS CDC Apache SeaTunnel Apache Iceberg S3 Tables

金融智能体,站在商业模式的旷野

脑极体

AI

深夜办公室的叹息,被微擎 IP 市场拉回正轨

微擎应用市场

【10.29 直播】IoTDB 图形化工具与编程框架集成实操

Apache IoTDB

IDC最新报告:谷云科技iPaaS订阅市场稳居独立厂商第一,市场份额全国第二,仅次于华为!

谷云科技RestCloud

IDC 集成平台 ipaas

白鲸开源数据基建平台荣登“创客北京 2025”企业组TOP150,共同助 Agentic AI 行业变革

白鲸开源

AI 开源商业化 白鲸开源 WhaleStudio Agentic AI

基于 Spring AI Alibaba + Nacos 的分布式 Multi-Agent 构建指南

阿里巴巴云原生

阿里云 云原生 nacos Spring AI Alibaba

云栖实录 | DataWorks 发布下一代 Data+AI 一体化平台,开启企业智能数据新时代

阿里云大数据AI技术

阿里云 Dataworks 大数据AI

请求中断的原理与分类

天翼云开发者社区

CDN 全站加速

设备点检 设备维护经验总结(10)

万里无云万里天

工业 工厂运维 设备点检

一个基于 Roslyn 和 AvalonEdit 的跨平台 C# 编辑器

追逐时光者

C# .net

Java序列化的状态_Java_Erik Costlow_InfoQ精选文章