关于Django OAuth Toolkit启用通配符redirect_uri及绕过验证的问询
Django OAuth Toolkit漏洞演示适配方案
1. 启用通配符Redirect URI
Django OAuth Toolkit默认不支持通配符URI,但可以通过重写验证逻辑实现:
- 自定义客户端模型的redirect_uri验证方法:
继承默认的Application模型,重写redirect_uri_allowed方法,添加通配符匹配逻辑:
之后在settings.py中指定自定义模型:from django.db import models from oauth2_provider.models import AbstractApplication import re class CustomApplication(AbstractApplication): def redirect_uri_allowed(self, uri): # 允许客户端配置的redirect_uri使用通配符,比如"*.abc.com" allowed_uris = self.redirect_uri.split() for allowed_uri in allowed_uris: # 将通配符转为正则表达式 pattern = re.escape(allowed_uri).replace(r'\*', r'.*') if re.fullmatch(pattern, uri): return True return super().redirect_uri_allowed(uri)
这样客户端配置OAUTH2_PROVIDER = { 'APPLICATION_MODEL': 'yourapp.CustomApplication', }*.abc.com作为redirect_uri时,攻击者篡改的evil.abc.com或其他子域就能通过验证。
2. 绕过令牌生成时的Redirect URI验证
要让攻击者拿到授权码后能换令牌,需要修改授权码与redirect_uri的绑定逻辑:
- 重写授权码授予类:
继承AuthorizationCodeGrant,修改create_authorization_code不存储redirect_uri,或者修改validate_redirect_uri跳过检查:
然后在settings.py中替换默认的授权类型:from oauth2_provider.oauth2_grants import AuthorizationCodeGrant from oauth2_provider.models import get_application_model class VulnerableAuthorizationCodeGrant(AuthorizationCodeGrant): def create_authorization_code(self, client, user, request, *args, **kwargs): # 生成授权码时不绑定redirect_uri code = super().create_authorization_code(client, user, request, *args, **kwargs) # 清空存储的redirect_uri code.redirect_uri = "" code.save() return code def validate_redirect_uri(self, client, redirect_uri): # 跳过redirect_uri验证 return True
这样攻击者用任意redirect_uri拿到的授权码,都能成功换取访问令牌。OAUTH2_PROVIDER = { 'GRANT_TYPES': { 'authorization_code': 'yourapp.path.to.VulnerableAuthorizationCodeGrant', }, }
3. 关于RFC规范的说明
Django OAuth Toolkit将授权码与redirect_uri绑定存储并验证的做法完全符合OAuth 2.0 RFC 6749规范。RFC 6749的4.1.3节明确要求:当客户端请求令牌时,必须提供与获取授权码时相同的redirect_uri,授权服务器必须验证两者一致。这是为了防止授权码被劫持后,攻击者将其用于其他恶意URI,属于OAuth 2.0的核心安全机制之一。
内容的提问来源于stack exchange,提问作者Johnny
相关产品推荐
相关产品推荐

