Reflected XSS — Search Bar¶
| Field | Value |
|---|---|
| Platform | PortSwigger Web Security Academy |
| Vulnerability | Reflected Cross-Site Scripting (XSS) |
| Difficulty | Apprentice |
| Injection Point | Search bar (?search= query parameter) |
| Goal | Execute alert() in the browser via reflected XSS |
Phase 1 — Reconnaissance¶
We land on a blog with a search bar.
Phase 2 — Confirming HTML Injection¶
Testing whether the search bar reflects HTML without sanitization:
<marquee>Kasane Teto</marquee>
The text scrolled across the page — the HTML tag was rendered by the browser rather than escaped and displayed as literal text. The application is inserting user input directly into the HTML response without encoding. HTML injection is confirmed, and script execution follows naturally.
Phase 3 — Reflected XSS Execution¶
<script>alert("Kasane Teto")</script>
The alert fired — reflected XSS confirmed. Lab solved. The URL now contains the payload:
/?search=<script>alert("Kasane+Teto")</script>
This URL itself is the attack vector — anyone who clicks it will trigger the script in their own browser context.
Phase 4 — Testing Cookie Theft and the HttpOnly Defence¶
After confirming XSS works, testing whether session cookies are accessible:
<script>alert(document.cookie)</script>
The alert fired but showed nothing — the session cookie is not accessible via JavaScript. The reason is the HttpOnly flag.
When a cookie has HttpOnly set, the browser enforces a strict rule: that cookie cannot be read by any JavaScript running on the page — not even JavaScript from the legitimate domain. The cookie is still sent automatically with every HTTP request, but document.cookie will not include it.
Set-Cookie: session=abc123; HttpOnly; Secure
↑
JavaScript cannot read this
document.cookie returns empty string
HttpOnly does not prevent the cookie from being sent to the server — it only prevents JavaScript from reading it client-side. An attacker with XSS can still perform actions on behalf of the user (make authenticated requests, submit forms) but cannot steal the session token itself to log in from a different machine.
Conclusion¶
- The search bar reflected user input directly into the HTML response without encoding —
<marquee>rendered confirmed HTML injection. - Injecting
<script>alert("Kasane Teto")</script>executed JavaScript in the browser — reflected XSS confirmed. - The payload travels in the
?search=query parameter — the crafted URL is the delivery mechanism for attacking victims. document.cookiereturned empty because the session cookie has theHttpOnlyflag set — XSS execution succeeded but session token theft was prevented by the server-side cookie configuration.
Key Concepts¶
Reflected XSS occurs when user input is included in the HTTP response without encoding. The search term goes in, the script tag comes out, and the browser executes it. The "reflected" name comes from the fact that the payload is in the request and reflected back in the response — as opposed to stored XSS where the payload persists in a database.
The URL is the delivery mechanism for reflected XSS. The payload travels in the query string — an attacker sends the crafted URL to a victim via email, phishing page, or any other channel. When the victim's browser visits the URL, it sends the search term to the server, the server reflects it unencoded, and the browser executes the script in the victim's context.
HTML injection is a stepping stone to XSS. If <marquee> renders, <script> will too. Testing with a harmless HTML tag first confirms rendering behavior before escalating to script execution.
HttpOnly is a critical defence against session theft via XSS — it does not prevent XSS from executing, but it specifically prevents JavaScript from reading the protected cookie. A well-configured application marks session cookies HttpOnly so that even a successful XSS attack cannot be used to hijack sessions remotely. This limits XSS impact to actions performed within the current session context rather than full session takeover.