<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.
<html>
<body>
<h2>To write a section,</h2>
<p>just use headings & 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
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.
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)