模式|OAuth 2.0 扩展协议之 PKCE( 二 )


授权码拦截攻击

模式|OAuth 2.0 扩展协议之 PKCE
文章图片

上面是OAuth 2.0授权码模式的完整流程 , 授权码拦截攻击就是图中的C步骤发生的 , 也就是授权服务器返回给客户端授权码的时候 , 这么多步骤中为什么C步骤是不安全的呢? 在OAuth 2.0核心规范中 , 要求授权服务器的anthorize endpoint和token endpoint必须使用TLS(安全传输层协议)保护 , 但是授权服务器携带授权码code返回到客户端的回调地址时 , 有可能不受TLS 的保护 , 恶意程序就可以在这个过程中拦截授权码code , 拿到 code 之后 , 接下来就是通过code向授权服务器换取访问令牌access_token , 对于机密的客户端来说 , 请求access_token时需要携带客户端的密钥 client_secret , 而密钥保存在后端服务器上 , 所以恶意程序通过拦截拿到授权码code 也没有用 , 而对于公开的客户端(手机App , 桌面应用)来说 , 本身没有能力保护 client_secret , 因为可以通过反编译等手段 , 拿到客户端client_secret , 也就可以通过授权码code换取access_token , 到这一步 , 恶意应用就可以拿着token请求资源服务器了 。
state参数 , 在OAuth 2.0核心协议中 , 通过code换取token步骤中 , 推荐使用state参数 , 把请求和响应关联起来 , 可以防止跨站点请求伪造-CSRF攻击 , 但是state并不能防止上面的授权码拦截攻击 , 因为请求和响应并没有被伪造 , 而是响应的授权码被恶意程序拦截 。
PKCE 协议流程

模式|OAuth 2.0 扩展协议之 PKCE
文章图片

PKCE协议本身是对OAuth 2.0的扩展 , 它和之前的授权码流程大体上是一致的 , 区别在于 , 在向授权服务器的authorize endpoint请求时 , 需要额外的code_challenge和code_challenge_method参数 , 向token endpoint请求时 , 需要额外的code_verifier参数 , 最后授权服务器会对这三个参数进行对比验证 , 通过后颁发令牌 。
code_verifier
对于每一个OAuth授权请求 , 客户端会先创建一个代码验证器code_verifier , 这是一个高熵加密的随机字符串 , 使用URI非保留字符 (Unreserved characters) , 范围[A-Z] / [a-z] / [0-9] / "-" / "." / "_" / "~" , 因为非保留字符在传递时不需要进行URL 编码 , 并且 code_verifier 的长度最小是43 , 最大是128 , code_verifier要具有足够的熵它是难以猜测的 。
code_verifier的扩充巴科斯范式 (ABNF) 如下:

code-verifier= 43* 128unreservedunreserved= ALPHA / DIGIT / "-"/ "."/ "_"/ "~" ALPHA= %x41- 5A / %x61- 7ADIGIT= %x30- 39 简单点说就是在[A-Z] / [a-z] / [0-9] / "-" / "." / "_" / "~"范围内 , 生成43-128位的随机字符串 。

推荐阅读