查看: 18|回复: 0

通俗读懂序列化与反序列化:程序世界的打包与拆包

[复制链接]

1813

主题

5

回帖

5516

积分

超级版主

积分
5516
发表于 6 天前 | 显示全部楼层 |阅读模式
做后端、写接口、做分布式开发,一定会碰到序列化、反序列化。很多初学者对这两个名词感到抽象,其实它就是程序世界的数据打包拆包机制。内存中的程序对象不能直接存文件、跨网络传输,序列化就负责把对象转成可流通格式;反序列化再把字节 / 文本还原成程序对象。但光鲜的功能背后,隐藏高危安全漏洞,也是 OWASP 重点收录的安全风险点。



一、什么是序列化、反序列化

序列化(Serialize):把内存里的对象、数组、结构体,转换成字符串、字节流,变成可以保存到文件、数据库、缓存,或者通过网络传输的数据格式。反序列化(Deserialize):收到字节 / 文本数据之后,重新还原为程序内存中可调用的对象、结构体。
通俗类比:程序内存中的对象,好比工厂组装完整的精密模型,只能放在车间内部,不能直接快递邮寄。
  • 序列化 = 拆解模型,写好组装说明书,打包成快递包裹,可以快递运输、存放仓库。
  • 反序列化 = 收到包裹,对照说明书,重新把零件组装回完整模型,恢复成程序可以调用的对象。
为什么必须做这套转换?对象只存活在程序内存里,进程关闭数据就消失,无法直接跨机器、跨进程持久保存,也不能直接走网络传输。举个业务例子:程序内存有一个用户对象,包含用户名、年龄、角色、登录状态。想要把这个对象通过 HTTP 接口传给前端,或者存入 Redis 缓存、写入本地文件,不能直接把内存对象丢出去,必须先序列化。前端 / 另一台服务拿到字符串字节,再执行反序列化,重建用户对象,业务代码才可以读取里面的属性。
二、开发中 5 大典型使用场景

  • 前后端接口通信:后端把业务对象序列化为 JSON 返回前端;前端拿到 JSON,解析还原成页面可用的数据结构。这是 Web 开发最常见场景。
  • 缓存存储(Redis 等):会话信息、商品数据、权限配置序列化存入缓存;程序读取缓存数据后反序列化,减少频繁查询数据库。
  • 消息队列 MQ:订单事件、业务消息序列化为字节送入 Kafka/RabbitMQ;消费端拿到数据反序列化执行业务逻辑。
  • 本地文件持久化:程序配置、运行状态、模型参数序列化写入磁盘文件,下次启动读取文件恢复状态。
  • RPC 远程调用:gRPC 等远程框架,把调用参数序列化通过网络发送,接收方反序列化,执行函数再把返回值序列化传回调用方。
三、主流序列化格式对比

分为文本可读格式、二进制格式,还有各编程语言专属原生序列化工具,不同格式取舍在可读性、体积、速度、跨语言、安全性之间。
文本格式(人可以直接阅读编辑)

  • JSONWeb 行业事实标准,可读性强,跨语言支持极好;广泛用于 HTTP 接口、简单配置。缺点:二进制、日期类型表达能力有限,序列化之后体积偏大。
  • XML早期企业系统、WebService 大量使用;标签冗长,体积大,现在接口领域逐步被 JSON 替代,遗留系统还会见到。存在 XXE 外部实体注入漏洞风险。
  • YAML大量用于配置文件、CI/CD 流水线;书写简洁,可读性高。但语法缩进严格,复杂嵌套容易出错。
二进制格式(机器高效解析,人不可直接阅读)

  • Protobuf(Protocol Buffers)谷歌开源,需要预先定义.proto协议 schema;体积小、解析速度极快,跨语言,gRPC 默认格式。未知字段直接忽略,安全性较好,高性能微服务 RPC 大量使用。
  • MessagePack可以理解成二进制版 JSON,不需要预先定义 schema;比 JSON 更紧凑。注意:开启Typeless无类型模式会带来严重安全风险。
语言原生序列化(⚠️高风险)

