此 Commit 这打开了后门
一项新功能已合并,用于处理用户上传的对象。所有功能均通过了测试,但几周后,渗透测试发现攻击者可以在服务器上执行命令;这是代码中隐藏的不安全反序列化漏洞造成的。从反序列化到远程代码执行的差距可能非常小,尤其是在未经验证就信任开源软件包或内部服务的序列化数据的情况下。
代码中的反序列化是什么?它为何危险?它隐藏在哪里?
从开发者角度来说,反序列化是什么?它是将结构化数据、JSON、XML、二进制格式或特定语言的序列化对象转换回内存中的对象的过程。
在其自己的, 反序列化 是无害且常见的,例如:
- 爪哇岛:使用 对象输入流
- Python
:使用加载数据 pickle.load
- Node.js:使用以下方式解析 JSON JSON.解析
当对不受信任的数据进行反序列化且未经验证时,风险就会显现。攻击者可以精心设计触发小工具链的输入,并以非预期的方式利用现有的代码路径,从而导致远程代码执行。
不安全 反序列化 通常出现在:
- 开源软件包 不安全的默认值
- 自定义代码 假设序列化输入是可信的
- 第三方API 返回未经验证的序列化对象
- 构建工件 的条件,如
- 爪哇岛 .ser 包含预序列化对象的文件。
- Python
.pkl 机器学习工作流中的模型文件。
- 嵌入在 Docker 镜像或部署容器中的序列化配置对象
- 爪哇岛 .ser 包含预序列化对象的文件。
- 测试治具 的条件,如
- 从生产快照复制的旧序列化测试数据。
- 从外部存储库下载的序列化有效载荷用于性能或回归测试。
- 从生产快照复制的旧序列化测试数据。
这些文件可以引入存储库并在测试或部署期间自动加载,从而触发不安全的 反序列化 in CI/CD pipeline在代码投入生产之前。
从不安全的反序列化到远程代码执行:攻击路径
不安全反序列化的利用链通常遵循以下模式之一:
- 不受信任的输入进入应用程序。
- 不安全的反序列化会不受限制地重新创建对象。
- 小工具链以意想不到的方式触发现有功能。
- 攻击者提升权限,实现远程代码执行。
变种:
- Java 小工具链利用 Apache Commons 等旧库。
- Python
.pkl 嵌入恶意对象的模型加载。
- Node.js JSON 解析 评估() 或动态导入。
推广模式:
Untrusted Input → Deserialization → Gadget Chain → Remote Code Execution
如何在合并前发现不安全的反序列化
在代码合并之前捕获不安全的反序列化漏洞比在部署后修复它的成本要低得多。自动化分析和主动测试相结合是最佳方案:
- 静态应用程序安全测试(SAST):
- 配置扫描仪来检测有风险的 API,例如 对象输入流, pickle.load和 YAML.load 没有安全装载机。
- 扫描源代码和构建/测试工件以查找不安全 反序列化 图案。
- 直接显示结果 pull requests 因此开发人员可以在合并之前解决这些问题。
- 配置扫描仪来检测有风险的 API,例如 对象输入流, pickle.load和 YAML.load 没有安全装载机。
- CI/CD 之路:
工作流程示例:
sql
Commit → SAST scan → PR alert → Fix before merge
- 对关键的不安全反序列化发现进行阻止合并,以防止不安全的代码到达生产分支。
- 使用模拟恶意输入的单元测试:
- 创建 无害、受控的有效载荷 模仿常见的序列化攻击对象。
- 测试应用程序如何处理它们;它应该拒绝、清理或记录输入,而不是盲目地处理它。
- 将这些测试纳入自动化 pipeline 因此它们在每个 PR 上运行,尽早捕获不安全的反序列化行为。
- 确保测试有效负载不可执行并且可以安全地存储在存储库中,纯粹关注检测逻辑。
- 创建 无害、受控的有效载荷 模仿常见的序列化攻击对象。
这种分层方法将自动扫描与开发人员拥有的测试相结合,确保在不安全的反序列化路径成为远程代码执行漏洞之前就将其识别并删除。
开发人员的预防策略:阻止反序列化成为远程代码执行
- 信任边界:仅从经过身份验证和验证的来源进行反序列化。
- 安全的 API:
- Java:通过验证确保库的安全。
- Python:使用 json.loads() 超过 pickle.loads() 在可能的情况。
- Node.js:避免 评估() 或动态代码执行。
- Java:通过验证确保库的安全。
- 允许列表和架构:限制允许的对象类型。强制使用 JSON 模式。
- 依赖卫生:监控提及反序列化或远程代码执行的 CVE。
- 代码审查: 添加 反序列化 对 PR 审查模板进行安全检查。
工具说明:类似工具 西吉尼 在合并之前扫描代码和依赖项是否存在不安全的反序列化,识别高风险区域,以便开发人员尽早修复它们。
跨语言检测模式示例 (安全伪代码)
以下所有示例都是经过净化的伪代码,显示了检测模式,而不是有效的漏洞:
Java – 检测不安全的 API 使用:
java
// BAD: Accepting untrusted input without validation
ObjectInputStream in = new ObjectInputStream(userInputStream);
Object obj = in.readObject(); // Unsafe - no class type checks
// GOOD: Validate allowed classes before processing
if (allowedClasses.contains(obj.getClass().getName())) {
process(obj); // Safe processing of approved classes
}
Python – 避免不安全的反序列化:
python
import pickle
# BAD: Loading untrusted serialized data directly
data = pickle.loads(untrusted_input) # Unsafe - arbitrary object execution risk
# GOOD: Use JSON with schema validation
import json
data = json.loads(untrusted_input) # Safe when validated against schema
Node.js – 防止动态代码执行:
javascript
// BAD: Executing code from parsed data
let obj = JSON.parse(untrustedInput);
eval(obj.code); // Unsafe - allows arbitrary code execution
// GOOD: Use fixed logic without dynamic execution
let safeObj = JSON.parse(untrustedInput);
process(safeObj); // Handle only expected properties and values
DevSecOps 中的自动检测 Pipelines:在反序列化进入生产环境之前捕获它
自动检测不安全的反序列化可确保 发现并修复漏洞 以免在生产环境中导致远程代码执行。
Pipeline 扫描
- 运行 SAST 源代码、配置文件和构建工件 commit.
- 检测应用程序代码和 依赖.
文物检验
- Scan 扫描 .ser、.pkl, 在部署甚至运行测试之前,请检查其他序列化文件中是否存在不安全模式。
Pull Request 闭塞
- 如果检测到不安全的反序列化,则阻止合并。
- 在 PR 中显示可操作的反馈以加快补救速度。
单元测试执行
- 在单元测试中加入模拟恶意输入 CI/CD pipeline
- 如果应用程序处理不安全的序列化数据而不是拒绝它,则构建失败。
在不削弱规则的情况下避免误报
- 不要禁用检测规则来“静音”警报;这可能会让真正不安全的反序列化不被检测到。
- 对已知的安全模式或依赖项使用受控白名单(允许列表)。
- 在批准白名单条目之前需要进行安全验证。
- 将白名单置于版本控制之下并定期审查,以确保所有例外情况仍然合理且安全。
Xygeni 的作用
- 直接集成到 CI/CD pipeline扫描源代码并构建工件。
- 在生命周期早期检测不安全的反序列化模式和有风险的依赖关系。
- 支持基于策略的白名单和强制性安全审查,平衡检测准确性和开发人员的工作效率。
通过安全反序列化预防远程代码执行
不安全的反序列化可能不被察觉,直到它成为远程代码执行的直接途径。防止它需要:
- 了解什么是反序列化以及如何滥用它。
- 在开发工作流程中嵌入自动检测。
- 定期审查测试中使用的依赖项、构建工件和序列化数据。
Xygeni 在此过程中的实际作用:
- 源代码扫描:在代码合并之前识别多种语言中不安全的反序列化模式。
- 工件和依赖关系分析:检测有风险的序列化文件(.ser、.pkl, 嵌入式配置)和已知漏洞的第三方组件。
- 基于策略的控制:支持具有安全验证的受控允许列表,确保必要的例外不会带来真正的风险。
- 开发人员的反馈:标记内部不安全反序列化的确切位置和原因 pull requests,允许开发人员立即修复问题并通过重新扫描确认缓解措施。
通过将这些检查直接集成到 CI/CD,团队可以发现并修复不安全 在它有机会升级为生产中的远程代码执行之前,对其进行反序列化。





