轉載請註明出處:unclekeith: 前端安全之CSRF攻擊html
CSRF,即(Cross-site request forgery), 中文名爲跨站請求僞造。是一種挾持用戶在當前已登陸的Web應用程序上執行非本意的操做的一種攻擊方式。CSRF攻擊的本質在於利用用戶的身份,執行非本意的操做。根據CSRF的全名,能夠得出的結論是:CSRF的請求是跨域且僞造的。前端
跨域指的是請求來源於其餘網站。好比說,目標網站上的刪除文章功能接收到來自其餘網站的刪除文章的請求,那麼這個請求就是跨域的。web
僞造指的是若是這個請求不是用戶自身的意願,那麼這個請求就是僞造的。跨域
簡單的說,跨站請求僞造的攻擊是攻擊者經過一些技術手段欺騙用戶的瀏覽器去訪問用戶曾經認證過的網站並執行一些操做(如發送郵件、發消息、甚至財產操做如轉帳和購買商品等)。因爲瀏覽器曾經認證過,因此被訪問的網站會認爲是真正的用戶操做而去執行。這利用了web登陸身份認證的一個漏洞:簡單的身份認證只能保證請求來自用戶的瀏覽器,但不能識別請求是用戶自願發出的。瀏覽器
假若有這麼一個場景,目標網站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攻擊cookie
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進行攻擊app
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攻擊有如下幾個關鍵點網站
惡意網站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. 而後欺騙用戶登陸惡意網站。這種惡意的網站有不少種形式,藏身於網頁中的許多地方。此外,攻擊者也不須要控制放置惡意網址的網站。例如他能夠將這種地址藏在論壇,博客等任何用戶生成內容的網站中。這意味着若是服務器端沒有合適的防護措施的話,用戶即便訪問熟悉的可信網站也有受攻擊的危險。
從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值不在同一域名下,這時候服務器就可以識別出惡意的訪問了。
因爲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