defmerge(src, dst): # src为原字典,dst为目标字典 # Recursive merge function for k, v in src.items(): ifhasattr(dst, '__getitem__'): # 键值对字典形式 if dst.get(k) andtype(v) == dict: merge(v, dst.get(k)) # 递归到字典最后一层 else: dst[k] = v elifhasattr(dst, k) andtype(v) == dict: # class形式 merge(v, getattr(dst, k)) # 递归到最终的父类 else: setattr(dst, k, v)
我们可以通过对src的控制,来控制dst的值,来达到我们污染的目的
注意Object类型不能被污染, 会直接报错
例子
classfather: secret = "hello" classson_a(father): pass classson_b(father): pass defmerge(src, dst): for k, v in src.items(): ifhasattr(dst, '__getitem__'): if dst.get(k) andtype(v) == dict: merge(v, dst.get(k)) else: dst[k] = v elifhasattr(dst, k) andtype(v) == dict: merge(v, getattr(dst, k)) else: setattr(dst, k, v) instance = son_b() payload = { "__class__" : { "__base__" : { "secret" : "world" } } } print(father.secret) # hello print(son_a.secret) # hello print(instance.secret) # hello merge(payload, instance) print(son_a.secret) # world print(instance.secret) # world print(father.secret) # world
setattr函数如下
defsetattr(x, y, v): # real signature unknown; restored from __doc__ """ Sets the named attribute on the given object to the specified value. setattr(x, 'y', v) is equivalent to ``x.y = v'' """ pass