动态

详情 返回 返回

安全測試之 CSRF 跨站點請求偽造 - 动态 详情

原文由發表於TesterHome社區,點擊原文鏈接可與作者直接交流。

▌CSRF 攻擊

CSRF 跨站點請求偽造 (Cross—Site Request Forgery):大概可以理解為攻擊者盜用了你的身份,以你的名義在惡意網站發送惡意請求,對服務器來説這個請求是完全合法的,但是卻完成了攻擊者所期望的一個操作,比如以你的名義發送郵件、發消息,盜取你的賬號,甚至於購買商品、轉賬等。

例如:Web A 為存在 CSRF 漏洞的網站,Web B 為攻擊者構建的惡意網站,User C 為 Web A 網站的合法用户。

image.png
CSRF 攻擊攻擊原理及過程如下:
1.用户 C 打開瀏覽器,訪問受信任網站 A,輸入用户名和密碼請求登錄網站 A;
2.在用户信息通過驗證後,網站 A 產生 Cookie 信息並返回給瀏覽器,此時用户登錄網站 A 成功,可以正常發送請求到網站 A;
3.用户未退出網站 A 之前,在同一瀏覽器中,打開一個 TAB 頁訪問網站 B;
4.網站 B 接收到用户請求後,返回一些攻擊性代碼,併發出一個請求要求訪問第三方站點 A;
5.瀏覽器在接收到這些攻擊性代碼後,根據網站 B 的請求,在用户不知情的情況下攜帶 Cookie 信息,向網站 A 發出請求。網站 A 並不知道該請求其實是由 B 發起的,所以會根據用户 C 的 Cookie 信息以 C 的權限處理該請求,導致來自網站 B 的惡意代碼被執行。

▌CSRF 漏洞檢測

a.檢測 CSRF 漏洞最簡單的方法就是抓取一個正常請求的數據包,去掉 Referer 字段後再重新提交,如果該提交還有效,那麼基本上可以確定存在 CSRF 漏洞。
b.隨着對 CSRF 漏洞研究的不斷深入,不斷涌現出一些專門針對 CSRF 漏洞進行檢測的工具,如 CSRFTester,CSRF Request Builder 等。
CSRF 漏洞檢測工具的測試原理如下:使用 CSRFTester 進行測試時,首先需要抓取我們在瀏覽器中訪問過的所有鏈接以及所有的表單等信息,然後通過在 CSRFTester 中修改相應的表單等信息,重新提交,這相當於一次偽造客户端請求。如果修改後的測試請求成功被網站服務器接受,則説明存在 CSRF 漏洞,當然這些工具也可以被用來進行 CSRF 攻擊。

▌防禦 CSRF 攻擊

(1) 驗證 HTTP Referer 字段
根據 HTTP 協議,在 HTTP 頭中有一個字段叫 Referer(瀏覽器會自動加上這個字段),它記錄了該 HTTP 請求的來源地址。通常情況下,訪問一個安全受限頁面的請求來自於同一個網站,例如從 login 頁面點擊 “點我” 跳轉,就會帶着 Referer:http://127.0.0.1:5000/login:
image.png
跳轉後:

image.png
在以上 CSRF 攻擊的第四步,該請求的 Referer 是指向黑客自己的網站 B 而不是網站 A。因此,要防禦 CSRF 攻擊,網站 A 只需要對於每一個請求驗證其 Referer 值,如果是 A 網站的域名,則説明該請求是來自己的請求,是合法的。如果 Referer 是其他網站的話,則有可能是黑客的 CSRF 攻擊,拒絕該請求。

Referer 的優勢與劣勢:
a.簡單易行,開發人員不需要操心 CSRF 的漏洞,只需要在最後給所有安全敏感的請求統一增加一個攔截器來檢查 Referer 的值就可以,非常便捷。

