XSS攻擊全稱跨站腳本攻擊(Cross-site scripting),為和CSS區別,改為XSS。XSS是一種經常出現在web應用中的計算機安全漏洞,它允許惡意的web用戶將代碼植入到提供給其它用戶使用的頁面中。比如這些代碼包括HTML代碼和客戶端腳本。
XSS攻擊的產生原因是對外部輸入的參數沒有做嚴格過濾,導致輸入參數直接參與頁面源代碼,相當於頁面源代碼可以被外部修改,因此可能被改變頁面結構、植入惡意腳本,可被用於釣魚、盜取數據、篡改頁面等。解決的方法是加強頁面輸出過濾或轉義,如ESAPI的Encoder轉義、自定義轉義,或者采用不存在XSS風險的頁面標簽進行輸出。
攻擊分類
反射型XSS攻擊
又稱為非持久性跨站點腳本攻擊。漏洞產生的原因是攻擊者注入的數據反映在響應中。一個典型的非持久性XSS包含一個帶XSS攻擊向量的鏈接(即每次攻擊需要用戶的點擊)。
例子
http://www.test.com/message.php?send=Hello,World
接收者將會接收信息顯示Hello,World
http://www.test.com/message.php?send=<script>alert(‘foolish!’)</script>
接收者接收消息顯示的時候將會彈出警告窗口顯示foolish!
存儲型XSS攻擊
又稱為持久型跨站點腳本,它一般發生在XSS攻擊向量(一般指XSS攻擊代碼)存儲在網站數據庫,當一個頁面被用戶打開的時候執行。每當用戶打開瀏覽器,腳本執行。持久的XSS相比非持久性XSS攻擊危害性更大,因為每當用戶打開頁面,查看內容時腳本將自動執行。
例子
一個正常的表單,正常操作是用戶提交相應留言信息;將數據存儲到數據庫;其他用戶訪問,應用查詢數據並顯示。
<input type=“text” name=“content” value=“這里是用戶填寫的數據”>
攻擊者在value填寫
<script>alert(‘foolish!’)</script>
或者其他攻擊代碼。將代碼存儲到數據庫中;其他用戶取出數據顯示的時候,將會執行這些攻擊性代碼。
攻擊入口
可以通過HTML節點、HTML屬性、JavaScript代碼、富文本等只要有用戶輸入信息的地方都可能是被攻擊的注入點。
防范方法
需要將一些特殊字符進行轉義處理。
-
通過前端對用戶輸入內容進行處理:
var escapeHtml = function(str) { str = str.replace(/</g,'<'); str = str.replace(/</g,'>'); return str; }
-
通過后台對用戶輸入內容進行處理:
private String cleanXSS(String value) { //You'll need to remove the spaces from the html entities below value = value.replaceAll("<", "<").replaceAll(">", ">"); value = value.replaceAll("\\(", "(").replaceAll("\\)", ")"); value = value.replaceAll("'", "'"); value = value.replaceAll("eval\\((.*)\\)", ""); value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\""); value = value.replaceAll("script", ""); return value; }
-
后台使用第三方方法處理:添加commons-lang-2.5.jar 包,然后使用方法或者使用Spring框架中的HtmlUtils方法:
StringEscapeUtils.escapeHtml(string); StringEscapeUtils.escapeJavaScript(string); StringEscapeUtils.escapeSql(string);
在父Controller里面進行處理:
@InitBinder
protected void initBinder(WebDataBinder binder) {
// String類型轉換,將所有傳遞進來的String進行HTML編碼,防止XSS攻擊
binder.registerCustomEditor(String.class, new PropertyEditorSupport() {
@Override
public void setAsText(String text) {
setValue(text == null ? null : StringEscapeUtils.escapeHtml4(text.trim()));
}
@Override
public String getAsText() {
Object value = getValue();
return value != null ? value.toString() : "";
}
});
}