DOJO Challenge #25 Winners!

July 27, 2023

CSS injection challenge

The #25th DOJO CHALLENGE, RootCSS, aims to exploit a CSS injection by making the application execute a CSS file located on the attacker’s server. The malicious CSS code must then manipulate the original CSS code of the challenge and trick the client-side JavaScript into executing its code.

💡 You want to create your own DOJO and publish it? Send us a message on Twitter!


We are happy to announce the list of winners of the #25 DOJO Challenge.


  • The best write-ups reports were submitted by: Hitsuomi, nishacid and hack42! Congrats 🥳

The swag is on its way! 🎁

Subscribe to our Twitter and/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


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.


We would like to thank everyone who participated. The DOJO challenge #25 gave us a large amount of high quality reports for this DOJO challenge, well done to all of you who reported!

We had to make a selection of the best ones. These challenges allow to see that there are almost as many different solutions… as long as there is creativity! 😉

Thanks again for all your submissions and thanks for playing with us!

Hitsuomi‘s Write-Up

————– START OF Hitsuomi‘s REPORT ——————

Cross Site Scripting (XSS) via stylesheet custom url ($URL)

Cross-site scripting (XSS) is a type of security vulnerability found in web applications. It occurs when an attacker injects malicious code, typically in the form of scripts, into a trusted website or web application. This often happens through inputs provided by users, such as search boxes or comment sections, which are not properly validated or sanitized by the application.


First, I observed the provided code. I noticed that if we try to break the following href with a double quote, it would be replaced by “UseThePowerOfCSS“.

<!-- Before append double quote -->
<link rel="stylesheet" href="https://$URL/style.css">
<!-- Result with double quote -->
<link rel="stylesheet" href="https://_UseThePowerOfCSS_/style.css">

Seeing that it isn’t good, an idea comes to me, which is to set up an HTTPS microservice to import a customized CSS file.

To do this, I am using a Python script that handles SSL (HTTPS) and will use my IP plus the port 8000 that I assign to it.

Now that I have the ability to import via a URL, I test to see if the import of my file is successful by changing the background to a personalized image while ensuring that the background change and its coverage are specified as important.

Here is my code and the result.

background-image: url('https://{URL}/image.jpg')  !important;
background-repeat: no-repeat;
background-size: cover !important;

This confirms to us that we can modify elements. From now on, we only need to see how to perform our XSS.


We will now consider how to carry out the attack.

Upon careful observation, I see two interesting things.

Firstly, we have a “root” element style which involves creating variables in CSS to easily call them, and therefore, in most cases, maintain a consistent theme (example: all the elements are in green, etc.).

This is the code:

    :root {
        --hacker: A person dressed in a black hoodie along with a laptop;
        --developer: A person who yells at their code to make things work;
        --bug: "It's a feature";

The second one is this part of code:

<div id="btn">
    <button onclick="Description('--hacker')">Hacker&#129399;</button>
    <button onclick="Description('--developer')">Developer&#x1F4BE;</button>
    <button onclick="Description('--bug')">Bug&#128126;</button>
    <p id="desc"></p>

    function Description(typ) {
        let style_element = getComputedStyle(document.body);
        let txt = style_element.getPropertyValue(typ);

        document.getElementById('desc').innerHTML = `[<b style="color:lightgreen">+</b>] <i>${txt}&#x2757;</i>`;


This code creates a HTML structure with buttons and a paragraph element. When a button is clicked, the function Description(typ) is called with a specific parameter (either ‘–hacker’, ‘–developer’, or ‘–bug’).

Within the function, it retrieves the computed style of the document body element, specifically the value of the property specified by the parameter. It then updates the inner HTML of the element with the ID ‘desc’ to display a formatted message using the retrieved value.

I am modifying the CSS to look like this:

:root {
    --hacker: A person dressed in a black hoodie along with a laptop;
    --developer: A person who yells at their code to make things work;
    --bug: <img src='#' onerror=alert("XSS") /></img> !important;

What will happen when we call our script is that it will first take the CSS stating that the variable “–bug” is the most important and therefore override this variable throughout the page. Then, when we click on “bug” on the page, it will attempt to load an image that will create an error and consequently execute our JavaScript code.

I import the code, everything is fine:

I click on the “bug” button, and there our XSS appeared.


For individual users, the risk of Stored XSS includes the potential exposure of personal data such as login credentials, financial information, or social security numbers. Attackers can exploit this vulnerability to steal sensitive data or gain unauthorized access to user accounts, leading to identity theft, financial loss, or even fraud.

In the case of companies, Stored XSS poses a significant risk to the organization’s reputation, business operations, and customers. If an attacker successfully exploits this vulnerability, they can inject malicious code into the company’s website, affecting all users who access it. This can lead to the theft or manipulation of critical business data, compromise customer information, result in financial loss, and damage the company’s brand image.

How to mitigate

To mitigate the XSS vulnerability in the provided code, we can take the following steps:

  1. Sanitize user input: Before using user input in your code, ensure that you properly sanitize it to remove any potentially malicious content. In this case, you should validate and sanitize the input used to set the --bug variable to prevent the injection of arbitrary code.
  2. Implement Content Security Policy (CSP): Use a Content Security Policy to restrict the types of content that can be loaded and executed on your webpage. By setting a strict CSP, you can prevent the execution of inline JavaScript and unauthorized loading of external resources.
  3. Use a security-focused HTML sanitization library: Utilize a trusted and actively maintained HTML sanitization library to clean any user-generated or dynamic content that is rendered on your webpage. This will help to remove any potentially malicious code and prevent XSS attacks.

By implementing these security measures, we can effectively mitigate the XSS vulnerability in the code and protect your website against such attacks.

Thank you for reading.

————– END OF Hitsuomi‘s REPORT ——————