Flask服务端对请求表单先pickle.dumps再loads是否存在RCE风险?
免责声明:本问题仅用于合法安全研究,所有测试均在本人自有虚拟机内完成,不涉及任何恶意用途!
结论
你描述的「服务端先对request.form执行pickle.dumps(),再对序列化结果执行pickle.loads()」的流程默认不存在RCE漏洞,具体原因如下:
- Flask 中
request.form是ImmutableMultiDict类型,所有通过表单提交的字段的键、值都会被解析为纯字符串,无法传递带有自定义__reduce__方法的恶意类实例。 - 你假设的「存在某字符串经过
pickle.dumps()序列化后,和pickle.dumps(RCE())结果完全一致」的情况不可能实现:pickle序列化字符串时会固定带上字符串类型标识、长度前缀等元数据,序列化结果和类实例的序列化结果结构完全不同,不可能重合。 - 你测试时第一个示例无法触发漏洞的原因也在此:客户端试图传递RCE实例,但是经过HTTP表单提交后,到服务端只会被解析为普通字符串,
pickle.dumps只是对这个字符串做序列化,不会还原成恶意类,后续loads自然也不会执行恶意代码。 - 只有当服务端主动把表单拿到的字符串作为参数传给
pickle.loads()时,才会触发漏洞,也就是你给出的第二个可复现漏洞的场景。
补充说明
如果要让该流程出现风险,必须存在二次反序列化逻辑:比如pickle.loads(test)得到的结果里的某个字段,又被服务端拿去执行了一次pickle.loads,此时你只要把恶意序列化串作为表单字段值提交即可触发漏洞。无该逻辑的前提下,该流程不存在RCE风险。
内容的提问来源于stack exchange,提问作者user1823456
相关产品推荐
相关产品推荐

