1. 程式人生 > >CSRF(Cross-site request forgery)

CSRF(Cross-site request forgery)

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>

正常流程如下:
輸入轉賬賬戶和金額進行轉賬
在這裡插入圖片描述
轉賬成功
在這裡插入圖片描述
但是如果直接訪問工作者偽造的網址則直接轉賬成功![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20181111100934684.png
通過以上例子,攻擊者通過構造請求包,誘導使用者點選導致直接轉賬成功。

這個例子中沒有用到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 方法中對於頁面區域性的非同步重新整理,並非所有的請求都適合用這個類來發起,而且通過該類請求得到的頁面不能被瀏覽器所記錄下 ,從而進行前進,後退,重新整理,收藏等操作,給使用者帶來不便。