OAuth认证漏洞

类型

1. 授权码模式(Authorization Code)

  • 流程
    1. 用户访问第三方应用,应用将其重定向到授权服务器。
    2. 用户在授权服务器上登录并授权。
    3. 授权服务器返回授权码给应用。
    4. 应用使用授权码向授权服务器请求访问令牌。
    5. 授权服务器返回访问令牌和刷新令牌。
  • 适用场景:Web 应用和移动应用。

2. 隐式模式(Implicit)

  • 流程
    1. 用户访问第三方应用,应用将其重定向到授权服务器。
    2. 用户在授权服务器上登录并授权。
    3. 授权服务器通过 URL 片段返回访问令牌。
  • 适用场景:单页应用(SPA)等无法安全存储凭证的场景。

3. 密码模式(Resource Owner Password Credentials)

  • 流程
    1. 用户直接向第三方应用提供用户名和密码。
    2. 应用使用这些凭证向授权服务器请求访问令牌。
    3. 授权服务器返回访问令牌和刷新令牌。
  • 适用场景:高度信任的应用,如内部系统。

4. 客户端模式(Client Credentials)

  • 流程
    1. 第三方应用使用自己的客户端 ID 和密钥向授权服务器请求访问令牌。
    2. 授权服务器返回访问令牌。
  • 适用场景:应用访问自身资源或与用户无关的资源。

5. 刷新令牌模式(Refresh Token)

  • 流程
    1. 应用使用刷新令牌向授权服务器请求新的访问令牌。
    2. 授权服务器返回新的访问令牌和刷新令牌。
  • 适用场景:访问令牌过期后获取新令牌。

总结

  • 授权码模式:最常用,安全性高。
  • 隐式模式:适用于单页应用,安全性较低。
  • 密码模式:适用于高度信任的环境。
  • 客户端模式:适用于应用访问自身资源。
  • 刷新令牌模式:用于延长会话。

/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 范围(如 openidprofileemail)。
response_types_supported 支持的响应类型(如 codetokenid_token)。
subject_types_supported 支持的主体类型,为public时表明任何客户端拥有一致标识符(sub值),为pairwise时会为每个客户端生成唯一的标识符
id_token_signing_alg_values_supported 支持的 JWT 签名算法(如 RS256)。
token_endpoint_auth_methods_supported 支持的客户端认证方式(如 client_secret_basicclient_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值的作用:

  1. 唯一标识用户
  2. 跨客户端用户识别
  3. 保护用户隐私
  4. 支持单点登录(SSO)
  5. 支持用户信息查询
  6. 支持审计和日志记录
  7. 支持权限控制

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