CSRF × self-XSS — the chain

Cross-Site Request Forgery
account settings — display name (shown to everyone on the account page)
Display name: Course Student
POST /csrf/lab25/name.php HTTP/1.1

name=<new value>&csrf_token=CSRF-TOKEN-1234

Watch that csrf_token field — it travels in every honest request and looks like real defense. In repeater the first question is always: does the endpoint read it, or just receive it?

Method — turn a self-XSS into a finding
  1. Marker first, always: <u>test</u> through the box → renders → HTML lands raw in a stored sink that every profile view executes.
  2. Payload → alert fires. Then the honest classification: this only runs in your context — you made the request, you rendered the name. That is self-XSS, and programs reject it for exactly that reason ("we need proof it works against other users").
  3. The chain: CSRF is one of the ways to escalate a self-XSS. Cross-site force the same POST (the update survives any frame — remember SOP stops reading, not sending), the victim's context renders your stored name → your code runs in their session. A new vulnerability created by combining two.
  4. Inspect the token before assuming it blocks you: this endpoint receives csrf_token and never validates it. The POC submits happily with a dummy value — or with the field missing entirely. ("The token is being passed" ≠ "the token is being checked.")
  5. Tools note: Caido's flow/assistant and Burp's engagement tools both auto-generate a CSRF POC from a replayed request; a 10-line HTML form by hand teaches the same mechanics either way.
  6. Report framing: "self-XSS escalated via CSRF — forced stored payload into victim sessions", demonstrated exactly as here: POC auto-firing in a logged-in browser.
Spoiler — the chain POC (works despite the cosmetic token)
<form method="POST" action="https://stuxnet.pro/csrf/lab25/name.php">
  <input type="hidden" name="name"
        value="<script>alert(document.domain)</script>">
  <input type="hidden" name="csrf_token" value="anything-at-all">
  <button type="submit">chain POC</button>
</form>

Two beats in one: the payload rides the POST body, and the token field carries anything (or is omitted) — the endpoint never reads it. The same POC body as curl: curl -X POST 'https://stuxnet.pro/csrf/lab25/name.php' --data-urlencode 'name=<script>alert(document.domain)</script>' --data-urlencode 'csrf_token=anything'. Fire it from another origin/hosted page in a logged-in browser: the name change is the payload delivery — alert executes on the victim's next profile view. A different browser proves the chain without your session anywhere near it.

Spoiler — other self-XSS escalators (beyond CSRF)

CSRF is the classic partner, not the only one: name-change endpoints that don't revalidate (threaten password reset flows), account-switching/impersonation features, and privileged shared pages where your stored name renders to higher-privilege users (administrators being the jackpot). The chain mindset is the transferable skill: combine the XSS with anything that puts it into someone else's context — that combination is the reportable finding.