前端安全之CSRF攻擊


前端安全之CSRF攻擊

轉載請注明出處:unclekeith: 前端安全之CSRF攻擊

CSRF定義

CSRF,即(Cross-site request forgery), 中文名為跨站請求偽造。是一種挾持用戶在當前已登錄的Web應用程序上執行非本意的操作的一種攻擊方式。CSRF攻擊的本質在於利用用戶的身份,執行非本意的操作。根據CSRF的全名,可以得出的結論是:CSRF的請求是跨域且偽造的。

跨域指的是請求來源於其他網站。比如說,目標網站上的刪除文章功能接收到來自其他網站的刪除文章的請求,那么這個請求就是跨域的。

偽造指的是如果這個請求不是用戶自身的意願,那么這個請求就是偽造的。

簡單的說,跨站請求偽造的攻擊是攻擊者通過一些技術手段欺騙用戶的瀏覽器去訪問用戶曾經認證過的網站並執行一些操作(如發送郵件、發消息、甚至財產操作如轉賬和購買商品等)。由於瀏覽器曾經認證過,所以被訪問的網站會認為是真正的用戶操作而去執行。這利用了web登錄身份認證的一個漏洞:簡單的身份認證只能保證請求來自用戶的瀏覽器,但不能識別請求是用戶自願發出的。

CSRF分類

  1. GET CSRF
  2. POST CSRF

假如有這么一個場景,目標網站A的url:www.a.com。惡意網站B的url:www.b.com。

GET CSRF
兩個網站的域名不一樣,目標網站A上有一個刪除文章的功能,通常是用戶單擊’刪除文章‘鏈接時才會刪除指定的文章。這個鏈接是www.a.com/blog/del?id=1, id代表不同的文章。實際上就是發起一個GET請求。

如果在目標網站A上存在XSS漏洞,那么可以利用這個XSS漏洞來進行攻擊。注意,XSS攻擊是在用戶的瀏覽器上進行的。如果對XSS攻擊不熟悉的朋友,可以看看這篇文章。傳送門:前端安全之XSS攻擊

1. 使用Ajax發起一個GET請求,因為是在目標網站上,所以符合同源策略。請求參數為id=1, 請求目標地址為www.a.com/blog/del。
2. 或者在目標網站A上動態創建一個標簽(script, img, iframe等),將其src指向www.a.com/blog/del?id=1, 那么攻擊就會發起。實際上通過這種方式發起的請求就是一個GET請求。
3. 最后欺騙用戶登錄目標網站A,那么攻擊就會發生。

如果在目標網站A上不存在XSS漏洞,那么可以利用GET CSRF進行攻擊

1. 無法使用Ajax發起GET請求。因為CSRF請求是跨域的,而Ajax有同源策略的限制。
2. 可以通過在惡意網站B上靜態或者動態創建img,script等標簽發起GET請求。將其src屬性指向www.a.com/blog/del?id=1。通過標簽的方式發起的請求不受同源策略的限制。
3. 最后欺騙已經登錄目標網站A的用戶訪問惡意網站B,那么攻擊就會發生。此時惡意網站B的請求是身份認證后的。

對比CSRF和XSS攻擊可以看出,CSRF攻擊有以下幾個關鍵點

  1. 請求是跨域的。可以看出請求是從惡意網站B上發出的
  2. 通過img, script等標簽來發起一個GET請求。因為這些標簽不受同源策略的限制
  3. 發出的請求是身份認證后的。這一點是CSRF中最重要的一點。如以下代碼

惡意網站B發出的刪除文章的GET請求的請求頭

GET /blog/del?id=1 HTTP/1.1
Host: www.a.com
* Referer: http://www.b.com/csrf.html
Connection: Keep-Alive
Cookie: name=kk
Other-Request-Name: Other-Request-Value:

目標網站A發出的刪除文章的GET請求的請求頭

GET /blog/del?id=1 HTTP/1.1
Host: www.a.com
* Referer: http://www.a.com/blog/
Connection: Keep-Alive
Cookie: name=kk
Other-Request-Name: Other-Request-Value:

對比以上的代碼可以看出,只有Referer字段不同。也就是說,只有請求來源不相同,而發送刪除文章的請求時都會帶上相同的cookie信息。這樣的請求就是身份認證后的,CSRF攻擊就會成功。

