XSS解決方案:瀏覽器是如是解碼的
我本人一直關(guān)注“知識”與“知識運用”之間的區(qū)別,我曾經(jīng)舉過一個例子說:“知識”與“知識運用”就如牛郎星與織女星,感覺二者之間似乎關(guān)系密切,實則相隔甚遠!我在初學平面幾何時,經(jīng)常會這么想: 兩條線平行則永遠不會相交,這不是廢話嗎! 三角形兩邊之和當然大于第三邊了!…… 在實際運用當中,我經(jīng)常是需要用它的時候想不起來或者用錯了它們。
我的文章《輸入驗證可避免一半以上的應用安全攻擊》,對于此文我相信是IT業(yè)界的人都能看明白,但是對于一個企業(yè)來說,它的價值萬金,有多少人可以體味呢?
對于XSS問題的系統(tǒng)性解決方案上也是一樣的。許多公司已經(jīng)90%以上的程度解決了XSS問題,但是依然存在那10%的風險,風險在哪里,我想我會一步一步給大家分享清楚。XSS問題是全球性普遍性問題,沒有深度的探索就不可能有徹底的解決方案,沒有靈丹妙藥,只有正確的方法!
好,進入正題。
基于HTTP協(xié)議的B/S(browser/server)架構(gòu)的Web應用程序,有它的特殊性,它結(jié)構(gòu)松散、多標簽語言相互嵌入以及服務端與客戶端使用了相互關(guān)聯(lián)實現(xiàn)上卻完全不同等等復雜的技術(shù),以至于給基于HTTP協(xié)議的Web應用程序埋下了諸多潛在的安全問題,XSS問題就是其中之一。
我們使用C/C++/Javascript,大家都清楚,如果我想在字符串當中表達字符【”】,很自然的就會想到轉(zhuǎn)義【\”】,想在字符串當中表達【\】,就得使用轉(zhuǎn)義(與本文中所說“編碼”概念相同)形式【\\】,在HTML文檔當中也是這樣,但是大家有沒有想過這幾個問題:
1. 這個轉(zhuǎn)義后的字符串是為誰而轉(zhuǎn)義的?
2. 這個轉(zhuǎn)義后的字符串是何時被還原成轉(zhuǎn)義前的字符串的?
3. 有沒有可能還原之后的字符被重新放回到代碼中而忽略了轉(zhuǎn)義?
答案:
1. 為解釋器(或編譯器,為了簡單,后面只稱解釋器)而轉(zhuǎn)義,字符串被解釋后在內(nèi)存當中的字符串等同于轉(zhuǎn)義前字符串
2. 通常解釋器是在讀取語言(C/C++/Javascript…)字符串后進行本地語言轉(zhuǎn)換前進行還原的
3. 有,在基于HTML架構(gòu)的前端(瀏覽器端)應用程序,尤為常見。比如: var myString=”<script>alert(\”jiayzhan\”)<\/script>”; 這個myString想表達的字符串是
<script>alert(“jiayzhan”)</script>,如果被document.write(myString)重新寫到DOM里,結(jié)果是什么呢? 或者也可能會直接賦值給某一HTML節(jié)點的innerHTML/outerHTML屬性,這里的問題就復雜了,二次賦值之后,你的程序沒那么聰明,它不會主動替你轉(zhuǎn)義一下再賦值,你可能會說:這不就是DOM Base XSS嗎? 你想的簡單了,對于我來說是DOM Based、反射式的還是存儲式的,這種分類意義不大,解決方案都是一樣,這就是高級別抽象后的解決方案的統(tǒng)一。這個問題較復雜,我們循序漸進的來了解它,您先知道有這么回事兒。有心的讀者可能會問:C/C++/Java會有這種情形嗎? 答案是:當然有,有一些軟件為了兼容性等諸多因素考慮,會在編譯時依據(jù)條件不同動態(tài)生成新的代碼然后再進行編譯,此時你該如何是好?這不是本文討論的重點,為了敘述的完整性,提一下有這么回事兒就行。本文的重點是Web應用當中的XSS問題。
鋪墊的差不多了,我們來一起看一段以下的HTML的document:
- <html>
- <body>
- <h1>jiayzhan's item</h1>
- <a ID="jiayzhan" onclick="alert('jiayzhan\'s onclick')" href="http://www.jiayzhan.org" ">jiayzhan's link</a>
- </body>
- <script>
- location.replace("jiayzhan's URL")
- </script>
- </html>
【說明】帶有字符串【jiayzhan】的一整串,您需要將它們理解為類似于這樣的JSP代碼:<%=request.getParameter(“jiayzhan”);%>
下面一步一步來說瀏覽器是如何解碼(反轉(zhuǎn)義)的,我就用字符串本身作為位置標識來解釋:
1. 位置:jiayzhan’s item, 瀏覽器在解析這個位置的字符串時,無論如何,會對其進行一次HTML解碼,(HTML編碼、解碼,請參考)
2. 位置:jiayzhan\’s onclick,無論如何,瀏覽器會對其進行:1) 先做HTML解碼 2)再做JS解碼
3. 位置: http://www.jiayzhan.org,無論如何,瀏覽器會對其進行:URL解碼
4. 位置:jiayzhan’s URL, 無論如何,瀏覽器會對此位置字符串進行:1)先JavaScript解碼 (JS編解碼請參考) 2)后URL解碼
以上只是一維與二維組合的情形,實際當中還會有三維以上的解碼組合,特別是大量使用Web2.0技術(shù)的網(wǎng)站。您理解了嗎? 如果您真的理解了,請分析一下以下代碼段中的變量<%=request.getParameter(“jiyazhan_url”)%>,瀏覽器如何做解碼?如果你真的理解了瀏覽器的解碼過程,你何嘗不知道你在解決XSS問題時的編碼過程? 請在評論中回復,我會及時與您討論:
<a href=”javascript:backToHome(<%=request.getParameter(“jiyazhan_url”)%>)” >click jiayzhan</a>
說明:backToHome是一個javascript函數(shù)
在這里先不說它的解碼過程,提示一下它是一個三維解碼過程,供讀者討論吧。
寫到這里,我想點睛一下我上文所述的”許多公司已經(jīng)90%以上的程度解決了XSS問題”而不是100%的原因了。本ID曾給某一知名公司報了一個XSS問題,其存在XSS問題的地方因為是一個三維的解碼語法環(huán)境,應用安全與開發(fā)人員許久也沒有找到合理的解決方案,最終此公司刪除了那個有XSS問題的功能點。不點名了,如果有幸遇到此公司的應用安全人員,這篇文章讀明白了,問題應該就好解決了。還是那句話:知識與知識運用相隔甚遠,我無法保證您可以正確運用它。
既然知道瀏覽器是如何解碼的了,我們該如何做編碼的事應該水到渠成了,不過依我的經(jīng)驗看,許多專業(yè)做XSS問題fix的解決方案的安全人員依然存在難以轉(zhuǎn)過這個彎的情況。下篇文章我將舉幾個具體的例子來說明如何利用解碼原理用來徹底解決XSS問題的編碼問題,以及在涉及到多重解碼的環(huán)境如果考慮維數(shù)不足所帶來的安全隱患是什么(透露一下:如果編碼維數(shù)考慮不足的可能結(jié)果是:
1). 其實等于沒解決,只是漏洞發(fā)現(xiàn)的難度大了一些而已,對于我來說都一樣
2). 改變了用戶的輸入,比如:用戶想找一個【“】,結(jié)果系統(tǒng)幫它找的是【\"】或【%22】或【"】......)。
今天先這樣吧,純技術(shù)文章,不知道有多少同行會耐心的閱讀它。