SSTI模版注入
文章目录
1 SSTI服务器端模板注入
SSTI服务器端模板注入(Server-Side Template Injection),同SQL注入、XSS注入等,都是从用户获取一个输入,由于代码不规范或信任了用户输入,后端的渲染处理上进行了语句的拼接,而导致了服务端模板注入。
SSTI利用的是网站模板引擎,主要针对python、php、java的一些网站处理框架,比如Python的jinja2、mako、tornado、django,php的smarty twig,java的jade、velocity,当这些框架对运用渲染函数生成html的时候会出现SSTI的问题。
现在网上提起的比较多的是Python的网站。
2 模板引擎
模板引擎(这里特指用于Web开发的模板引擎)是为了使用户界面与业务数据(内容)分离而产生的,它可以生成特定格式的文档,用于网站的模板引擎就会生成一个标准的HTML文档。
模板引擎可以让(网站)程序实现界面与数据分离,业务代码与逻辑代码的分离,这就大大提升了开发效率,良好的设计也使得代码重用变得更加容易。
模板引擎可以让(网站)程序实现界面与数据分离,业务代码与逻辑代码的分离,这大大提升了开发效率,良好的设计也使得代码重用变得更加容易。但是往往新的开发都会导致一些安全问题,虽然模板引擎会提供沙箱机制,但同样存在沙箱逃逸技术来绕过。
拿到数据,塞到模板里,然后让渲染引擎将赛进去的东西生成 html 的文本,返回给浏览器,这样做的好处展示数据快,大大提升效率。
后端渲染:浏览器会直接接收到经过服务器计算之后的呈现给用户的最终的HTML字符串,计算就是服务器后端经过解析服务器端的模板来完成的,后端渲染的好处是对前端浏览器的压力较小,主要任务在服务器端就已经完成。
前端渲染:前端渲染相反,是浏览器从服务器得到信息,可能是json等数据包封装的数据,也可能是html代码,他都是由浏览器前端来解析渲染成html的人们可视化的代码而呈现在用户面前,好处是对于服务器后端压力较小,主要渲染在用户的客户端完成。
3 举例
这里举个简单的例子来简析模板渲染。
前端代码:
<html>
<div>{{name}}</div>
</html>
我们想要在<div>
标签里呈现不同的信息,或者说是用户输入的信息,但是{{name}}我们不知道用户输入的是什么,就用一些url或者cookie包含的信息,渲染到what变量里,呈现给用户的为:
<html>
<div>张三</div>
</html>
3.1 以python的flask为例
python后端代码:
from flask import Flask
from flask import render_template
from flask import request
from flask import render_template_string
app = Flask(__name__)
@app.route('/')
@app.route('/index')#我们访问/或者/index都会跳转
def index():
user = {'name': '小猪佩奇'}#传入一个字典数组
return render_template("index.html",user=user)
if __name__ == '__main__':
app.debug = True
app.run()
前端界面:
<html>
<body>
<h1>Hello, {{user.name}}!</h1>
</body>
</html>
显示的是,Hello, 小猪佩奇!
4 绕过tips
4.1 过滤[]等括号
使用gititem绕过。如原poc
{{"".class.bases[0]}}
绕过后
{{"".class.bases.getitem(0)}}
4.2 过滤了subclasses
拼凑法
原poc
{{"".class.bases[0].subclasses()}}
绕过
{{"".class.bases[0]['subcla'+'sses']}}
4.3 过滤class
使用session
原poc
{{session['cla'+'ss'].bases[0].bases[0].bases[0].bases[0].subclasses()[118]}}
多个bases[0]是因为一直在向上找object类。使用mro就会很方便
{{session['__cla'+'ss__'].__mro__[12]}}
或者
{{request['__cl'+'ass__'].__mro__[12]}}
5 总结
实战中几乎不会出现ssti模板注入,或者说很少,大多出现在python 的ctf中。
每一个模板引擎都有着自己的语法,Payload 的构造需要针对各类模板引擎制定其不同的扫描规则,就如同 SQL 注入中有着不同的数据库类型一样。更改请求参数使之承载含有模板引擎语法的 Payload,通过页面渲染返回的内容检测承载的 Payload 是否有得到编译解析,不同的引擎不同的解析。所以我们在挖掘之前有必要对网站的web框架进行检查,否则很多时候{{}}并没有用,导致错误判断。
接下来附张图,实战中要测试重点是看一些url的可控,比如url输入什么就输出什么。
参考文章:
https://xz.aliyun.com/t/3679#toc-11
https://blog.csdn.net/zz_Caleb/article/details/96480967