XSS編碼問題的個人總結
XSS也太太太難了,主要也是因為自己沒花時間集中。
文章脈絡:根據我粗淺的理解,從開始學習XSS到現在,從一開始的見框就插到現在去學構造、編碼,首先需要的是能看懂一些payload,然後再去深入理解。所以,文章首先會介紹一些常見的可供利用的編碼,然後再理解瀏覽器如何解析HTML文件,最後再總結一下。應該有很多不正確的地方,希望看到的朋友幫我指正以下,帶我挖洞,衝。QQ:2309896923
寫的這些內容都是借鑑總結了許多大神的文章,對大神提及的一些注意點進行總結歸納。
一、一般可利用的編碼
1.URL編碼
格式:%十六進位制數
字元 | 編碼 |
---|---|
= | %3D |
a | %61 |
我太難了 | %E6%88%91%E5%A4%AA%E9%9A%BE%E4%BA%86 |
記住常用符號、字母的 ASCII 碼,能熟練轉換 10 -16 進位制即可。中文的URL編碼略有不同,因為用的地方沒有,也就不詳寫了
如何利用:瀏覽器的 URL 位址列,反射型 XSS,可以將特殊字元進行 URL 編碼,可以嘗試多次編碼試一試;POST過去的資料,儲存型 XSS,跟反射型的一樣。最後提一點:因為一般網站處理資料的時候最開始解碼的一般是 URL 解碼,所以可以在用其他編碼構造完成 payload 後,最後再進行 URL 編碼,由此可見,可以根據解碼順序,靈活得進行編碼,最先解碼的,就最後編碼,懂我什麼意思吧,我也不太懂我到底有沒有說懂
2.HTML實體編碼
格式:&#十進位制/十六進位制; (一般是用十進位制)十六進位制的時候為 &#x十六進位制數
字元 | 實體名稱 | 實體編碼 |
---|---|---|
< | < |
< |
: | : |
: |
換行 | 
 |
|
空格 | |
  |
