跨站點請求僞造

如果要避免 CSRF 攻擊,每個請求都應該包含唯一標識,它是攻擊者所無法猜測的參數。 建議的選項之一是添加取自會話 cookie 
的會話標識,使它成爲一個參數。服務器必須檢查這個參數是否符合會話 cookie,若不符合,便廢棄請求。 攻擊者無法猜測這個參數的原因是應用於 cookie 
的“同源策略”,因此,攻擊者無法僞造一個虛假的請求,讓服務器誤以爲真。 攻擊者難以猜測且無法訪問的任何祕密(也就是無法從其他域訪問),都可用來替換會話標識。 
這可以防止攻擊者設計看似有效的請求。

比較容易想到的有下面兩種思路:

方案一:每個請求都帶上一個由服務器生成的隨機參數。然後在服務器端和對該參數,如果和下發的隨機數不同,則可以認爲有人在僞造請求。因爲攻擊者無法知道他本次攻擊的http請求需要帶什麼樣的隨機數纔是有效的。 
方案二:跨域僞造之所以能成功,主要決定因素是攻擊者的頁面和稍候被打開的目標頁面共享session信息。受害者登錄後,攻擊者的頁面通過ajax向被攻擊網站的關鍵業務發起的請求便自動帶上了合法的session信息。但是,根據javascript的同源策略可知,掛有A域名的窗口,不能獲取掛有B域名窗口中的任何信息,不管B是如何被打開的。據此,我們可以在客戶端的每個要保護的業務鏈接上增加一個參數sessionId,這個參數可以通過js從cookie中獲得。然後,在服務器端獲取此參數,並同真正的sessionId做對比,如果不同,則認爲請求是僞造的。因爲攻擊者的窗口無法從被攻擊網站的窗口中取得這個sessionId。

方案二的實現: 定義一個過濾器, 對頁面傳遞過來的sessionid和實際sessionid進行比較, 相同則通過

1. 定義過濾器
<filter>
        <filter-name>SessionFilter</filter-name>
        <filter-class>com.xxx.common.security.auth.SessionFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>SessionFilter</filter-name>
        <url-pattern>/login.do</url-pattern>
    </filter-mapping>


@Override
    public void doFilter(ServletRequest servletrequest, ServletResponse servletresponse, FilterChain filterchain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletrequest;
        HttpServletResponse response = (HttpServletResponse) servletresponse;
        String clientSessionId = servletrequest.getParameter("ssid");
        String serverSessionId = request.getSession().getId();
        if (serverSessionId.equals(clientSessionId)) {
            filterchain.doFilter(request, response);
        } else {
            response.sendRedirect("/common/dataError");
        }
    }

2. 請求時增加sessionid參數
<input type=hidden id="ssid" name="ssid" value="<%=request.getSession().getId()%>">
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章