Quantcast
Channel: IT社区推荐资讯 - ITIndex.net
Viewing all articles
Browse latest Browse all 15843

在 HTML 內嵌 JSON object 時要注意的事情…

$
0
0

有時候我們會因為效能問題,在 HTML 內嵌入 JSON object,而不是再多一個 HTTP request 取得。

但「嵌入」的行為如果沒有處理好,就產生非常多 XSS attack vector 可以玩。

首先最常犯的錯誤是使用錯誤的 escape function:

<!DOCTYPE HTML><html><body><script>
var a = "<?= addslashes($str) ?>";</script></body></html>

這樣可以用 </script><script>alert(1);//攻擊 $str。因為 addslashes()並不會過濾到這個字串,而產生這樣的 HTML:

<!DOCTYPE HTML><html><body><script>
var a = "</script><script>alert(1);//";</script></body></html>

而這個字串會造成 DOM parser 解讀上產生不是我們預期的行為:

可以看到在字串裡面的 </script>被拆開了。

這是因為瀏覽器會先拆解產生 DOM tree,再把 <script></script>內的程式碼交給 JavaScript engine 處理。所以在一開始產生 DOM tree 的時候,是看不懂 JavaScript 程式邏輯的…

正確的方法是用 json_encode()處理,因為 PHPjson_encode()預設會把 / (slash) 變成 \/ (這是 JSON spec 裡合法的轉換):

<!DOCTYPE HTML><html><body><script>
var a = <?= json_encode($str) ?>;</script></body></html>

這會產生出:

<!DOCTYPE HTML><html><body><script>
var a = "<\/script><script>alert(1);//";</script></body></html>

但上面這段 HTML 與 PHP code 仍然有問題,如果 $str<!--<script時,你會發現 DOM 又爛掉了:

<!DOCTYPE HTML><html><body><script>
var a = "<!--<script>";</script></body></html>

escape.alf.nu的 Level 15 就是利用這個問題,再加上其他的漏洞而完成 XSS 攻擊。

為了這個問題去 StackOverflow 上問:「 Why does <!–<script> cause a DOM tree break on the browser?」,才又發現上面這段 code 並不是合法的 HTML5 (先不管 head & title 的部份,補上後仍然不是合法的 HTML5)。

原因在於 DOM parser 對 <script></script>的特殊處理:「 4.3.1.2 Restrictions for contents of script elements」。(話說這段 ABNF 差點讓我翻桌…)

解法是在 <script></script>的開頭與結尾加上 HTML 註解:(這剛好是 HTML 4.01建議的方法)

<!DOCTYPE HTML><html><body><script><!--
var a = "<!--<script>";
--></script></body></html>

那段 ABNF 的目的是希望可以盡可能往後找到 --></script>結尾的地方。

當然你也可以用 json_encode()JSON_HEX_TAG<>硬轉成 \u003c\u003e避開這個問題,但這使得呼叫 json_encode()時要多一個參數 (而非預設參數),用起來比較卡…

這個問題會變得這麼討厭,是因為 DOM parser 與 JavaScript 語法之間有各自的處理方式,然後又有些 pattern 是之前的 spec 遺留下來的包袱 (像是 HTML 4.01 在「 18.3.2 Hiding script data from user agents」裡有提到用 <!---->包裝 <script></script>),變成在設計 HTML5 時都要考慮進去相容…

之前會習慣用 <!--//-->包裝 <script></script>倒不是這個原因,而是因為不這樣做的話, jQuery在 IE 使用 html()時遇到有 <script></script>的字串會爛掉,所以後來寫的時候變成習慣了…

反而因為這個習慣而避開了這個問題…

超難搞啊…

Related Posts:


Viewing all articles
Browse latest Browse all 15843

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>