欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

常见的web攻击方式之服务器端模板注入

程序员文章站 2022-07-15 14:05:25
...

服务器模板注入 (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,显示的结果为:
常见的web攻击方式之服务器端模板注入
然后我们尝试一些良性的输入,访问 http://127.0.0.1:5000/login?name=bob,结果为:
常见的web攻击方式之服务器端模板注入
下面演示一些攻击者的输入,比如访问 http://127.0.0.1:5000/login?name=bob{{person.secret}},你会发现页面中除了显示了 Hello bob!之外,连同秘钥也一起被显示了。
常见的web攻击方式之服务器端模板注入
由于在模板中使用的是 % 字符串模板,所以它对任何传递给 python 表达式的内容进行了求值。在 Flask 模板语言中,我们传递了 {{ person.secret }},它对字典 person 中保密的键值进行了求值,这泄露了应用程序的秘钥。
我们还可以执行更强大的攻击,访问 http://127.0.0.1:5000/login?name={% for item in person %}<p>{{ item, person[item] }}</p>{% endfor %},你会发现整个 person 字典中的内容全被显示在页面中了。
常见的web攻击方式之服务器端模板注入
即使攻击者想要获取服务器端敏感的配置参数,也可以通过 {{ config }} 的名称采纳数来获取,访问 http://127.0.0.1:5000/login?name={{%20config%20}},你会发现服务器的配置显示在页面中了。
常见的web攻击方式之服务器端模板注入
那么如何避免敏感信息泄露呢,在这个情况下,解决的方法是使用模板中我们需要的特定变量,而不是直接使用 %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 }},而没有服务器的敏感信息了。
常见的web攻击方式之服务器端模板注入