整理關於web項目如何防止CSRF和XSS攻擊的方法

腳本語言 CSS SQL 技術 淮安二傻子 淮安二傻子 2017-09-10

1 瞭解CSRF的定義

CSRF(Cross-site request forgery)跨站請求偽造,也被稱為“One Click Attack”或者Session Riding,通常縮寫為CSRF或者XSRF,是一種對網站的惡意利用。儘管聽起來像跨站腳本(XSS),但它與XSS非常不同,XSS利用站點內的信任用戶,而CSRF則通過偽裝來自受信任用戶的請求來利用受信任的網站。與XSS攻擊相比,CSRF攻擊往往不大流行(因此對其進行防範的資源也相當稀少)和難以防範,所以被認為比XSS更具危險性。

攻擊通過在授權用戶訪問的頁面中包含鏈接或者腳本的方式工作。例如:一個網站用戶Bob可能正在瀏覽聊天論壇,而同時另一個用戶Alice也在此論壇中,並且後者剛剛發佈了一個具有Bob銀行鏈接的圖片消息。設想一下,Alice編寫了一個在Bob的銀行站點上進行取款的form提交的鏈接,並將此鏈接作為圖片src。如果Bob的銀行在cookie中保存他的授權信息,並且此cookie沒有過期,那麼當Bob的瀏覽器嘗試裝載圖片時將提交這個取款form和他的cookie,這樣在沒經Bob同意的情況下便授權了這次事務。

2 在項目中如何解決csrf的攻擊

我們以用戶登錄這段代碼來舉例說明:

2.1 首先項目裡面引入CSRFTokenManager.java,這個裡面主要是產生一個csrftoken session的代碼。

整理關於web項目如何防止CSRF和XSS攻擊的方法

2.2 在用戶進入項目,還沒有跳轉到登錄頁面之前,我們通過CSRFTokenManager代碼產生一個token,然後把它傳入登錄頁面,給它定義成csrf。

整理關於web項目如何防止CSRF和XSS攻擊的方法

2.3 在登錄頁面裡面,通過隱藏域來獲取剛剛傳入的csrf,這樣當用戶提交form表單的時候,這裡的csrf就會一起被提交到後臺的代碼。

整理關於web項目如何防止CSRF和XSS攻擊的方法

2.4 在後臺代碼裡面,我們通過頁面傳入的token和已經產生的token session進行對比,如果兩個相同,那麼這些操作就認為是用戶自己在操作,如果頁面傳入的和產生的token不相同那麼這就是其他人員通過模擬用戶進行了這樣的操作,那麼我們就要對它進行處理,讓它跳轉到登錄頁面。

整理關於web項目如何防止CSRF和XSS攻擊的方法

3 瞭解XSS的定義

跨站腳本攻擊(Cross Site Scripting),為不和層疊樣式表(Cascading Style Sheets, CSS)的縮寫混淆,故將跨站腳本攻擊縮寫為XSS。惡意攻擊者往Web頁面裡插入惡意Script代碼,當用戶瀏覽該頁之時,嵌入其中Web裡面的Script代碼會被執行,從而達到惡意攻擊用戶的目的。XSS攻擊分成兩類,一類是來自內部的攻擊,主要指的是利用程序自身的漏洞,構造跨站語句,如:dvbbs的showerror.asp存在的跨站漏洞。另一類則是來自外部的攻擊,主要指的自己構造XSS跨站漏洞網頁或者尋找非目標機以外的有跨站漏洞的網頁。如當我們要滲透一個站點,我們自己構造一個有跨站漏洞的網頁,然後構造跨站語句,通過結合其它技術,如社會工程學等,欺騙目標服務器的管理員打開。

4 在項目中如何解決XSS的攻擊

4.1 首先項目導入XSSStringEncoder.java,這個裡面主要就是把傳入字符串的特殊字符進行html轉碼,例如> < ) ( " ' % ; & +,這些特殊字符很有可能就是被注入的代碼。

整理關於web項目如何防止CSRF和XSS攻擊的方法

4.2 對每一個代碼傳入的字符串調用這裡面的encodeXSSString進行轉碼,然後把轉碼後的字符串返回回來

整理關於web項目如何防止CSRF和XSS攻擊的方法

附,CSRFTokenManager,XSSStringEncoder內容:

1 CSRFTokenManager.java

package com.claridy.common.util;

import java.util.UUID;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpSession;

/**

*

* A manager for the CSRF token for a given session. The

* {@link #getTokenForSession(HttpSession)} should used to

*

* obtain the token value for the current session (and this should be the only

* way to obtain the token value).

*

* ***/

publicfinalclass CSRFTokenManager {

/**

*

* The token parameter name

*/

staticfinal String CSRF_PARAM_NAME = "CSRFToken";

/**

*

* The location on the session which stores the token

*/

publicstaticfinal String CSRF_TOKEN_FOR_SESSION_ATTR_NAME = CSRFTokenManager.class.getName() + ".tokenval";

publicstatic String getTokenForSession(HttpSession session) {

String token = null;

synchronized (session) {

token = (String) session.getAttribute(CSRF_TOKEN_FOR_SESSION_ATTR_NAME);

if (null == token) {

token = UUID.randomUUID().toString();

session.setAttribute(CSRF_TOKEN_FOR_SESSION_ATTR_NAME, token);

}

}

return token;

}

/**

*

* Extracts the token value from the session

*

*

*

* @param request

*

* @return

*/

publicstatic String getTokenFromRequest(HttpServletRequest request) {

return request.getParameter(CSRF_PARAM_NAME);

}

private CSRFTokenManager() {

};

}

2 XSSStringEncoder.java

package com.claridy.common.util;

publicclass XSSStringEncoder {

/**

* 排除XSS(Cross Site Scripting)和SQL injection攻擊字元

*

* @param data

* */

publicstatic String encodeXSSString(String data) {

if (data == null || "".equals(data)) {

return data;

}

final StringBuffer buf = new StringBuffer();

finalchar[] chars = data.toCharArray();

for (int i = 0; i < chars.length; i++) {

// > < ) ( " ' % ; & +

if ((int) chars[i] == 62 || (int) chars[i] == 60 || (int) chars[i] == 41 || (int) chars[i] == 40 || (int) chars[i] == 34 || (int) chars[i] == 39

|| (int) chars[i] == 37 || (int) chars[i] == 59 || (int) chars[i] == 38 || (int) chars[i] == 43) {

buf.append("&#" + (int) chars[i]);

} else {

buf.append((char) chars[i]);

}

}

return buf.toString();

}

}

相關推薦

推薦中...