對照ASCII碼錶基本就可以輕鬆轉換了
HTML實體編碼對照表參考地址:https://www.w3school.com.cn/html/html_entities.asp
如何利用:注意不要編碼 標籤的 <> 、屬性名、以及賦值號(等號=,冒號:)就可以了
3.JS編碼
格式:①--unicode:\u十六進位制 ②--\八進位制、\十六進位制
字元 | \u | \八進位制 | \十六進位制 |
---|---|---|---|
a | \u0061 |
\141 |
\x61 |
b | \u0062 |
\142 |
\x62 |
c | \u0063 |
\143 |
\x63 |
如何利用:一般使用 jsUnicode編碼比較多,其他的兩種還在研究,望得到高人指點
4.CSS編碼
格式:\1~6位十六進位制數
後邊就不能直接緊跟數字或字母,否則會被當成轉義裡的內容處理,所以CSS 選擇了空格作為終止標識,在解碼的時候,再將空格去除。
如何利用:在使用 style 屬性或標籤的時候使用,或者也可以在引入外部 CSS 檔案的時候,將引入的檔案內容進行編碼
二、弄清楚瀏覽器解碼順序
瀏覽器解析順序:
示例HTML程式碼:
<a href="javascript: //%0a%61l\u0065rt(1)">click me</a>
解釋:
1.首先瀏覽器接收到HTML程式碼,會先開始進行HTML解析,構造DOM樹,粗略的講就是識別 <>
這些標籤,賦予其特殊含義,區別於純文字內容。
注意此時並不會做任何解碼操作,所以構造 &#lt;img src="javascript:al\u0065rt(1)">
是不會彈窗的,因為沒有識別到標籤,它相當於就是一個純文字,具體來說就是:標籤屬性名和賦值符號不能編碼,但是標籤屬性的值可以編碼
2.DOM樹構造完成,開始HTML解碼,變成了<a href="javascript://%0a%61l\u0065rt(1);">click me</a>
3.唉,碰到連結類屬性 href 了,儘管發現了是javascript偽協議,瀏覽器也會直接 URL 解碼一次,然後就變成了 <a href="javascript://al\u0065rt(1)">click me</a>
4.解碼後,因為是 javascript 偽協議,所以 JS 解析器便開始工作了,解析成了 <a href="javascript://alert(1)">click me</a>
,注意在識別協議的時候,協議是不能被任何編碼的,除非在識別之前已經被解碼了,不然的話是不能被識別出來的的,比如說 href="j%61vascript:alert(1)" ,冒號被編碼也不行,瀏覽器雖說會 URL 解碼,但是並不會解碼之後再識別一次這是什麼協議,於是不管是 http 協議還是 javascript 偽協議也好,此時都發揮不了作用而且,此時 href="j%61vascript:alert(1)" 中的冒號括號也不能被 js 編碼,否則不會彈窗
5.然後就順利彈窗了
6.當然,並不是所有時候都是這種解碼順序,要依據具體情況而定。
7.演示一下如何自己進行編碼:
可以看到上述例子瀏覽器解碼順序為 HTML實體解碼
-> URL解碼
-> JSUnicode解碼
<-----> 於是便反過來編碼 JSUnicode解碼
-> URL解碼
-> HTML實體解碼
假設要編碼的內容:<img/src/onerror=alert(1)>
,可以先思考一下改如何編碼,再往下看
首先JSUnicode編碼 :
<img/src/onerror=\u0061\u006c\u0065\u0072\u0074(1)>
,加不加雙引號包裹onerror後面的內容無所謂,加也好,不加也好,最好不加,因為雙引號被過濾了的話,會更麻煩,依據前文所述,此處的注意點有:不能編碼括號 (),還有一點很奇怪,彈窗提示的 1 字元也不能被編碼,否則不會彈,除非加引號包裹起來。
其次HTML編碼 :<img/src/onerror=\u0061\u006c\u0065\u0072\u0074(1)>
此處的注意點有:不能編碼標籤的 <>、屬性、等號=
最後URL編碼 :%3Cimg/src/onerror%3D%5Cu0061%26%23x5C%3B%26%23x75%3B006c%5Cu0065%5Cu0072%5Cu0074%26%23x28%3B1%29%3E
最後一個問題:這句payload應該插在哪? 一般是反射型的XSS直接便可以見到效果,
有php環境的可以試一下:a.php 內容為 <?php echo $_GET["a"]; ?>
,然後用瀏覽器開啟這個檔案,後面接 ?a=%3Cimg/src/onerror%3D%5Cu0061%26%23x5C%3B%26%23x75%3B006c%5Cu0065%5Cu0072%5Cu0074%26%23x28%3B1%29%3E
,即可彈窗
如圖:
注意點總結:
1.轉義編碼應當只出現在標示符部分,不能用於對語法有真正影響的符號,也就是括號,或者是引號、等號、冒號
2.瀏覽器是不會在html標籤裡解析js中的那些編碼的!所以我們在onerror=後面放js中的八進位制、十六進位制編碼(jsUnicode編碼除外)是不會解析 你放進去是什麼 解析就是什麼!而另一方面,如果想用這種方式來替換掉圓括號,或者引號,會判定為失敗。同時,主要注意的方式,上邊這種直接在字串外進行專一的方式,只有Unicode 轉義方式被支援,其他轉義方式則不行。其實,這樣的策略是正確的,因為對於JavaScript,轉義編碼應當只出現在標示符部分,不能用於對語法有真正影響的符號,也就是括號,或者是引號。其實,這樣的處理方法,反而是比CSS 更加合理的。
3.HTML解析器在建立文件樹的時候會針對節點內的Entity編碼(即實體編碼)解碼後傳輸。
4.使用DOM 操作,對DOM Tree 造成了改變,會呼叫到 HTML 解析器重新對其解析,意思就是,用 DOM 操作建立了節點標籤什麼的,會重新呼叫 HTML 解析
5.在一個頁面中,可以觸發 JS 解析器的方式有這麼幾種:
直接嵌入< script> 程式碼塊。
通過< script sr=… > 載入程式碼。
各種HTML CSS 引數支援JavaScript:URL 觸發呼叫。
CSS expression(…) 語法和某些瀏覽器的XBL 繫結。
事件處理器(Event handlers),比如 onload, onerror, onclick等等。
定時器,Timer(setTimeout, setInterval)
eval(…) 呼叫。
可以想一下這個 <script>\u0061\u006c\u0065\u0072\u0074\u0028\u0031\u0031\u0029</script>
,為什麼這個不彈窗呢?????????????????
不清楚可以看一下參考文章的第一篇!!
另外一些例子:
以下兩個表示相同:
<img src="http://www.example.com">
<img src="http://www.example.com">
因為在識別協議之前,已經HTML解碼了,所以並不會出現識別協議失敗
下面兩個例子程式碼不會執行,因為,編碼的是標籤本身的結構而非節點內的內容:(這一點非常重要)
<img src="http://www.example.com">
<img src="http://www.example.com">
三、騷操作
HTML新增字元
:
冒號