POST CSRF:POST請求實際上就是在惡意網站B上發起一個POST請求,同樣的,這個請求也是跨域和身份認證后的。如靜態或動態的創建一個form表單,當用戶訪問到這個惡意網站B時,就會提交這個表單。

假如目標網站A上有‘寫文章’的功能,那么我們就可以動態創建form標簽,然后修改文章的題目。

www.b.com/csrf.html

function setForm () {
    var form = document.createElement('form')
    form.action = 'www.a.com/blog/article'
    form.methods = 'POST'
    var input = document.createElement('input')
    input.type = 'text'
    input.value = 'csfr攻擊啦!'
    input.id = 'title'
    form.appendChild(input)
    document.body.appendChild(form)
    form.submit()
}
setForm()

上面代碼可以看出,動態創建了form表單,然后調用submit方法。就可以通過跨域的偽造請求來實現修改目標網站A的某篇文章的標題了。

以上說了GET和POST的CSRF攻擊。本質上都是欺騙用戶以自己的身份去執行非本意的操作。欺騙流程大致如下

1. 首先欺騙用戶登錄目標網站。
2. 然后欺騙用戶登錄惡意網站。這種惡意的網站有很多種形式,藏身於網頁中的許多地方。此外,攻擊者也不需要控制放置惡意網址的網站。例如他可以將這種地址藏在論壇,博客等任何用戶生成內容的網站中。這意味着如果服務器端沒有合適的防御措施的話,用戶即使訪問熟悉的可信網站也有受攻擊的危險。

CSRF危害

  1. 模擬表單提交盜取用戶資金。實際上就是上面所說的POST CSRF攻擊
  2. 篡改目標網站上的用戶數據。
  3. 盜取用戶隱私數據

CSRF防范

  1. 檢測請求頭中的Referer字段

從GET CSRF例子中可以看到,目標網站A和惡意網站B發出的請求中,請求頭唯一的不同就是Referer字段。通常來說,Referer字段通常與Host字段的域名是一樣的。

以上面刪除文章功能為例,在目標網站A中的Referer字段為http://www.a.com/blog/,而惡意網站B中的Referer字段為http://www.b.com/csrf.html。所以根據Referer字段與Host字段在同一域名下的規則,可以檢測Referer字段值,如果發現其與Host值不在同一域名下,這時候服務器就能夠識別出惡意的訪問了。

  1. 添加檢驗token

由於CSRF的本質在於攻擊者欺騙用戶去訪問自己設置的地址,所以如果要求在訪問敏感數據請求時,要求用戶瀏覽器提供不保存在cookie中,並且攻擊者無法偽造的數據作為校驗,那么攻擊者就無法再執行CSRF攻擊。這種數據通常是表單中的一個數據項。服務器將其生成並附加在表單中,其內容是一個隨機數。即<input type="hidden" name="_csrf_token" value="xxxx">)的形式。

當客戶端通過表單提交請求時,這個隨機數也一並提交上去以供校驗。正常的訪問時,客戶端瀏覽器能夠正確得到並傳回這個隨機數,而通過CSRF傳來的欺騙性攻擊中,攻擊者無從事先得知這個隨機數的值,服務器端就會因為校驗token的值為空或者錯誤,拒絕這個可疑請求。

為了防范CSRF,在需要增刪改數據時,使用POST請求,而不要使用GET請求。

具體的方案如下:

1. 服務端在收到客戶端請求時,生成一個隨機數,在渲染頁面時將隨機數埋入頁面(一般埋入form表單中),<input type="hidden" name="_csrf_token" value="xxxx">)`的形式。每次刷新頁面后這個隨機數都會改變,並在服務器中存儲。
2. 服務端設置Set-Cookie, 把該隨機數作為cookie種入用戶瀏覽器。
3. 當用戶發送GET或POST請求時帶上_csrf_token參數(對於form表單直接提交即可)
4. 后台在接受到請求后解析請求頭中的cookie字段,獲取_csrf_token的值,然后和用戶請求提交的_csrf_token值做比較。如果相等則表示請求來源是合法的。

參考資料:

1.《web前端黑客技術》

2.聊聊CSRF


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM