OAuth认证漏洞
OAuth认证漏洞
类型
1. 授权码模式(Authorization Code)
- 流程:
- 用户访问第三方应用,应用将其重定向到授权服务器。
- 用户在授权服务器上登录并授权。
- 授权服务器返回授权码给应用。
- 应用使用授权码向授权服务器请求访问令牌。
- 授权服务器返回访问令牌和刷新令牌。
- 适用场景:Web 应用和移动应用。
2. 隐式模式(Implicit)
- 流程:
- 用户访问第三方应用,应用将其重定向到授权服务器。
- 用户在授权服务器上登录并授权。
- 授权服务器通过 URL 片段返回访问令牌。
- 适用场景:单页应用(SPA)等无法安全存储凭证的场景。
3. 密码模式(Resource Owner Password Credentials)
- 流程:
- 用户直接向第三方应用提供用户名和密码。
- 应用使用这些凭证向授权服务器请求访问令牌。
- 授权服务器返回访问令牌和刷新令牌。
- 适用场景:高度信任的应用,如内部系统。
4. 客户端模式(Client Credentials)
- 流程:
- 第三方应用使用自己的客户端 ID 和密钥向授权服务器请求访问令牌。
- 授权服务器返回访问令牌。
- 适用场景:应用访问自身资源或与用户无关的资源。
5. 刷新令牌模式(Refresh Token)
- 流程:
- 应用使用刷新令牌向授权服务器请求新的访问令牌。
- 授权服务器返回新的访问令牌和刷新令牌。
- 适用场景:访问令牌过期后获取新令牌。
总结
- 授权码模式:最常用,安全性高。
- 隐式模式:适用于单页应用,安全性较低。
- 密码模式:适用于高度信任的环境。
- 客户端模式:适用于应用访问自身资源。
- 刷新令牌模式:用于延长会话。
/reg返回字段解析
返回的字段可以在请求的时候进行修改,比如:
POST /reg HTTP/2
Host: oauth-0a3000d50423f4cd819e3c8c020b0037.oauth-server.net
Content-Type: application/json
Content-Length: 194
{
"redirect_uris" : [
"https://www.baidu.com"
],
"policy_uri":"http://www.baidu.com"
}
以下是返回字段的相关内容:
客户端注册响应字段
| 字段名称 | 作用 | 值类型/示例 |
|---|---|---|
application_type |
指定客户端的类型。 | web(Web 应用),native(原生应用) |
grant_types |
指定客户端支持的授权类型。 | ["authorization_code", "refresh_token"] |
id_token_signed_response_alg |
指定 ID Token 的签名算法。 | RS256(RSA-SHA256),HS256(HMAC-SHA256) |
post_logout_redirect_uris |
指定用户注销后重定向的 URI 列表。 | ["https://example.com/logout"] |
require_auth_time |
指定是否需要在 ID Token 中包含用户最后一次认证的时间。 | true(包含),false(不包含) |
response_types |
指定客户端支持的响应类型。 | ["code"](授权码),["token", "id_token"](访问令牌和 ID Token) |
subject_type |
指定用户标识符的类型。 | public(全局唯一),pairwise(针对每个客户端生成不同的标识符) |
token_endpoint_auth_method |
指定客户端在令牌端点使用的认证方法。 | client_secret_basic(HTTP Basic 认证),client_secret_post(POST 参数认证) |
introspection_endpoint_auth_method |
指定客户端在令牌验证端点使用的认证方法。 | 同 token_endpoint_auth_method |
revocation_endpoint_auth_method |
指定客户端在令牌撤销端点使用的认证方法。 | 同 token_endpoint_auth_method |
require_signed_request_object |
指定是否需要对请求对象进行签名。 | true(需要签名),false(不需要签名) |
request_uris |
指定客户端支持的请求对象 URI 列表。 | ["https://example.com/request"] |
client_id_issued_at |
指定客户端 ID 的颁发时间(Unix 时间戳)。 | 1741177051 |
client_id |
客户端的唯一标识符。 | "5gqLG7dp0ImHHyuQOtKYm" |
client_secret_expires_at |
指定客户端密钥的过期时间(Unix 时间戳)。 | 0(永不过期),1741177051(过期时间戳) |
client_secret |
客户端的密钥,用于认证。 | "rmCzXjRtf1x4AlnftTKaYq4T7lBYGcxdoo4tAGaEXISRR4fWeKGfvLwZRZ7z7aBHalPiLAupi1ruXFg4pTpKig" |
logo_uri |
指定客户端的 Logo 图标 URI。 | "http://169.254.169.254/latest/meta-data/iam/security-credentials/admin/" |
redirect_uris |
指定客户端允许的重定向 URI 列表。 | ["https://www.baidu.com"] |
registration_client_uri |
指定客户端注册信息的 URI。 | "https://oauth-0a3000d50423f4cd819e3c8c020b0037.oauth-server.net/reg/5gqLG7dp0ImHHyuQOtKYm" |
registration_access_token |
用于访问客户端注册信息的访问令牌。 | "d6RUIcVuwZz19wvv6ponzoSBs8xaPPiD0o84-eOIozY" |
contacts |
指定客户端的联系人信息(如电子邮件)。 | ["admin@example.com"] |
policy_uri |
指定客户端的隐私政策 URI。 | "https://example.com/policy" |
tos_uri |
指定客户端的服务条款 URI。 | "https://example.com/tos" |
jwks_uri |
指定客户端的 JSON Web Key Set (JWKS) URI。 | "https://example.com/jwks" |
sector_identifier_uri |
指定客户端的 Sector Identifier URI(用于 pairwise Subject Type)。 |
"https://example.com/sector" |
default_max_age |
指定默认的最大认证年龄(秒)。 | 3600 |
default_acr_values |
指定默认的认证上下文类引用(ACR)值。 | ["urn:mace:incommon:iap:silver"] |
initiate_login_uri |
指定客户端的登录初始化 URI。 | "https://example.com/login" |
backchannel_logout_uri |
指定客户端的后台注销 URI。 | "https://example.com/backchannel_logout" |
backchannel_logout_session_required |
指定是否需要会话支持后台注销。 | true(需要),false(不需要) |
额外信息获取
知道提供OAuth2服务的服务主机后,可以通过向该主机的以下路径发送get请求来获取一些额外的信息
/.well-known/oauth-authorization-server
/.well-known/openid-configuration
关键字段说明
| 字段名称 | 说明 |
|---|---|
issuer |
OIDC 服务的唯一标识符(通常是 URL)。 |
authorization_endpoint |
授权端点,用于获取授权码。 |
token_endpoint |
令牌端点,用于交换访问令牌和刷新令牌。 |
userinfo_endpoint |
用户信息端点,用于获取用户的基本信息。 |
jwks_uri |
JWKS(JSON Web Key Set)端点,用于获取公钥以验证 JWT 签名。 |
scopes_supported |
支持的 OIDC 范围(如 openid、profile、email)。 |
response_types_supported |
支持的响应类型(如 code、token、id_token)。 |
subject_types_supported |
支持的主体类型,为public时表明任何客户端拥有一致标识符(sub值),为pairwise时会为每个客户端生成唯一的标识符 |
id_token_signing_alg_values_supported |
支持的 JWT 签名算法(如 RS256)。 |
token_endpoint_auth_methods_supported |
支持的客户端认证方式(如 client_secret_basic、client_secret_post)。 |
scopes_supported |
表明服务器支持的权限范围,在客户端发起授权请求时携带这些scope(email、address等)就可以放回对应的信息 |
以下是一些常见的 Scopes 及其含义:
| Scope 名称 | 说明 |
|---|---|
openid |
必需 Scope,用于请求 ID Token,表示使用 OpenID Connect 协议。 |
profile |
请求访问用户的基本信息(如姓名、头像、性别等)。 |
email |
请求访问用户的电子邮件地址。 |
address |
请求访问用户的地址信息。 |
phone |
请求访问用户的电话号码。 |
offline_access |
请求刷新令牌(Refresh Token),用于长期访问用户资源。 |
api |
自定义 Scope,用于访问特定的 API 资源。 |
sub值的作用:
- 唯一标识用户。
- 跨客户端用户识别。
- 保护用户隐私。
- 支持单点登录(SSO)。
- 支持用户信息查询。
- 支持审计和日志记录。
- 支持权限控制。
SRC挖掘
漏洞思路:
-
检查认证凭据是否只适用于一个用户,在包含认证凭据的请求包中,通常会存在一些标识用户身份的东西,如userid、username或是email等,通过修改为其他用户的相关信息来尝试能否通过OAuth2认证
-
注册端点(registration_endpoint)检查
-
SSRF可能:如果OAuth服务器允许用户注册自己的客户端程序,那就可以尝试向目标OAuth2服务器发以下包:
POST /reg HTTP/2 Host: oauth-0a4e00100466c5338085c4af02a50010.oauth-server.net Content-Type: application/json Content-Length: 156 { "redirect_uris" : [ "https://www.baidu.com" ], "logo_uri":"http://169.254.169.254/latest/meta-data/iam/security-credentials/admin/" }通过注册时生成的client_id能够间接调用logo_url,即请求–》OAuth2服务器–》请求logo_uri,最终响应返回给最初的请求,这个logo_uri是OAuth服务器本来就有的key,这意味这尝试OAuth服务器的一些可以修改的key可能会造成更多的一些漏洞,这和实际场景相关
-
-
CSRF检查:抓取所有携带认证凭据如授权码code的请求包,如果在请求中没有携带csrf-token,就存在被csrf攻击的可能性,保留这些包,然后根据实际的业务场景去评估CSRF攻击的影响
-
重定向外带检查:找到OAuth的重定向请求,替换域名,检查是否会在响应包的location中携带敏感的信息如授权码code