XSS編碼與繞過


 XSS編碼與繞過

0x00 背景

對於了解web安全的朋友來說,都知道XSS這種漏洞,其危害性不用強調了。一般對於該漏洞的防護有兩個思路:一是過濾敏感字符,諸如【<,>,script,'】等,另一種是對敏感字符進行html編碼,諸如php中的htmlspecialchars()函數。

一般情況,正確實施這兩種方案之一就可以有效防御XSS漏洞了。但其實也會有一些場景,即使實施了這兩種方案,攻擊者也可以繞過防護,導致XSS漏洞被利用。

0x01 繞過場景

下面主要是參考文章http://www.freebuf.com/articles/web/43285.html

場景一:XSS注入點在某個html標簽屬性中,代碼片段如下

可以看到,這里防護措施采用的是方案一:過濾敏感字符。那么這里如果輸入javascript:alert (11),是會被過濾掉的,輸出的內容會是:

這當然不能彈框,常規的xss payload就會失敗了。如同參考文中所說的,這里繞過方法有很多中,你完全不需要使用 > 去閉合html標簽,也可以用其他關鍵字來代替javascript,不過既然說的是編碼問題,當然要用編碼問題來解決問題。

這里可以對"javascript:alert(11)"進行html編碼來繞過,你可以試試將html編碼后的payload傳遞給name參數,也就是:javascript%3Aalert%2811%29,可以看到熟悉的窗口又彈出來了。原因就是,瀏覽器在解析到這段代碼時,會對其先進行html解碼,然后當觸發onclick事件后,會調用js引擎對其進行js編碼后執行js代碼,所以就看到了彈窗。原文在這里只提到了html編碼的方式,其實這里還可以對payload進行js編碼。但是要注意的是,這里不能將整個payload進行編碼,你要像這樣:

又可以看見彈框了。(是不是略微有點看不懂啊,沒關系,接下來還有更繞的)

 

場景二:XSS注入點在js標簽中,代碼片段:

這里采用的防護措施是第二套,使用php內置函數htmlspecialchars對敏感字符進行編碼。如果輸入正常的payload,如:<img src=1 onerror=alert(11)>,是不會有彈窗的,此時瀏覽器的輸出:

這里的敏感字符< >,已經被html編碼了,最后在<div>標簽里面輸出的時候瀏覽器再使用html解碼將其原文顯示出來,但是並不會再觸發js引擎了,所以也就沒有彈窗了,利用失敗。

這里使用js編碼就可以繞過了,因為瀏覽器是先js解碼然后再html解碼,通過js編碼后的payload在html解碼的時候已經是正常的html了,就會觸發js引擎,彈框也就出來了。

試試js編碼后的payload:

 

看到這里,你心中肯定有疑問,瀏覽器到底是怎么解碼的,為什么一會先js解碼,一會兒又是先html解碼?起初我在看到這里時候也一直很納悶,原文里面並沒有對瀏覽器為什么這樣解碼說明原因,直到我看到這篇文章http://xuelinf.github.io/2016/05/18/編碼與解碼-瀏覽器做了什么/。該作者從原理上對瀏覽器編碼解碼進行了說明,揭開了我的疑問,這篇文章也主要是說明該問題。

0x02 瀏覽器編碼解碼方式

來看看瀏覽器處理一次完整的http請求,會涉及到的編碼解碼問題。

  1. 當瀏覽器發送http請求時,會先對特殊字符進行URL編碼后,發送給服務器。
  2. 服務器收到客戶端發送來的http請求,會對其進行URL解碼后,再進行處理,處理完成后將結果返回給瀏覽器。
  3. 瀏覽器接收到html文件后,最先是觸發html解析器來解析html,將標簽轉化為內容樹中的DOM節點,此時在識別標簽的時候,html解析器是不能識別哪些被html實體編碼了,只有當整個DOM樹建立起來后,才能對每個節點的內容進行識別,如果有html實體編碼,再對其進行解碼。
  4. 在html解析器過程中,遇到js標簽諸如<script>會調用js解釋器對js代碼進行解析,而js DOM API會對DOM結構進行更改,DOM樹節點的更改也會反過來觸發html解釋器。
  5. CSS解釋器也會在html解釋器過程中參與進來,但它不會干擾到DOM樹,它會結合<style>標簽和CSS文件以及html指令來構建render tree。

以上,就是瀏覽器解析一次完整http請求所會涉及到的編碼解碼問題。瀏覽器在收到html文件后,如果沒有js DOM API的參與,那么瀏覽器會按照html解碼àCSS解碼àjs解碼的順序解析下去,但是由於js DOM API的存在,解碼順利會被打亂,所以有了上面兩個場景中不同的解碼順序,那么到底為何要按照這樣的解碼方式呢?再來具體看看js解釋器的處理流程。

當瀏覽器在處理諸如<script> <style>標簽,解釋器會自動切換到特殊解析模式,src href后邊加入的javascript為URL,也會進入到JS解析模式。而進入該解析模式的時候,該DOM節點已經建立起來了,但是html解釋器還並未進行html解碼。當觸發js解釋器后,js會先對內容進行解析,如果有js編碼就會進行解碼操作,接下來是就是執行里面的js語句。所以此時執行該js語言前的解碼順序為js解碼-->html解碼。

來看看能夠觸發js引擎的標簽:

  • 直接嵌入< script> 代碼塊。
  • 通過< script sr=… > 加載代碼。
  • 各種HTML CSS 參數支持JavaScript:URL 觸發調用。
  • CSS expression(…) 語法和某些瀏覽器的XBL 綁定。
  • 事件處理器(Event handlers),比如 onload, onerror, onclick等等。
  • 定時器,Timer(setTimeout, setInterval)
  • eval(…) 調用。

既然js DOM API可以更改瀏覽器正常的解碼順序,那么觸發js解釋器的方式有哪些呢?

了解了瀏覽器的編碼解碼之后,我們再回頭看一下前面的兩個場景。

第一個場景中,js語句是在a標簽中,在onclick事件觸發js解釋器之前,DOM樹結構已經建立完成了,並且這里也沒有DOM API操作,所以瀏覽器會先對該語句進行html解碼,然后再是js解碼,所以當我們對payload進行html編碼后,在js解釋器解析該js語句時,其已經被html解碼了,是正常的js語句,所以能夠正常彈窗。

場景二中,payload是在script標簽里面,瀏覽器解析到這里時,會觸發js解釋器,js解釋器會對該語句進行js解碼操作,我們使用js編碼的payload被還原成正常的語句。雖然此時整個DOM樹已經建立起來了,但是由於DOM API存在,會再一次的調用html解釋器,對我們的payload進行解析,payload里面有js標簽,再一次觸發js解釋器,完成對js語句調用,成功彈窗。

0x03 總結

可以看到,因為瀏覽器豐富多樣的解碼方式,對於XSS的防御不能完全單一依靠編碼和過濾操作,需要根據上下文對輸入語句,先進行相應的解碼之后再進行編碼和過濾操作,才能有效的防御XSS。

 

by:會飛的貓

轉載請注明:http://www.cnblogs.com/flycat-2016


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM