原型链污染学习

原型链污染(更新中)

python

python原型链污染

简介:

Python原型链污染是对类属性值的污染,且只能对类的属性来进行污染而不能够污染类的方法。

代码

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)

hasatter(object,name)

两个参数,一个object对象,另一个是字符串。如果字符串是对象的一个属性,则返回True,否则返回False。

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
def merge(src, dst):
"""
递归地将源字典 `src` 合并到目标对象 `dst` 中。

参数:
- src (dict): 源字典,包含要合并的键值对。
- dst (object): 目标对象,可以是字典或具有属性的对象。

说明:
- 如果 `dst` 是字典,则将 `src` 中的键值对合并到 `dst` 中。
- 如果 `dst` 是对象,则将 `src` 中的键值对作为属性合并到 `dst` 中。
- 如果 `src` 中的值是字典且 `dst` 中对应的值也是字典,则递归合并。
"""
for k, v in src.items():
# 检查目标对象是否支持字典操作(即是否有 __getitem__ 方法)
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)
  • 可以通过对src的控制,来实现dst值的控制,达到污染目的。

示例用法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 合并到字典
dst_dict = {'a': 1, 'b': {'c': 2}}
src_dict = {'b': {'d': 3}, 'e': 4}
merge(src_dict, dst_dict)
print(dst_dict) # 输出: {'a': 1, 'b': {'c': 2, 'd': 3}, 'e': 4}

# 合并到对象
class MyClass:
pass

dst_obj = MyClass()
dst_obj.a = 1
dst_obj.b = MyClass()
dst_obj.b.c = 2

src_dict = {'b': {'d': 3}, 'e': 4}
merge(src_dict, dst_obj)
print(dst_obj.a) # 输出: 1
print(dst_obj.b.c) # 输出: 2
print(dst_obj.b.d) # 输出: 3
print(dst_obj.e) # 输出: 4

解释:

  • merge 函数可以处理字典到字典的合并,也可以处理字典到对象的合并。
  • 如果目标对象是字典,则直接更新字典中的键值对。
  • 如果目标对象是普通对象,则将字典中的键值对作为属性设置到对象中。
  • 如果遇到嵌套的字典,则会递归地进行合并。

image-20250117003359765


原型链污染学习
https://xu17.top/2025/01/17/原型链污染/
作者
XU17
发布于
2025年1月17日
许可协议
XU17