导语:CSRF(Cross-site request forgery)跨站请求伪造,也被称为“One Click Attack”或者Session Riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。攻击者可以使认证用户提交表单数据给执行管理功能或修改个人设置的web服务。

CSRF(Cross-site request forgery)跨站请求伪造,也被称为“One Click Attack”或者Session Riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。攻击者可以使认证用户提交表单数据给执行管理功能或修改个人设置的web服务。

错误配置

在一个典型的攻击场景中,有合法网站现存会话的受害者被诱骗访问恶意站点,使用用户的会话session来触发一些恶意动作。下面的代码段就是攻击者在没有CSRF Token保护的站点执行攻击的例子,代码保存在攻击者的站点上,但可以在合法用户站点上执行。

<!-- bank.evil.com site -->
<html>
    <head>
        <title>Malicious website</title>
    </head>
    <body>
        <!-- hehe i'm gonna be rich -->
        <h1>Enter your name to find out your funny nickname:</h1>
        <form action="http://legitimate-site.com/transferfunds" method="POST">
            Your name: <input type="text"><br/>
            <input type="submit">
            <input type="hidden" name="amount" value="10000">
            <input type="hidden" name="recipient" value="evil_hacker">
        </form>
    </body>
</html>

为了防止这类攻击的产生,在每个请求中都要加入加密的安全随机数(nonce)或哈希值,在执行敏感功能前都要进行验证。

正确配置

大多数web框架都提供能生成安全CSRF token的中间件,主要有:

Django

1.在配置文件MIDDLEWARE_CLASSES中加入django.middleware.csrf.CsrfViewMiddleware;

2.在所有用户可以提交POST数据的模板中加入特殊的csrf_token tag;

<form action="." method="POST">
    {% csrf_token %}
    <!-- other form fields -->
</form>

3. 确保CSRF上下文被传递给所有表达的视图。如果之前没有使用RequestContext就要手动设置;

具体可以参考Django文档 <https://docs.djangoproject.com/en/1.8/ref/csrf/#using-csrf>

Flask-WTF

在不进行任何配置的情况下,flask_wtf.Form就是一个可以保护CSRF的安全会话表单。

表单定义如下:

# form.py
from flask_wtf import Form
from wtforms import StringField
from wtforms.validators import DataRequired
 
class PersonForm(Form):
    name = StringField('name', validators=[DataRequired()])
You need only include the form.hidden_tag() in your template definition:
<!-- view.html -->
<form method="POST" action="{{ url_for('submit') }}">
    {{ form.hidden_tag() }}
    {{ form.name.label }} {{ form.name(size=20 }}
    <input type="submit" value="ok">
</form>

在任何需要验证提交的表单时,CSRF token会自动被验证。

# view.py
from form import PersonForm
 
@app.route("/submit", methods=("GET", "POST"))
def submit():
    f = PersonForm()
    if form.validate_on_submit():
        # csrf token also validated
        return redirect("/")
    return render_template("view.html", form=f)

CSRF攻击的结果

1.劫持合法的用户会话;

2.可以访问特权服务和功能;

3.可以修改受保护的数据。

源链接

Hacking more

...