PEANUT-XSS

<aside> 📢 Nutshell is pretty cool. Want to test it out?

admin bot: nc peanut-xss-bot.chal.uiuc.tf 1337

Author: arxenix

</aside>

The page looks like a simple editor page where you can write html and render it into the browser AND it uses nutshell library to make expandable, embeddable explanations. This is the code of the page.

Untitled

<html>
<body>
    <h2>To write a section,</h2>
    <p>just use headings &amp; paragraphs like this! Then…</p>
    <h2>To embed a section,</h2>
    <p>just make a link with :colon at the front… <a href="#ToWriteASection">:LIKE THIS</a>!</p>
</body>
</html>
    </textarea>
    <button id="submit" style="display: none;">Preview</button>
    <script>
      const $ = document.querySelector.bind(document);
      const nutshell = new URLSearchParams(location.search).get("nutshell");
      if (nutshell) {
        preview.innerHTML = DOMPurify.sanitize(nutshell);
      } else {
        var editor = CodeMirror.fromTextArea($("#editor"), {
          mode: "htmlmixed",
          lineNumbers: true
        });
        $("#submit").style.display = "";

        $("#submit").onclick = () => {
          location.search = `nutshell=${encodeURIComponent(editor.getValue())}`;
        };
      }
    </script>
  </body>
</html>

As we can see from the code the page use dompurify in order to sanitize the code that we put and that will be rendered. Nutshell by default also use dompurify in order to make the embedded content ,whetever is a website or a video, safe. Obviously the dompurify version was up to date, here’s when the library sanitize the code

Untitled

Now we recap all that we have:

So we are very limited in what we are doing, what was left was to go trough all the library code to see what the library does.

By looking at the real code that start approximately at line 600 we can see a weird things that nutshell is doing.

Untitled

This code retrieves all the <a> (anchor) elements within the dom element and stores them in an array called expandables. The querySelectorAll('a') method selects all the <a> elements, and the spread operator [... ] converts the resulting NodeList into an array. The filter function then filters the links based on a condition: the innerText of the link should start with a colon (:). This filters out the links that do not meet the criteria. Then it iterates over each link in the expandables array using the forEach method. For each link, it adds the CSS class 'nutshell-expandable' to the link's class list using classList.add(). Additionally, it sets the attribute mode of the link to "closed" using setAttribute(). It creates a new <span> element and assigns it to the variable linkText. The <span> element is a generic container that can hold text or other elements. And finally

linkText.innerHTML = ex.innerText.slice(ex.innerText.indexOf(':') + 1);

This line sets the innerHTML property of the linkText element. The innerHTML property represents the HTML content inside an element. In this case, it's being assigned a value based on the following expression: ex.innerText.slice(ex.innerText.indexOf(':') + 1)