*本文原創作者:tocttou,本文屬FreeBuf原創獎勵計畫,未經許可禁止轉載
在本文中,我向大家分享一個我在去年發現的Edge瀏覽器的漏洞。這個漏洞利用了瀏覽器XSS篩檢程式的缺陷,來繞過另一種XSS防禦措施:CSP(Content Security Policy,內容安全性原則)。注意這個漏洞並不是在繞過XSS篩檢程式,而是利用它讓一些本來沒有XSS的頁面,强行製造出可利用的XSS漏洞。
0×01背景
瀏覽器XSS篩檢程式誕生於IE 8,它用於防範反射型XSS攻擊。其基本原理是[參1,2,3]:既然是反射型,那麼URL中的某個參數的值必然會在頁面的某個位置出現。當然不是每個反射到HTML頁面中的參數都是XSS,比如example.com/index.php?id=12345,如果頁面中含有12345,這顯然是無所謂的。但是如果example.com/index.php?id=<script>alert(1)</script>中的script元素被反射回來,則有可能是XSS攻擊。篩檢程式的判斷邏輯大概是這樣:首先判斷GET或者POST的數據中有沒有參數可能含有XSS程式碼,這一步瀏覽器內寘了一個比較複雜的正則來匹配。如果匹配成功,則蒐索這個參數值有沒有出現在服務器返回的HTML中。如果出現了,則瀏覽器認為這是一個XSS攻擊。Edge和IE的XSS篩檢程式有兩種模式,一種是發現攻擊後遮罩整個頁面,另一種是嘗試修復XSS。默認是第二種模式,服務器可以通過設定HTTP頭欄位X-XSS-Protection: 1;mode=block調成第一種模式[參4]。
example.com/index.php?id=12345
example.com/index.php?id=<script>alert(1)</script>
X-XSS-Protection: 1; mode=block
下麵說一下微軟瀏覽器是如何“嘗試修復XSS”的。舉例來說,假設URL是example.com/index.php?id=<script>alert(1)</script>,並且HTML程式碼中含有<script>alert(1)</script>,那麼瀏覽器就把HTML中的這個元素修改為<sc#ipt>alert(1)</script>。修改之後再交給HTML解析器。由於它把r改成了#,破壞掉了script元素,那麼之後這段JavaScript程式碼就不會被執行。embed、iframe、object、meta等標籤同理,都是用#替換一個字母來破壞這些標籤。
example.com/index.php?id=<script>alert(1)</script>
<script>alert(1)</script>
<sc#ipt>alert(1)</script>
r
#
#
上述的這個修復方法雖然有效地修復了一部分反射XSS,但是它也有潜在危險。自IE 8引入XSS篩檢程式以來就一直有研究者通過濫用這個修復邏輯,向本來沒有XSS漏洞的頁面注入XSS。一個簡單的利用方法是:比如頁面中本來就有<script src=“jquery.js”></script>,我們構造這個URL:example.com/index.php?<script src=“jquery.js”></script>。IE和Edge都會誤報這是一個XSS攻擊,並按上述管道修復,修復之後的程式碼成了<sc#ipt src=“jquery.js”></script>,於是jquery.js就沒法加載了。當然這個例子不是漏洞,因為這就跟jquery.js檔案不存在一樣,雖然功能可能受影響,但沒有安全問題。
<script src="jquery.js"></script>
example.com/index.php?<script src="jquery.js"></script>
<sc#ipt src="jquery.js"></script>
<img alt="x onload=alert(0) x" src="x.png">
<img alt#"x onload=alert(0) x" src="x.png">
0×02 CVE-2017-0135
上文我們說了利用篩檢程式的誤報來幹掉jquery.js。既然它能幹掉script標籤,那麼能不能幹掉其他標籤呢?特別是能不能幹掉和安全相關的標籤。我想到了Content Security Policy有兩種設置方法,既可以在HTTP頭欄位中設定,也能在HTML中用<meta http-equiv=“Content-Security-Policy”content=“…”>來設定。於是我就試了下,如果網站用的是meta標籤設定CSP,我能不能利用篩檢程式的誤報來幹掉這個meta標籤,使得CSP失效。結論是可以。我構造了這樣一個HTML頁面,假設其URL是http://example.com/xss.html:
<meta http-equiv="Content-Security-Policy" content="...">
http://example.com/xss.html
<!DOCTYPE html>
<html>
<head>
<title>CSP Test</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self'">
</head>
<body>
<script>alert(document.domain);</script>
</body>
</html>
在一個支持CSP的瀏覽器中訪問xss.html,由於script-src‘self’這條CSP策略,我們應該是看不見彈窗的。但是在Edge中訪問http://example.com/xss.html?%3Cmeta%20http-equiv=%22Content-Security-Policy%22%20content=%22script-src%20'self'%22%3E,你會發現Edge提醒你篩檢程式發現了一個XSS,然後彈窗就出現了。
http://example.com/xss.html?%3Cmeta%20http-equiv=%22Content-Security-Policy%22%20content=%22script-src%20'self'%22%3E
<me#a http-equiv="Content-Security-Policy" content="script-src 'self'">
發現了這個漏洞之後我立即提交給了微軟,2016年底提交,2017年3月在MS17-007中修復了這個漏洞,漏洞編號是CVE-2017-0135。因為這個漏洞符合“Windows預覽版Edge瀏覽器賞金計畫”要求,微軟給了我1500美元獎金。
微軟的修復這個漏洞之後,再打開上述PoC,Edge依然會誤報它為反射XSS,但是不再嘗試自動修復,而是強制遮罩掉整個頁面,不論服務器選擇的是不是遮罩模式。
0×03寬位元組編碼XSS
修復之後我在想,其實上述meta標籤繞過,應該還有一種利用場景,同理我們可以利用XSS篩檢程式幹掉<meta charset>標籤。這樣Edge只能猜頁面的編碼類型。如果猜錯了,比如把本來是GBK編碼的網頁猜成UTF-8,也許也能導致XSS。這類漏洞原理參見[6]。比如這個HTML:
<meta charset>
<!DOCTYPE html>
<html>
<head>
<meta charset="gb2312">
<title>CSP Test</title>
</head>
<body>
<script>
var a = "峔\";alert(1);//";
</script>
</body>
</html>
其中var a的值,如果服務器按照GB2312編碼過濾,瀏覽器也按照GB2312解析,上述程式碼不會彈窗。但是我們通過訪問xss.html?<meta charset=“gb2312”>,讓Edge去掉<meta charset=“gb2312”>之後,它就有可能認為是ASCII編碼的。而“峔”的GB2312編碼是8D 5C。按ASCII來說5C恰好是反斜線,與後面轉義雙引號的反斜線構成\\。下一個雙引號則閉合了這個字串。這樣alert(1)就執行了。(在瀏覽器編碼下,相當於var a =“?\\”;alert(1);//“;)
var a
xss.html?<meta charset="gb2312">
<meta charset="gb2312">
\\
var a = "?\\"; alert(1); //";
當然因為這個利用管道是漏洞修復之後好久我才想到的,所以沒辦法測試了。僅供大家參攷思路。
0×04總結
這個漏洞說明網站儘量不要用默認模式的Edge篩檢程式。建議用X-XSS-Protection: 1;mode=block模式。或者X-XSS-Protection: 0關掉XSS篩檢程式。即使關掉都比Edge的自動修復安全(如果自信你的網站幾乎沒有反射XSS漏洞的話)。另外建議儘量使用HTTP頭欄位的管道設定CSP策略,如果不能控制HTTP響應頭再考慮用meta標籤。
X-XSS-Protection: 1; mode=block
X-XSS-Protection: 0
我估計XSS篩檢程式今後還能發現其他的惡意利用情景。因為它的判斷規則比較複雜,而且HTML標準不僅複雜而且隨時變化。難免有些之前無所謂的自動修改,之後發現問題。另外XSS篩檢程式既要保證盡可能全的識別XSS,又要儘量避免誤報,這個平衡點把握不好就容易出bug。所以我認為XSS篩檢程式是一個值得繼續研究的攻擊面。
0×05參考資料
- IE8 Security Part IV: The XSS Filter
- IE8 XSS Filter design philosophy in-depth
- IE 8 XSS Filter Architecture / Implementation
- Controlling the XSS Filter
- Abusing Internet Explorer 8′s XSS Filters
- 寬位元組編碼類型的XSS
*本文原創作者:tocttou,本文屬FreeBuf原創獎勵計畫,未經許可禁止轉載