換行
1) HTML編碼:實體編號,就是ASCII碼的10進位制,還可以$#000060來實現繞過一些WAF。
2) 當 <> 這些符號被編碼的時候,因為在JS中常見的傳輸中文或者非ASCII碼字元就會使用unicode編碼,同樣這種編碼可以用來繞過一些WAF。如 '<':編碼為 '\u003c'(unicode編碼),'a'->\x61。此時需要考慮網站傳輸資料的方式!
3) 如果任何形式引號都被攔截的情況下,你可以使用fromCharCode()方法來創造你需要的XSS Payload.如<IMG SRC=javascript:alert(String.fromCharCode(88,83,83))>
,然後再編碼
4) 還有,數字編碼前面加「0」,這也是一條很好的繞過 WAF 的向量。
5) 多觀察網站傳輸資料的編碼格式,利用其對應特點進行編碼
參考文章:(建議全部仔細讀一遍,當然最後那一篇是我之前寫的,看不看問題不大)
名稱 | 地址 |
---|---|
理解瀏覽器解析規則文章 | http://bobao.360.cn/learning/detail/292.html |
XSS編碼剖析 | https://www.freebuf.com/articles/web/43285.html |
Browser Security-超文字標記語言(HTML) | https://www.madebug.net/static/drops/tips-147.html |
編碼與解碼-瀏覽器做了什麼 | http://xuelinf.github.io/2016/05/18/編碼與解碼-瀏覽器做了什麼/ |
深入理解瀏覽器解析機制和XSS向量編碼 文章總結 | https://www.wjlshare.xyz/2019/08/10/深入理解瀏覽器解析機制和xss向量編碼-文章總結/ |
XSS與字元編碼的那些事兒 ---科普文 | https://www.madebug.net/static/drops/tips-689.html |
XSS之繞過WAF總結 | https://www.cnblogs.com/wjrblogs/p/12341190.html |
推薦一些線上編碼的網站:可能之後會自己寫一個,之前有 0x_Jin 大佬的 XSS_ENCODE 谷歌外掛,但是不知道為什麼用不了了
名稱 | 地址 |
---|---|
CTF線上工具 | http://ctf.ssleye.com/ |
HTML字元實體轉換 | https://www.qqxiuzi.cn/bianma/zifushiti.php |
Unicode與中文互轉 16進位制Unicode編碼轉換、還原 | http://www.msxindl.com/tools/unicode16.asp |
Unicode 編碼&解碼 | https://www.css-js.com/tools/unicode.html |
注:純推薦,沒打廣告