> 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/css-exfiltration.md).

# CSS Exfiltration

There is my writeup for a task on css injection attack.

<figure><img src="/files/0iIbU0atNIdM4Po6GaYe" alt=""><figcaption></figcaption></figure>

The website provide an feedback function for report a bug to admin. After sending test information, we can see that form sent to admin.

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

If we look on responce at burp suite

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

We can see intersting css function `@importurl`

With this function we can parse .css files, can we replace this file?

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

We have full control over the `@importurl` source and can upload our own css files. Based on this, our next step is to try to reproduce css injection.

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

In the picture above you can see a basic css injection based on loading a background and stealing one/the first character in the victim's token sent to our controlled webhook.

So the concept of the attack is to force the victim to download our "infected" .css file, which will steal his first token. We could use a regular webhook tool for this, but since the server automatically adds .css at the end.

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

We should use our own personal server which will locate css payload on endpoint, /somename.css, you can use ngrok or your personal vps to host your payload.

Before sending the payload to the admin, we should check the payload on ourselves. Since we know our token, we will steal its first symbol to check the correct operation.

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

First char is y, and payload is:

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

The payload is located on /bro.css endpoint, so we can check it.

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

After sending we got request on our webhook

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

We successfully performed css injection and "stole" the first character of our token.

Stealing character by character is a long operation, since usually a csrf token stores 32 characters, so I remembered that a few days ago a security researcher [slonser](https://x.com/slonser_), published an interesting post about a new way of the css injection attack, using the attr() function.

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

The thing is that starting with Chrome 133, the attr() function allows you to work with variables

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

&#x20;Now  variable `--val` contains csrf-token but previous type of hooking `background: url(var(--val));`will be incorrect, but if we using `background: image-set(var(--val));` thats work!&#x20;

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

For more details you can look at the official [research](https://x.com/slonser_/status/1912060407344201738).

Based on this we can try to exploit and grab full csrf-token of victim by only 1 request.

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

And test it firstly on our side

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

Awesome! it works, we stole the whole csrf token in one request. It's time to test our exploit on the admin

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

But after some time and a bunch of attempts, this was not successful, I could not steal the token until I realized that the admin bot uses chromium 120v

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

Which means that it won't work on the admin! So at this stage we will return to the oldschool css injection attack, to steal the token character by character. All we need to do is repeat our first attack and extract the files, I used a small script for the slightest automation

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

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

Using a painstaking process, we extract all the characters of the csrf token.

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

After extracting full csrf token , do request as admin and get the flag!

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