Skip to content
Field Detail
Platform PortSwigger Web Security Academy
Type OAuth 2.0 / OpenID Connect / SSRF
Difficulty Practitioner
Objective Register a malicious OAuth client with a crafted logo_uri pointing to the AWS metadata endpoint, then trigger the provider to fetch it and leak the admin IAM secret access key

SSRF via OpenID Dynamic Client Registration

Clicking "My account" redirected through the OAuth flow. The authorization request included scope=openid — OpenID Connect is in use, not bare OAuth. OIDC adds standardized authentication on top of OAuth, and crucially, it standardizes features like dynamic client registration.

Screenshot
Screenshot

After authenticating as wiener:peter, the consent screen loaded. Something subtle in the page source:

<img src="/client/d7egmxuxwr7x6kbtst06d/logo">
Screenshot

The OAuth provider fetches and serves a client logo from a URI associated with the registered client — a server-side fetch. The normal login completed:

Screenshot

Dynamic client registration in OIDC lets applications register themselves programmatically via a /registration endpoint by POSTing their metadata as JSON. Some providers expose this without authentication — meaning an attacker can register an arbitrary client and supply attacker-controlled values for any field the provider subsequently consumes server-side, including URIs. When the provider serves the consent screen, it fetches the logo_uri from the registered client server-side to display the logo. That's a second-order SSRF primitive: register the malicious URI now, trigger the server-side fetch later by requesting the logo endpoint. The SSRF doesn't fire at registration time — it fires when the URI is consumed.

The /.well-known/openid-configuration endpoint is always the first stop with OIDC — it maps the full attack surface:

Screenshot
"registration_endpoint": "https://oauth-0afd0005043d832f8076154502d90030.oauth-server.net/reg"

Working through the error messages on POST /reg:

Screenshot

A minimal valid registration request:

POST /reg HTTP/2
Host: oauth-0afd0005043d832f8076154502d90030.oauth-server.net
Content-Type: application/json

{
    "redirect_uris": [
        "https://teto.com"
    ]
}
Screenshot

201 Created — no authentication required. The registration endpoint is completely open. Registering the malicious client with logo_uri pointing at the AWS instance metadata service, accessible from any EC2 instance's own network but not from outside:

POST /reg HTTP/2
Host: oauth-0afd0005043d832f8076154502d90030.oauth-server.net
Content-Type: application/json

{
    "redirect_uris": [
        "https://teto.com"
    ],
    "logo_uri": "http://169.254.169.254/latest/meta-data/iam/security-credentials/admin/"
}
Screenshot

New client registered with client_id: qMy3jQDUKjdFAu_nBhwSj. Requesting the logo for this client triggered the server-side fetch from the OAuth provider's internal network:

GET /client/qMy3jQDUKjdFAu_nBhwSj/logo HTTP/2
Screenshot

The response contained the IAM credentials including the secret access key. Submitting it:

Screenshot
Screenshot

With this the lab is solved

Resources