本系列文之後也会置於个人网站
+-------------------+
| Authz Server |
+--------+ | +---------------+ |
| |--(A)- Authorization Request ---->| | |
| | + t(code_verifier), t_m | | Authorization | |
| | | | Endpoint | |
| |<-(B)---- Authorization Code -----| | |
| | | +---------------+ |
| Client | | |
| | | +---------------+ |
| |--(C)-- Access Token Request ---->| | |
| | + code_verifier | | Token | |
| | | | Endpoint | |
| |<-(D)------ Access Token ---------| | |
+--------+ | +---------------+ |
+-------------------+
Figure 2: Abstract Protocol Flow
说穿了PKCE是基於Code flow的安全强化版。在整个过程前後添加了两个动作--产生code_verifier
和code_challenge
,并在最後透过code_challenge
验证code_verifier
。其目的有很大程度是为了建立前端通讯与後端通讯的关联。
那麽先来看看原本发生了什麽问题。
首先,已经知道Code Flow的整个流程是:
code
。code
转交给授权的客户端。code
,像授权服务器换取access_token
。可以看到code
可能透过网路传递了多次,资源拥有者代理与授权服务器之间、资源拥有者代理与客户端之间、客户端与授权服务器之间。传递多次同时意味这泄漏的风险提高,也就有可能有恶意中间层取得存取权杖。
就算不是截取到code
,了解攻击手法的,同样有可能不小心就猜测到code
,进行攻击。说真的这种情况还真的很难防范,防不胜防。爲了降低被攻击的机会,最好在添加一些秘密,使攻击难度提升。当然配合使用 Client Credentials Flow 或许是一个办法,毕竟按照设计client_secret
只会由客户端拥有,并只在客户端与授权服务器之间流通。但这只证明了客户端是已经被认可的客户端,尚未证明资源拥有者授权的客户端与使用code
换取存取权杖的爲同一个。
这就像是任何人都可以声称自己是被授权的「那个人」。
难道授权服务器要等个400多年吗?还是随便一个人说自己是「那个人」也就认可了呢?怎麽想都不太对吧!
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
| End Device (e.g., Smartphone) |
| |
| +-------------+ +----------+ | (6) Access Token +----------+
| |Legitimate | | Malicious|<--------------------| |
| |OAuth 2.0 App| | App |-------------------->| |
| +-------------+ +----------+ | (5) Authorization | |
| | ^ ^ | Grant | |
| | \ | | | |
| | \ (4) | | | |
| (1) | \ Authz| | | |
| Authz| \ Code | | | Authz |
| Request| \ | | | Server |
| | \ | | | |
| | \ | | | |
| v \ | | | |
| +----------------------------+ | | |
| | | | (3) Authz Code | |
| | Operating System/ |<--------------------| |
| | Browser |-------------------->| |
| | | | (2) Authz Request | |
| +----------------------------+ | +----------+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
Figure 1: Authorization Code Interception Attack
A number of pre-conditions need to hold for this attack to work:
1. The attacker manages to register a malicious application on the
client device and registers a custom URI scheme that is also used
by another application. The operating systems must allow a custom
URI scheme to be registered by multiple applications.
2. The OAuth 2.0 authorization code grant is used.
3. The attacker has access to the OAuth 2.0 [RFC6749] "client_id" and
"client_secret" (if provisioned). All OAuth 2.0 native app
client-instances use the same "client_id". Secrets provisioned in
client binary applications cannot be considered confidential.
4. Either one of the following condition is met:
4a. The attacker (via the installed application) is able to
observe only the responses from the authorization endpoint.
When "code_challenge_method" value is "plain", only this
attack is mitigated.
那麽如何做才能够在前端通讯与後端通讯建立更爲明确的关联了?客户端必须有某种方式能攻证明授权的是自己。
code
。并与授权服务器约定好,在未来又一个人会带着这个code
,并使用一个能证明自己就是「那个人」的方法来找你。code
交给客户端。code
访问授权服务器。这边我不打算详细说明客户端如何证明身份。从概念上来说,就是有一个难题,这个难题的答案只有自己知道。要从难题推出答案很难,但是从难题证明答案正确很容易。
换个比喻就是:
而这里使用到的难题就是单向杂凑函数(One-Way Hash Function)。如同其名,这个函数功能要透过一个方向运算非常简单,但是反过来却非常困难。
实际上产生过程在OAuth 2.0 Playground已经看过了:
产生出的code_challenge
和已知的演算法(单向杂凑函数,这里是SHA256)组成难题。只要能够提出正确的code_verifier
就能够证明客户端(出题人)。
这次同样已Code模式爲基础,透过PKCE来强化安全性。
同样登入。但在登入时,将code_challege
与演算法组成的难题告诉授权服务器。
最後在後端通讯时,将答案告诉授权服务器:
如果验证失败就不会通过授权,并且code
可能也已经被泄漏,也不再可用。如果都通过,就能够正常取得存取权杖。
code_verifity
和code_challenge
要产生并没有那麽困难,code_verifity
只是乱数字串而已。然後透过一定演算法就可以得到code_challenge
code_verifity
和code_challenge
同样的验证也就没有那麽困难。授权服务器先後得到:
code_challenge
和验证使用的方法code_verifity
现在姑且叫第一个叫做c1
,第二个叫做v
,验证使用的方叫做m
。透过m
和v
可以得到c2
,只要c1
和c2
一致就是通过验证。下面可以用Python程序码简单验证一下:
from base64 import urlsafe_b64encode
from hashlib import sha256
def gen_challege(vertify_str):
return urlsafe_b64encode(sha256(vertify_str).digest())
####################
c1 = b'24OdicZTLu8T9kV3Pf1ZaPr8iJAGwaQJ0dvTQy5SSf0'
m = gen_challege
####################
v = b'xgoALuaqJPR4bK2wgNUSEBwKrxy6ljufTU7k4DRw7SA7NcqjLLqJXX4bI0091bbK'
####################
c2 = m(v)
c2 = c2.decode().rstrip('=').encode()
c1 == c2 # True
<<: Day19-JavaScript(JS)与TypeScript(TS)的函式(Function) Part1
前言 前面几篇写了一些有趣没什麽人讨论的攻击手法,中场休息偷懒一下 之前在PTT上看到有人讨论OSC...
传值与传址,但C++是一个特别的语言比C语言更复杂真要细分可分成3类(传值,传址,传参考),同时指标...
这个得上一篇-https://ithelp.ithome.com.tw/articles/10283...
在谈论V8引擎时,我们得先了解什麽是 JavaScript 引擎。 JavaScript Engin...
再来说说templates 先修改在noob1 中的setting.py,找到TEMPLATES,修...