#每個請求執行之前先執行before驗證請求頭中的referer
@app.before_request
def csrf_check_referer():
    # 獲取請求頭中的referer,login頁面不需要檢查因為沒有,只需要檢查後續的跳轉頁面請求是否帶referer字段
    if request.path != "/login":
        referer=request.referrer
        print(referer)
        if referer[:22] != "http://127.0.0.1:5000/":
            return "page not found",404

如果域名不是"http://127.0.0.1:5000/404",跳轉後的頁面:
image.png
b.Referer 的值是由瀏覽器提供的,並不能保證瀏覽器自身沒有安全漏洞。對於某些瀏覽器,目前已經有一些方法可以篡改 Referer 值,黑客完全可以修改 Referer 值,這樣就可以通過驗證,從而進行 CSRF 攻擊。
c.即便黑客無法篡改 Referer 值,因為 Referer 值會記錄下用户的訪問來源,有些用户認為這樣會侵犯到他們自己的隱私權,因此用户自己可以設置瀏覽器使其在發送請求時不再提供 Referer。當他們正常訪問網站時,網站會因為請求沒有 Referer 值而拒絕合法用户的訪問。

(2) 在請求中添加 token 並驗證
demo 代碼如下:
app.py 需要設置秘鑰,使用 form 表單驗證模塊 flask-wtf 對前端數據進行驗證,包括前端傳回的 csrf-token 的驗證;

import os
from flask import Flask, request, render_template

#初始化application
from wtforms import ValidationError
from registerform import MyForm

app = Flask(__name__)
#設置秘鑰
app.config["SECRET_KEY"] = os.urandom(10)

#每個請求執行之前先執行before驗證請求頭中的referer
@app.before_request
def csrf_check_referer():
    # 獲取請求頭中的referer,login頁面不需要檢查因為沒有,只需要檢查後續的跳轉頁面請求是否帶referer字段
    if request.path != "/login":
        referer=request.referrer
        print(referer)
        if referer[:22] != "http://127.0.0.1:5000/":
            return "page not found",404

@app.route("/")
def index():
    return {"user":"lei"}

@app.route('/login',methods=['GET','POST'])
def login():
#使用flask-wtf表單驗證,會自動加上CSRF攻擊的驗證
    form = MyForm()
    if request.method == "GET":
        return render_template('index.html', form=form)
    if form.validate_on_submit():
        return 'OK'
    else:
        raise ValidationError(message=form.errors)

if __name__ == '__main__':
    app.run(debug=True)

form 表單驗證模塊:
from flask_wtf import FlaskForm
from wtforms import StringField
from wtforms.validators import DataRequired,Length

class MyForm(FlaskForm):
驗證前端傳入的name不能為空,長度2-10;
    name = StringField('name', validators=[DataRequired("姓名不能為空"),Length(2,10,"名字長度錯誤")])

html 文件:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>flask</title>
</head>
<body>
<div style="color:red">歡迎~~~</div>
<form method="POST" action="/login">
#請求頁面時會加上csrf_token,提交表單時會帶上這個隱藏的token以和參數一起提交給服務器;
{{ form.csrf_token }}
<lable>姓名:</lable>
    <input type="text" name="name" value="">
<input type="submit" value="submit">
</form>
<a href="http://127.0.0.1:5000">點我</a>
</body>
</html>

1.在客户端向後端請求界面數據的時候,需要在 Form 表單中添加一個隱藏的的字段,值是 csrf_token。

image.png

2.在用户點擊提交的時候,會帶上這個值向後台發起請求;

image.png
3.後端接受到請求,會比較值是否正確,如果沒取到或者不正確,代表不是正常的請求,不執行下一步操作。

如下用 postman 直接發起請求,則會報 csrf_token 錯誤;

image.png

原文由發表於TesterHome社區,點擊原文鏈接可與作者直接交流。

今日份的知識已攝入~
想了解更多前沿測試開發技術:歡迎關注「第十屆MTSC大會·上海」>>>
1個主會場+12大專場,大咖雲集精英齊聚

Add a new 评论

Some HTML is okay.