jQuery <= 1.11.3 DomXSS漏洞

 

聽團裏說WordPress又爆跨站漏洞了:「 XSS漏洞在Jetpack和二十五默認主題影響百萬WordPress用戶 」,分析發現原來是jQuery老版本的DOM XSS漏洞【錯誤#9521】。
11年dmethvin提交jQuery 1.6.1版本的Ticket#9521,其緣由是由$() | jQuery()預選的CSS選擇器在其餘狀況下可用於建立HTML元素,若是編碼不當(事實上不少編碼不當的狀況),將會致使產生DomXSS漏洞。

示例(jQuery 1.6.1)javascript

  1. <html>
  2. <head>
  3.     <title>jQuery DomXSS test</title>
  4.     <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
  5.     <script>
  6.         $(location.hash);
  7.     </script>
  8. </head>
  9. <body>
  10. Hello, jQuery.
  11. </body>
  12. </html>
複製代碼



WordPress默認主題二十一個例子php

example.html 297-299行:
  1. // set permalink
  2. var permalink = cssclass.split(' genericon-')[1];
  3. window.location.hash = permalink;
複製代碼

console.log永久連接:css

  • http://linux.im/wp-content/themes/twentyfifteen/genericons/example.html#123
  • console.log(permalink):genericon-123
335-343行:
  1. // pick random icon if no permalink, otherwise go to permalink
  2. if ( window.location.hash ) {
  3.     permalink = "genericon-" + window.location.hash.split('#')[1];
  4.     attr = jQuery( '.' + permalink ).attr( 'alt' );
  5.     cssclass = jQuery( '.' + permalink ).attr('class');
  6.     displayGlyph( attr, cssclass );
  7. } else {
  8.     pickRandomIcon();
  9. }
複製代碼
若是存在window.location.hash則拼接固定連接並使用jQuery的進行屬性操做,問題出現,當咱們將的location.hash爲設置<img src=@ onerror=alert(1)>時,致使跨站。

jQuery 1.6.1源碼html

  1. >_ $
  2. jquery.js:25 function ( selector, context ) {
  3.         // The jQuery object is actually just the init constructor 'enhanced'
  4.         return new jQuery.fn.init( selector, context, rootjQuery );
  5.     }
  6. >_ jQuery.fn.init
  7. jquery.js:93 function ( selector, context, rootjQuery ) {
  8.         var match, elem, ret, doc;
  9.         // Handle $(""), $(null), or $(undefined)
  10.         if ( !selector ) {
  11.             return this;
  12.         }
  13.         // Handle $(DOMElement)
  14.         if ( selector.nodeType ) {
  15.             this.context = this[0] = selector;
  16.             this.length = 1;
  17.             return this;
  18.         }
  19. ......
  20.         if (selector.selector !== undefined) {
  21.             this.selector = selector.selector;
  22.             this.context = selector.context;
  23.         }
  24.         return jQuery.makeArray( selector, this );
  25.     }
複製代碼

其中jQuery.fn.init:html5

  1. if ( typeof selector === "string" ) {
  2.     // Are we dealing with HTML string or an ID?
  3.     if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
  4.         // Assume that strings that start and end with <> are HTML and skip the regex check
  5.         match = [ null, selector, null ];
  6.     } else {
  7.         match = quickExpr.exec( selector );
  8.     }
複製代碼

quickExpr對選擇器進行過濾,正則爲:java

  1. quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,
複製代碼
顯然咱們上面的Payload是能經過的。

jQuery 1.7.2源碼node

當時漏洞報告者在#9521中提到修復方案:
  1. the quick patch by jquery is here
  2. -       quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,
  3. +       quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,
複製代碼

儘管在開始的例子代碼中不能生效,但因爲程序開發人員的編碼習慣顯然按照上面的修復並無什麼卵用,修復後原有的攻擊代碼效果:jquery

  1. >_ location.hash
  2. "#test<img src=1 onerror=alert(1)>"
  3. >_$(location.hash)
  4. []
複製代碼

由於正則新增#的緣由致使增長失敗,在真實環境中屬性或其餘操做直接使用location.hash的可能性叫小,開發人員以及業務需求使得上面的修復方案沒有意義,例如開始提到的WordPress默認主題XSS漏洞337行:linux

  1. permalink = "genericon-" + window.location.hash.split('#')[1];
複製代碼
程序將獲取到的哈希['#test111'] split後,只保存test111,也就能夠獲得咱們能忽略到1.7.2的修復。

jQuery 1.11.3源碼ajax

在前面版本中其實可以得以證實jQuery團隊確實修復#9521的問題就是quickExpr的上方註釋:
  1. // A simple way to check for HTML strings or ID strings
  2. // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
  3. quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,
複製代碼

可能開發團隊遇到了1.7.2中我提到問題的尷尬窘境,他們在1.11.3又對其進行了升級:

  1. rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,
複製代碼
看到這個正則我幾乎無語,使用開頭和結尾<就能輕易繞過:

終於,他們在2.x系列正式修復了這個問題:
  1. rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
複製代碼

其餘瀏覽器

如何所見,上面這些Payload並不會在Safari中成效,經過調試便可發現Chrome未對location.hash部分進行URL編碼處理進入函數,而Safari會通過URL編碼進入函數,是這樣的:

可是咱們仍然可使用html5的一些特性,引起錯誤並onerror出來:
  1. file:///Users/evi1m0/Desktop/1.html#<video><source/onerror=alert(1)>
複製代碼


 

來源:

http://www.hack80.com/forum.php?mod=viewthread&tid=47045

相關文章
相關標籤/搜索