利用location來變形我們的XSS Payload

此前小編在群里看大神們討論的時(shí)候,有了一些新的想法,所以整理出來了。在XSS的時(shí)候,有時(shí)候有的過濾器很變態(tài),會(huì)過濾很多特殊符號和關(guān)鍵詞,比如&、(、)、#、'、",特別是&和括號,少了的話payload很難構(gòu)造出來。

舉個(gè)例子吧,比如過濾器過濾了array("(",")","&","\\","<",">","'"),而沒有過濾雙引號,輸出點(diǎn)在<img src="xxxx">,xxxx這里,怎么構(gòu)造一個(gè)可以利用的XSS?Payload?

過濾代碼如下:

1 ?? ?<?php
2 ?? ?header('X-XSS-Protection: 0');
3 ?? $xss?= isset($_GET['xss'])?$_GET['xss']:'';
4 ?? $xss?=?str_replace(array("(",")","&","\\","<",">","'"), '',?$xss);
5 ?? echo?"<img src=\"{$xss}\">";
6 ?? ?>

所有人肯定都知道,先閉合雙引號,后面使用onerror事件觸發(fā)XSS。輸入xss=1" onerror=alert(1),就可以構(gòu)造成如下html:

1 <img?src="1"?onerror=alert(1)>

可是括號被過濾了怎么辦?窗戶都彈不出來。

聰明人可能想到,用html實(shí)體來代替括號,變成這樣:

1 ?? <img?src="1"?onerror=alert(1)>

一樣可以彈出。但是,&也被過濾了。有同學(xué)可能還想到,用unicode或8進(jìn)制編碼(如\u0028或\50)來繞過,也是不行的,就算沒過濾"\"號,在html屬性中也不能直接用這種編碼。

這里涉及到j(luò)s中關(guān)鍵詞(函數(shù)名、變量名、保留字等)、字符串、左值與右值的問題,這也是所有語言中都有的問題。

舉個(gè)例子,比如test="phithon";,這里test就是左值、變量名,"phithon"就是右值、字符串,=和"是符號。字符串中可以用編碼來替換原始字符,比如用\u0028代替左括號(,或用\50來代替左括號(。左值必須是可寫的,比如一個(gè)變量,我們不能把字符串放在等號左邊,因?yàn)樽址且粋€(gè)只讀的值。還有,有關(guān)于javascript的字符編碼,都只能用在字符串中,不能用字符編碼去代替符號或變量名、函數(shù)名。

我們要把js中的編碼和html中的編碼區(qū)分開,在html屬性中可以用字符實(shí)體代替原字符,比如(代替(,但js中的unicode與8進(jìn)制編碼,只能放在js中的“字符串”中。比如<img src=1 onerror=alert\u0040\u0041>是不行的,但<img src=1 onerror=alert()>可以。

所以回到我們的測試,根據(jù)我之前說的,這些編碼在payload里都不能用,因?yàn)槔ㄌ柺恰胺枴?,js編碼不能替換符號,而html實(shí)體又因?yàn)檫^濾了&而不能使用。

這里一個(gè)小tip就是,我們可以利用location加javascript偽協(xié)議,將“符號”、“變量名”、“函數(shù)名”統(tǒng)統(tǒng)變成“字符串”,在字符串中我們可以使用所有js里可以使用的編碼,去構(gòu)造payload。

怎么變?比如我們可以構(gòu)造如下payload:

1 ?? <img?src="1"?onerror=location="javascript:alert(1)">

這個(gè)時(shí)候,alert(1)被放進(jìn)了字符串里,因?yàn)橛衘avascript偽協(xié)議,所以也可以執(zhí)行xss。在字符串中就能夠用很多編碼了,雖然我們這里過濾了\,但可以用url編碼來替代括號,如下payload:

1 ?? <img?src="1"?onerror=location="javascript:alert%281%29">

就能成功繞過上述filter。

測試一下:http://xxxx/index.php?xss=1"%20onerror%3Dlocation%3D"javascript%3Aalert%25281%2529"%20

那么,我們把難度提高一點(diǎn)。再攔截一些關(guān)鍵詞,比如document,cookie,eval,setTimeout,alert等:

1 ?? <?php
2 ?? header('X-XSS-Protection: 0');
3 ?? $xss?= isset($_GET['xss'])?$_GET['xss']:'';
4 ?? $xss?=?str_replace(array("(",")","&","\\","<",">","'"), '',?$xss);
5 ?? if?(preg_match('/(script|document|cookie|eval|setTimeout|alert)/',?$xss)) {
6 ????exit('bad');
7 ?? }
8 ?? echo?"<img src=\"{$xss}\">";
9 ?? ?>

這時(shí)我們怎么能彈出cookie?

這個(gè)時(shí)候我們可以用字符串拼接的方式繞過,這也是得益于我們之前將要執(zhí)行的“函數(shù)”變成了“字符串”才有的效果,我們不可能直接<img sec=1 onerror='al'+'er'+t(1)>,js中只有“字符串”才能拼接。

payload例如:

1 ?? <img?src="1"?onerror=location="javascr"+"ipt:al"+"ert%?? 28docu"+"ment.co"+"okie%29">

用拼接來繞過一些關(guān)鍵詞。