解碼規則
- html解析器對html文檔進行解析,完成解析并創建DOM樹
- JavaScript或者CSS解析器對內聯腳本進行解析,完成js、css解碼
- url解碼會根據url所在的順序不同而在JS解碼或者解碼后
解碼順序
html解析第一步執行,而JS解析和URL解析則要根據情況而定
HTML解析器
1、html解析器以狀態機的方式運行
狀態流程圖為:
即:Data—》Tag open----》Tag name —》Data
注意:如果我們的標簽是在Data狀態下被解析出來的,那么標簽將作為一種文本輸出來,
舉例:<p>Hello<p>
初始狀態為Data state ,當遇到<
時,狀態轉為 Tag open,讀取a-z某個字符創建開始標簽,然后狀態變為Tag name ,知道讀取到>
,狀態變為Data,接著讀取到H會識別并生成一個字符,相應得會為Hello中的每個字符生成一個字符符號,之后遇到<
,又變為Tag open,讀取到/
則會創建一個閉合標簽,并將狀態改為Tag name,直到遇到>
,后回到Data state。
注意:HTML解析器處于Data State、RCDATA State 、Attribute Value State(屬性值),字符實體會被解碼為對應的字符
2、原始文本元素
特性:該元素標簽中的實體不會被HTML解碼
標簽:script,style
舉例:標簽中的實體字符不會被html解碼,因此不會執行js
<script>alert(1)</script>
3、RCDATA 元素
特性:html解析器遇到該元素標簽時,會進入RCDATA狀態,實體字符會被解析器解碼
標簽:textarea、title
舉例:字符實體會被解碼,但是不會執行JS,因為沒有進入Tag open狀態,其中<script>
不會被解釋為HTML標簽
<textarea><script>alert(1)</script></textarea>
解碼得到<textarea><script>alert(1)</script></textarea>
JavaScript解析器
JavaScript中有三個地方可以出現JS編碼
1、字符串
<script>alert(“\u0031”);</script>
被編碼的為1且是字符串,可以正常解碼并觸發執行
2、標識符
<script>\u0061\u006c\u0065\u0072\u0074(1);</script>
被編碼的部分為alert字符,是函數名,屬于在標識符中的情況,因此會被正常解碼并執行JS
3、控制符
包含:單引號、雙引號、括號等
特性:能被解碼但不會解釋為控制字符,即失去特殊意義,只會被當做標識符或字符串的一部分
<script>alert\u0028″xss”);</script>
\u0028會被解碼為( 但是不會觸發JS,因為是控制符
URL解析器
1、URL的協議部分必須為ASCII字符、否則URL解析器的狀態機將進入No Scheme狀態
<a href="%6a%61%76%61%73%63%72%69%70%74:alert(1)"></a>
url編碼部分為javascript,因為作為協議部分的"javascript"被編碼,故不會觸發JS
2、url中的:
符號不能被以任何形式編碼
<a href="javascript%3aalert(1)"></a>
:被url編碼為%3a,導致url狀態機進入No Scheme狀態,故不會觸發JS
3、當javascript沒有被編碼時
<a href = "javascript:alert(3)">hhhhh<a>
JS編碼:
<a href="javascript:\u0061\u006c\u0065\u0072\u0074(3)">hhhhhh</a>
再對JS編碼來一個URL編碼
<a href="javascript:%5c%75%30%30%36%31%5c%75%30%30%36%63%5c%75%30%30%36%35%5c%75%30%30%37%32%5c%75%30%30%37%34(3)">hhhhhh</a>
這個是可以成功執行的,當HTML解析到href時,交給URL處理,URL發現了javascript:
,把后面的數字解碼后交由JavaScript處理,所以會彈出
例子
<a href="%6a%61%76%61%73%63%72%69%70%74:%61%6c%65%72%74%28%31%29">hhhh</a>
URL encoded "javascript:alert(1)" //冒號(:)沒有被編碼
Answer: The javascript will NOT execute.
HTML沒有編碼,不用考慮,根據href,URL模塊處理,但是協議沒辦法識別(即編碼的JavaScript:),URL會解碼出來,但JS不會被執行,所以url編碼的XSS,javascript:
一定不能被url編碼,編碼后無法識別,js還是不能執行
<a href="javascript:%61%6c%65%72%74%28%32%29">
Character entity encoded "javascript" and URL encoded "alert(2)"
Answer: The javascript will execute
HTML先解碼得到:
<a href="javascript:%61%6c%65%72%74%28%32%29">
href中為URL,URL模塊可識別為javascript協議,進行URL解碼,得到
<a href="javascript:alert(2)">
由于是javascript協議,解碼完給JS模塊處理,于是被執行
<div><img src=x οnerrοr=alert(4)></div>
Character entity encoded < and >
Answer: The javascript will NOT execute.
當HTML解析到<;
時,此時的狀態為Data,會被解碼,但是不能創建img標簽,因為不是Tag open狀態,所以解碼后被當做文本,不會執行
<button onclick="confirm('7');">Button</button>
Character entity encoded '
Answer: The javascript will execute.
這里onclick中為標簽的屬性值,會被HTML解碼,得到
<button onclick="confirm('7');">Button</button>
然后被執行
<button onclick="confirm('8\u0027);">Button</button>
Unicode escape sequence encoded '
Answer: The javascript will NOT execute.
不需要HTML解碼,onclick中的值會交給JS處理,在JS中只有字符串和標識符能用Unicode表示,'顯然不行,JS執行失敗。
<script>alert(9);</script>
Character entity encoded alert(9);
Answer: The javascript will NOT execute.
不會被執行,script屬于原始文本元素(Raw text elements),只可以容納文本,注意沒有字符引用,于是直接由JS處理,JS也認不出來,執行失敗
參考鏈接
https://blog.csdn.net/baidu_38844729/article/details/109328472
https://xz.aliyun.com/t/5863