前言
今天碰到一道需要SSTI注入的题,百度了一下,发现大多数关于SSTI的基础文章上下文的连贯性并不是很好,于是便有了此文。
在阅读此文前,我假设您已具有Python和Html基础.
什么是SSTI(服务器模板注入)
SSTI 即服务端模板注入攻击,服务端接受用户输入,将其作为 Web 应用模板的一部分渲染编译后执行了恶意内容,导致敏感信息泄露,代码执行等.(与Xss原理大致相似)
什么是Flask
Flask是一个用Python编写的Web应用程序框架.它由Armin Ronacher 开发,他领导一个名为Pocco的国际Python爱好者团队.Flask基于Werkzeug WSGI工具包和Jinja2模板引擎.两者都是Pocco项目.
一个Flask应用是如何跑起来的
运行虚拟环境:
Flask是运行在虚拟环境(VirtualEnv)中的,VirtualEnv是一个虚拟的Python环境构建器。它可以帮助用户并行创建多个Python环境.因此,它可以避免不同版本的库之间的兼容性问题.(最好不要使用python3.8运行,以减少不兼容的可能性)
pip install virtualenv
virtualenv venv
cd ./venv/Scripts
activate.bat
如何跑起来:
先来看一个简单的小demo
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello World'
if __name__ == '__main__':
app.run()
首先是导入flask框架,这是必须的.
Flask构造函数使用当前模块(__name __)的名称作为参数.
Flask类的route()函数是一个装饰器,它告诉应用程序哪个URL应该调用相关的函数.
app.route(rule, options)
rule参数代表该路径与哪个函数进行绑定.如上图中的小demo,@app.route(‘/’)是函数hello_world的装饰器,即代表网站的根路径与函数hello_world绑定,在访问http://127.0.0.1/的时候,就会触发函数hello_world.
最后,Flask类的run()方法在本地开发服务器的虚拟环境上运行应用程序
Flask模板
Flask模板的基本使用
在项目下创建 templates 文件夹,用于存放所有模板文件,并在目录下创建一个模板文件 html 文件 hello.html
在env这个虚拟环境中,render_template()这个函数会自动寻找在同级目录下templates文件夹下的文件.
也就是说render_template(‘hello.html’)等价于render_template(‘./templates/hello.html’)
模板变量(重点)
传入字符串到html模板中


一个存在SSTI漏洞的demo
在ctf中基于python开发的web,存在SSTI漏洞的一般都使用的是Jianja2模板引擎
什么是Jianja2引擎
Jinja2是Python下一个被广泛应用的模版引擎,他的设计思想来源于Django的模板引擎,并扩展了其语法和一系列强大的功能。.中最显著的一个是增加了沙箱执行功能和可选的自动转义功能.
注意这一句话,可选的自动转义功能,即默认不进行转义.这为我们进行SSTI注入创造了条件.
test.py
from flask import Flask, request
from jinja2 import Template
app = Flask(__name__)
@app.route('/')
def index():
id = request.args.get('id')
t = Template('''
<html>
<head>
<title></title>
</head>
<body>
<h1>%s</h1>
</body>
</html>
''' % (id))
return t.render()
app.run()
表达式果然被执行了.
一个不存在SSTI漏洞的demo
test.py
from flask import Flask, request,render_template
app = Flask(__name__)
@app.route('/')
def index():
id = request.args.get('id')
return render_template('hello.html',id=id)
app.run()
使用request对象,处理来自客户端url中id的数据.
request.args.get() 解析查询字符串的内容,它是问号(?)之后的URL的一部分。
html模板
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{{id}}
</body>
</html>

如何对存有SSTI漏洞的flask进行命令执行
这里一道简单的ctf练习题为例.你可能会疑惑,没有导入OS模块,也没有system()类似的函数怎么能进行命令执行呢?
命令执行的基本流程:获取基本类->获取基本类的子类->在子类中找到关于命令执行和文件读写的模块
获取基本类
我们都知道在python中一切皆为对象.
使用__bases__获取基本类
Python 为所有类都提供了一个 bases属性,通过该属性可以查看该类的所有直接父类,该属性返回所有直接父类组成的元组,注意是直接父类.
''.__class__.__bases__
可以看到str的父类是basestring
使用__mro__同样也可以查找父类,不同的是__mro__获取的是类的调用顺序

获取基本类的子类
”.__class__.__mro__[2].__subclasses__()
在子类中找到关于命令执行和文件读写的模块
在上图中我们要找到’os’ 所在的’site._Printer’类,它的索引为[71]
使用__subclasses__()[71].__init__.__globals__[‘os’].popen(‘cmd’).read(),运行命令并得到回显结果
总结
SSTI模板注入的漏洞好像并不太常见,以后遇到再更新吧。
来源:freebuf.com 2021-07-06 13:40:00 by: 菜头想学安全






在子类中找到关于命令执行和文件读写的模块