Python pickle、Java ObjectInputStream、PHP unserialize、.NET BinaryFormatter。
特点:可以完整还原复杂对象、执行对象回调方法;但是只适配本门语言,跨语言基本不可用,反序列化不可信输入极易触发高危漏洞。
形象比喻:
  • JSON/YAML:公开通用说明书,所有人都看得懂;
  • Protobuf/MessagePack:压缩加密的专业说明书,体积小跑得快;
  • 语言原生序列化:厂家私有专属配件,自家机器能用,外人看不懂,收到恶意包裹会触发机关。
四、重点:反序列化的致命安全风险

这是很多新手容易忽略的大坑。普通解析 JSON 只是读取字段数值。但是语言原生反序列化,重建对象的时候,会自动调用构造函数、析构函数、魔术回调方法。类比快递:正常包裹拆开取出商品;恶意包裹拆开瞬间,包裹内部暗藏机关直接触发爆炸。
攻击者构造恶意序列化字节流,服务端进行反序列化,就会出现严重后果:
  • 远程代码执行 RCE,服务器被完全接管;
  • 任意读取服务器本地文件;
  • 权限绕过、业务逻辑篡改;
  • 拒绝服务(深度嵌套造成栈溢出、内存耗尽)。
Java ysoserial 工具、Python pickle 漏洞、PHP unserialize 漏洞,都是互联网历史上大名鼎鼎的反序列化攻击案例,被 OWASP 列入软件完整性风险 A08,CWE‑502 漏洞编号。
重点提醒:不要以为只有 HTTP 接口才会遇到风险。缓存 Redis、消息队列 MQ、Cookie、本地文件里的序列化数据,一样可能被篡改,同样存在攻击面。
五、安全防护最佳实践

  • 核心原则:绝不反序列化不受信任的外部可控输入。外部用户提交数据优先选择 JSON 这类纯数据格式,只解析成字典、普通结构体,不要直接还原完整业务对象。
  • 如果业务不得不使用语言原生序列化:开启类白名单机制,只允许反序列化明确安全的类,禁止任意类实例化。
  • 序列化传输存储的数据,做 HMAC 签名校验;先校验签名完整性,校验通过之后再做反序列化,防止内容被篡改。
  • 及时升级框架、依赖库,修补已知反序列化相关漏洞。
  • 尽量禁用多态类型自动解析功能(例如 Newtonsoft 的 TypeNameHandling),不要让外部数据指定要实例化哪一个类。
  • 遵循最小权限原则,即便漏洞触发,尽可能降低攻击者能够造成的破坏。
常见认知误区澄清

  • 误区:序列化 = 把对象转 JSON纠正:JSON 只是众多序列化格式之一;Protobuf、pickle、XML 都属于序列化,JSON 是文本序列化,pickle 是语言原生二进制序列化。
  • 误区:只要数据来自内网 MQ、Redis 缓存就一定安全纠正:内网组件也可能被入侵篡改,不能默认可信,依旧建议做签名校验。
  • 误区:反序列化漏洞只出现在 Java 语言纠正:Python、PHP、.NET、Ruby 都存在原生反序列化高危风险。
  • 误区:只要反序列化完成之后再校验字段就安全纠正:危险代码在反序列化解析阶段就执行完毕,等解析完成再校验已经晚了。
结语

序列化解决的核心问题:让内存中的对象可以离开程序,实现网络传输、持久化存储,是接口、缓存、消息队列、RPC 分布式体系的基础能力。
但要牢牢记住一件事:序列化只是打包;反序列化拆包不等于单纯读取数据,部分格式拆包的过程可以自动执行代码。选型上,对外交互优先选用 JSON、Protobuf 这类安全的通用格式;尽量避免直接把用户可控输入交给语言原生反序列化接口。

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|天翼网

相关侵权、举报、投诉及建议等,请发 E-mail:2026@typc.net

Powered by Discuz! X5.0 © 2001-2026 Discuz! Team.|晋ICP备2026008270号-1|晋公网安备14010602111293号

QQ客服返回顶部