March 12, 2021

The #7th DOJO CHALLENGE was on finding a valid WAF bypass to exploit an XSS on prototype pollution vulnerability.


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


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 an input field that you could inject, but many characters were sanitized and the WAF could detect them. The goal was to get around that WAF and find a way to exploit an XSS.

See the challenge page >

We 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.


Zomsop82‘sreport was detailed, informative, and good at explaining the WAF exploitation logic.
The others reports, notably Marcosen‘s and ivarsvids‘s were also very nice, we’re sorry can’t publish them all because that’s where you clearly witness the outstanding creativity of our community.
Thank you all for playing with us!

Zomsop82‘s Write-Up

————– START OF Zomsop82 REPORT ——————


Website allow user to control a JavaScript variable named “config” which can be used to perform reflected XSS.
It is noted that a “WAF” is in place to avoid XSS but can be bypassed.


  • Website allow user input with almost no restriction to take place in a JavaScript variable.
  • User input is expected to be valid JSON which restricts a bit the allowed charset and forbid usage of JavaScript features such as functions.
  • The “WAF” in place forbid characters such as ["<", ">", "'", '"', "?"], which would be enough to restrict XSS if previous checks were not hijackable.
  • The main issue lie in the function isObject() which is bypassable because user can modify the JavaScript object prototype and masquerade as another type by declaring a property
    __proto__ such as config = {"__proto__": {}}
  • Once type check bypassed, the control loop over forbidden characters was not working anymore because of missing includes function on object. This could be fixed by using Array prototype on config object such as
    config = {"__proto__": []}, which has an includes function (See [1]) and is then inherited by config object allowing to bypass the loop.
  • Now that the config object can pass through the “WAF” without issues, we can add a payload with JavaScript code execution inside name property such as
    {"name": "<script>alert(1)</script>".

Final payload is:

{"__proto__":[], "name": "<script>alert(1)</script>"}



{"__proto__":[], "name": "<script>alert(1)</script>"}
  1. Input following payload in $config field:
    {"__proto__":[], "name": "<script>alert(1)</script>"}
  2. Validate
  3. XSS triggers


  • Account Hijacking
  • Stealing credentials
  • Expose sensitive data


  1. JavaScript has a lot of quirks and will have many more, it is generally unsafe to consider that you can “control” an almost fully controlled user input variable. Though, to fix the isObject function it might be better to rely on instanceof JavaScript keyword.
  2. In all case, use a sanitization library such as DOMPurify before returning/interpreting user controlled input. See [3].



  • [1]
  • [2]
  • [3]

————– END OF Zomsop82 REPORT ——————