赞
踩
服务器模板注入 (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 }},而没有服务器的敏感信息了。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。