1、背景
javascript
jQuery官方上週發佈了最新版本3.5.0,主要修復了兩個安全問題,官方博客爲:html
https://blog.jquery.com/2020/04/10/jquery-3-5-0-released/
據NVD描述:在大於或等於1.2且在3.5.0以前的jQuery版本中,即便執行了消毒(sanitize)處理,也仍會執行未來自不受信任來源的HTML傳遞給jQuery的DOM操做方法(即html()、.append()等),從而致使xss漏洞。java
2、前置知識
在講解漏洞以前,須要瞭解jQuery的基本用法和歷史漏洞,具體可參考:jQuery框架漏洞全總結及開發建議:jquery
https://mp.weixin.qq.com/s/M1BYj6VbeoNV4C5M7cR_hA
而與這次jQuery漏洞聯繫比較緊密的是html()等方法,此方法返回或設置被選元素的內容 (inner HTML),可用於設置全部選定元素的內容,看一個簡單的使用案例:git
此處定義一個點擊事件,會對全部的p元素進行匹配,並修改成相同的內容。
github
3、漏洞復現
對於此漏洞原做者搭建了在線環境,內置了三個xss poc,點擊Append via .html()按鈕便可觸發xss:apache
https://vulnerabledoma.in/jquery_htmlPrefilter_xss.html
審查源碼,邏輯很簡單:api
首先使用以下代碼模擬了一個開發場景,即將頁面的全部div元素替換爲根據ID取到的sanitizedHTML:瀏覽器
<script>function test(n,jq){ sanitizedHTML = document.getElementById('poc'+n).innerHTML; if(jq){ $('#div').html(sanitizedHTML); }else{ div.innerHTML=sanitizedHTML; }}</script>
雖然三個poc都使用了包含onerror事件的img標籤,但其實它們是放在屬性或style元素內部,所以會繞過HTML清理器。安全
以poc1爲例,根據此id取到的值以下:
<style><style /><img src=xonerror=alert(1)>
點擊以後,執行xss,此時審查div元素:
發現咱們提交的poc多了一個閉合標籤</style>,變成了:
<style><style /></style><imgsrc=x onerror=alert(1)>
</style>閉合了<style>標籤,成功執行後面的<img>腳本,致使xss。
4、漏洞原理
1、CVE-2020-11022
致使上述問題的關鍵是,在html()方法中,做爲參數傳遞的HTML字符串將傳遞到 $ .htmlPrefilter()方法:
https://api.jquery.com/jQuery.htmlPrefilter/
這個方法用於替換自閉合標籤,如將<tagname /> 替換爲 <tagname ></tagname>,3.x版本以前使用的正則爲:
rxhtmlTag =/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi[...]htmlPrefilter: function( html ) { return html.replace(rxhtmlTag, "<$1></$2>" );}
3.x以後使用的正則爲:
rxhtmlTag =/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi
這就使用到環境裏的poc2(僅適用於jQuery3.x),注意這裏的xss payload是做爲屬性出現,因此能夠繞過消毒器規則:
<img alt="<x" title="/><img src=xonerror=alert(1)>
該poc使用html()方法執行後發現變爲:
<img alt="<x" title="/></x」><imgsrc=x onerror=alert(1)>
該正則會將x"識別爲標籤並新增</x」>閉合標籤,從而達到xss的效果:
2、CVE-2020-11023
針對上述漏洞原理,jQuery Team進行了修復,修復手段爲將$.htmlPrefilter()方法替換爲標識函數,所以傳遞的HTML字符串如今再也不通過htmlPrefilter函數處理,從而成功修復了漏洞。但仍有一些手段能夠繞過,CVE-2020-11023就是針對CVE-2020-11022的繞過:
繞過使用的是另外一個特性,某些特殊的標籤在通過html()方法處理時,會因爲HTML的特性或瀏覽器的bug而使得這些標籤被移除。
option就是這些特殊標籤之一,咱們知道option 元素經過位於 select 元素內部來構造一個選擇列表,但若是沒有select元素,option會被移除。爲了解決這個bug,若是傳入參數的第一個元素爲option,jQuery會新增<select multiple='multiple’>和</select>。
因此咱們提交poc3:
<option><style></option></select><imgsrc=x onerror=alert(123456)></style>
通過處理會變爲:
<select multiple='multiple'><option><style></option></select><imgsrc=x onerror=alert(123456)></style></select>
根據HTML從前日後解析的順序,會先解析一個<select>標籤,且<select>不容許將大部分HTML標籤包裹其中,致使<style>被忽略,然後識別<img>標籤從而xss。
此漏洞在最新的3.5.0中也被修復,對於特殊的標籤進行了處理。
https://github.com/jquery/jquery/commit/966a70909019aa09632c87c0002c522fa4a1e30e#diff-51ec14165275b403bb33f28ce761cdedR25
5、總結
1、漏洞利用
1)系統使用jQuery的html()、append()或$('<tag>')等方法處理用戶輸入;
2)用戶輸入已通過「消毒」(sanitize)處理。
2、修復方案
1)更新jQuery到3.5.0或更高版本
https://code.jquery.com/jquery-3.5.0.js
2)使用XSS清理工具清理用戶輸入的HTML,官方推薦:
https://github.com/cure53/DOMPurify
參考:
https://mksben.l0.cm/2020/05/jquery3.5.0-xss.html?m=1
本文分享自微信公衆號 - 卓文見識(zhuowenjianshi)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。