常见的web攻击方式之服务器端模板注入
服务器模板注入 (SSTI ) 是一种利用公共 Web 框架的服务器端模板作为攻击媒介的攻击方式,该攻击利用了嵌入模板的用户输入方式的弱点。SSTI 攻击可以用来找出 Web 应用程序的内容结构。下面举一个例子:
使用 Flask 构建一个基本的 Web 应用程序:
from flask import Flask
from flask import request, render_template_string, render_template
app = Flask(__name__)
@app.route('/login')
def hello_ssti():
person = {
'name': 'hello',
'secret': '7d793037a0760186574b0282f2f435e7'
}
if request.args.get('name'):
person['name'] = request.args.get('name')
template = '<h2>Hello %s!</h2>' % person['name']
return render_template_string(template, person=person)
if __name__ == "__main__":
app.run(debug=True)
运行上面这段代码,并在浏览器中访问 http://127.0.0.1:5000/login
,显示的结果为:
然后我们尝试一些良性的输入,访问 http://127.0.0.1:5000/login?name=bob
,结果为:
下面演示一些攻击者的输入,比如访问 http://127.0.0.1:5000/login?name=bob{{person.secret}}
,你会发现页面中除了显示了 Hello bob!之外,连同秘钥也一起被显示了。
由于在模板中使用的是 % 字符串模板,所以它对任何传递给 python 表达式的内容进行了求值。在 Flask 模板语言中,我们传递了 {{ person.secret }},它对字典 person 中保密的键值进行了求值,这泄露了应用程序的秘钥。
我们还可以执行更强大的攻击,访问 http://127.0.0.1:5000/login?name={% for item in person %}<p>{{ item, person[item] }}</p>{% endfor %}
,你会发现整个 person 字典中的内容全被显示在页面中了。
即使攻击者想要获取服务器端敏感的配置参数,也可以通过 {{ config }} 的名称采纳数来获取,访问 http://127.0.0.1:5000/login?name={{%20config%20}}
,你会发现服务器的配置显示在页面中了。
那么如何避免敏感信息泄露呢,在这个情况下,解决的方法是使用模板中我们需要的特定变量,而不是直接使用 %s。
比如我们将 flask 代码改为:
from flask import Flask
from flask import request, render_template_string, render_template
app = Flask(__name__)
@app.route('/login')
def hello_ssti():
person = {
'name': 'world',
'secret': '7d793037a0760186574b0282f2f435e7'
}
if request.args.get('name'):
person['name'] = request.args.get('name')
template = '<h2>Hello {{ person.name }}!</h2>'
return render_template_string(template, person=person)
if __name__ == "__main__":
app.run(debug=True)
然后我们在尝试访问 http://127.0.0.1:5000/login?name={{%20config%20}}
,你会发现显示的结果只是字符串 {{ config }},而没有服务器的敏感信息了。
上一篇: centos6 安装 jenkins
推荐阅读