PKCE 实际上保护的是什么?

信息安全 休息 api 客户 oauth2
2021-08-18 14:51:34

我试图弄清楚 PKCE在移动应用程序中的工作原理,但有些东西我不太明白。

因此,从我可以收集到的内容中,客户端应用程序创建了一个随机的加密安全字符串,称为代码验证器。然后将其存储。然后,应用程序会由此生成代码质询。然后将代码质询与质询的生成方式(例如 S256 或纯代码)一起在 API 请求中发送到服务器。服务器将此质询与相关请求的适当授权码一起存储。

然后,当客户端尝试将代码交换为访问令牌时,它还会在请求中发送原始代码验证器。然后,服务器检索存储的质询和最初用于为该特定代码生成质询的方法,并生成等效的 s256/plain 散列并比较它们。如果它们匹配,它会返回一个访问令牌。

我不明白这应该如何替换客户端应用程序中的秘密?当然,如果您想欺骗这一点,您只需将 client_id 视为正常并生成您自己的代码验证器和挑战,并且您处于与一开始不需要 PKCE 相同的位置。如果最初的想法是它基本上是一个“动态秘密”,那么 PKCE 在这里实际上试图解决什么?我的假设是只有当有人碰巧在“听”auth_code返回时才存在,但是如果您再次使用 SSL,是否需要这样做?它被称为取代了您不应该在公共应用程序中存储秘密的事实,但客户端负责生成而不是服务器的事实感觉它实际上并没有帮助。

2个回答

PKCE 很重要的原因是,在移动操作系统上,操作系统允许应用程序注册以处理重定向 URI,因此恶意应用程序可以使用合法应用程序的授权代码注册和接收重定向。这称为授权码拦截攻击。

授权码拦截攻击

WSO2 在此处对此进行了描述:

由于可以将多个应用程序注册为特定重定向 URI 的处理程序,因此该流程的漏洞在于,恶意客户端也可以将自己注册为合法应用程序处理的相同 URI 方案的处理程序。如果发生这种情况,操作系统可能会将 URI 解析给恶意客户端。这种攻击的流程如下图所示。

在某些操作系统(如 Android)中,在流程的第 5 步中,会提示用户选择应用程序来处理重定向 URI,然后再使用“完成操作使用”活动对其进行解析。这可以避免恶意应用程序对其进行处理,因为用户可以识别并选择合法应用程序。但是,某些操作系统(例如 iOS)没有任何此类方案。

为了更好地理解这一点,这里有一个来自 OpenID 的图表和讨论。您可以看到移动系统浏览器有责任接收重定向 URI 并将其路由到正确的应用程序。

原生应用重定向 URI 路由

但是,由于移动操作系统可以允许许多应用程序注册相同的重定向 URI,因此恶意应用程序可以注册并接收合法的授权代码,如下图所示,也是 WSO2:

PKCE 恶意应用

PKCE 攻击缓解

PKCE 通过要求在发起 OAuth 2.0 请求(请求身份验证代码)的应用和将身份验证代码交换为令牌的应用之间共享知识来缓解这一问题。在 Auth Code Interception Attack 的情况下,恶意应用程序没有验证者来完成令牌交换。

Okta关于这个主题的这篇文章很好地解释了这一点,恕我直言。

我相信这是因为 PKCE 旨在用于本机应用程序(例如 Android、iOS、UWP、Electron 等),您可以在其中离开应用程序的安全上下文并转到浏览器进行身份验证,并依赖从安全返回到您的应用程序浏览器。您不一定在重定向回您的应用程序时使用 TLS(在自定义方案的情况下,您依赖操作系统将响应带回您的应用程序),因此如果您的授权代码出现恶意,接收如果没有动态密钥,应用程序将无法获取访问令牌。

公共客户端上的动态密钥的优点在这里很明显 - PKCE 的假设是不难拦截浏览器对应用程序的响应。