標題:OAuth 2.0協議及漏洞

taibeihacker

Moderator

OAuth 2.0协议及漏洞​

1 OAuth 2.0 协议简介​

OAuth 2.0 是一種授權機制,常用來授權第三方應用登錄。數據的所有者告訴系統,同意授權第三方應用獲取用戶的數據。系統從而產生一個短期的進入令牌(token),用來代替密碼,供第三方應用使用。
通俗的講,很多網站登錄時,允許使用第三方網站的身份登錄,其本質就是通過OAuth 協議進行授權。

1.1 OAuth 协议中的角色​

Third-party application:第三方應用程序,通常又被稱為“客戶端”(client)。
HTTP service:HTTP 服務提供商,通常又稱為“服務提供商”。
Resource Owner:資源所有者,通常又稱為“用戶”(user)。
User Agent:用戶代理,通常就是指瀏覽器。
Authorization server:認證服務器,即服務提供商專門用來處理認證的服務器。
Resource server:資源服務器,即服務提供商存放用戶生成的資源的服務器。它與認證服務器,可以是同一台服務器,也可以是不同的服務器。

1.2 OAuth 协议的认证流程​

OAuth 2.0 的運行流程如下圖:
202305041945699.png-water_print

用戶打開客戶端以後,客戶端要求用戶給予授權。
用戶同意給予客戶端授權。
客戶端使用上一步獲得的授權,向認證服務器申請令牌。
認證服務器對客戶端進行認證以後,確認無誤,同意發放令牌。
客戶端使用令牌,向資源服務器申請獲取資源。
資源服務器確認令牌無誤,同意向客戶端開放資源。

1.3 OAuth 2.0 四种授权方式​

1.3.1 authorization code - 授权码模式​

授權碼方式指的是三方應用需要先申請授權碼,然後再用該授權碼獲取訪問系統的令牌。
下面是該授權方式的流程圖,以第三方網站使用Github 賬號登錄為例:
202305042003493.png-water_print

Step1:第三方網站提供一個鏈接,用戶點擊後就會跳轉到Github,授權用戶數據給第三方網站使用。下面就是第三方網站跳轉Github 的一個示意鏈接。
1
2
3
4
5
response_type=code
client_id=CLIENT_ID
redirect_uri=CALLBACK_URL
scope=read
response_type 參數表示要求以授權碼code形式返回結果,client_id 參數讓github.com 知道是誰在請求,redirect_uri參數是Github 接受或拒絕請求後的跳轉網址,scope參數表示要求的授權範圍(這裡是只讀)。
Step2:用戶跳轉後,Github 會要求用戶登錄,然後詢問是否同意給予第三方網站授權。用戶表示同意,這時Github 就會按照redirect_uri參數指定的網址進行跳轉,並傳回一個授權碼:
1
Step3:第三方網站拿到授權碼以後,向Github 網站請求令牌。
1
2
3
4
5
6
client_id=CLIENT_ID
client_secret=CLIENT_SECRET
grant_type=authorization_code
code=AUTHORIZATION_CODE
redirect_uri=CALLBACK_URL
client_id參數和client_secret參數用來讓Github 確認A 的身份; client_secret 參數是保密的,因此只能在後端發請求),grant_type 參數的值是AUTHORIZATION_CODE,表示採用的授權方式是授權碼,code 參數是Step2 拿到的授權碼,redirect_uri 參數是令牌頒發後的回調網址。
Step4:Github 收到請求以後向第三方網站頒發令牌。即:向redirect_uri 指定的網址發送一段數據,如:
1
2
3
4
5
6
7
8
9
{
'access_token':'ACCESS_TOKEN',
'token_type':'bearer',
'expires_in':2592000,
'refresh_token':'REFRESH_TOKEN',
'scope':'read',
'uid':100101,
'info': '.'
}
後續第三方網站就可以帶著這個Token 獲取請求用戶資源了。

1.3.2 implicit - 隐藏式​

這種模式允許直接向前端頒發令牌,這種方式簡化了獲取授權碼的中間步驟。
202305042016880.png-water_print

Step1:第三方網站提供一個鏈接,要求用戶跳轉到Github 網站,授權用戶數據給第三方網站使用。
1
2
3
4
5
response_type=token
client_id=CLIENT_ID
redirect_uri=CALLBACK_URL
scope=read
Step2:用戶跳轉到Github,登錄後同意給予第三方網站授權。這時,Github 網站就會跳回redirect_uri 參數指定的跳轉網址,並且把令牌作為URL 參數,傳給第三方網站。
1
token參數就是令牌,第三方可以直接在前端拿到令牌。
令牌的位置保存在URL 錨點中,因為OAuth 2.0 允許跳轉網址使用HTTP 協議,因此存在“中間人攻擊”的風險,而瀏覽器跳轉時,錨點不會發到服務端,這樣就可以減少令牌洩漏的風險。

1.3.3 password - 密码式​

如果某個應用處在相對信任的環境,RFC 6749 也允許用戶把用戶名和密碼直接傳遞給該應用。該應用通過使用用戶的密碼申請令牌。
202305042022385.png-water_print

Step 1:第三方網站要求用戶提供Github 網站的用戶名和密碼。第三方網站拿到憑據後,直接向Github 請求令牌。
1
2
3
4
5
grant_type=password
username=USERNAME
password=PASSWORD
client_id=CLIENT_ID
Step 2:Github 驗證身份通過後,直接給出令牌。這種情況下不需要redirect 跳轉,而是把令牌放在JSON 數據裡面,作為HTTP 回應,A 因此拿到令牌。

1.3.4 client credentials - 凭证式​

這種方式適用於沒有前端的命令行應用,即在命令行下請求令牌。
Step 1:第三方在命令行向Github 發出請求。
1
2
3
4
grant_type=client_credentials
client_id=CLIENT_ID
client_secret=CLIENT_SECRET
Step 2:Github 驗證通過以後,直接返回令牌。
這種方式給出的令牌,是針對第三方應用的,而不是針對用戶個人的,因此存在多個用戶共享同一個令牌的可能性。

1.4 令牌的使用​

第三方網站拿到令牌以後,就可以向Github 的API 請求數據了。
此時,每個發到API 的請求,都必須帶有令牌。具體做法是在請求的頭信息,加上一個Authorization字段,令牌就放在這個字段裡面。
1
2
curl -H 'Authorization: Bearer ACCESS_TOKEN' \
'https://github.com'

2 OAuth2.0 认证漏洞​

2.1 OAuth 客户端应用程序的漏洞​

2.1.1 Authentication bypass via OAuth implicit flow​

靶場地址:https://portswigger.net/web-security/oauth/lab-oauth-authentication-bypass-via-oauth-implicit-flow
前面的章節中描述過隱式授權常用於直接向前端頒發令牌。在這個流程中,訪問令牌是通過用戶的瀏覽器以URL 參數的形式從OAuth 服務發送到客戶端應用程序的。然後,客戶端應用程序使用JavaScript 訪問該令牌。問題是,如果應用程序想在用戶關閉頁面後保持會話,它需要在某個地方存儲當前的用戶數據。
為了解決這個問題,客戶端應用程序通常會在一個POST 請求中把這些數據提交給服務器,然後給用戶分配一個會話cookie。這個請求類比基於密碼驗證的表單提交請求。然而,在這種情況下,服務器沒有對token 與用戶id 進行比較與鑑別,因此存在風險。
靶場中相關的數據包如下:
202305051428042.png-water_print

首先攜帶client_id 訪問auth 路由向認證服務端請求授權:
202305051429450.png-water_print

之後重定向url, 然後輸入了賬號密碼進行認證:
202305051431946.png-water_print

獲取access_token:
202305051432393.png-water_print

/oauth-callback 路由下獲取到Ajax 的請求信息:
202305051434119.png-water_print

首先會請求/me 去驗證訪問權限,再向/authenticate 路由發送對應信息,獲取持久化Cookie:
202305051437364.png-water_print

將email 修改為:[email protected],即可實現越權:
202305051445956.png-water_print

202305051446964.png-water_print

2.1.2 Flawed CSRF protection​

這個漏洞的主要成因是錯誤配置OAuth 組件,比如說state 參數的配置,這個參數一般都是與會話信息相關聯的一個hash 值,在服務端和客戶端之間來回傳遞,作為客戶端的CSRF令牌。
靶場地址:https://portswigger.net/web-security/oauth/lab-oauth-forced-oauth-profile-linking
首先使用wiener:peter 賬號登錄,點擊Attach a social profile:
202305051459074.png-water_print

redirect_uri中將授權代碼發送到了/oauth-linking路由中,特別的是,這裡並沒有state 參數的存在,存在有CSRF 漏洞
202305051502071.png-water_print

重新生成一個有效code:
202305051507656.png-water_print

構造csrf 請求:
202305051511441.png-water_print

重新使用社交媒體賬號登錄,獲取admin 權限,即實現用攻擊者的社交媒體賬號綁定管理員的網站賬號:
202305051511028.png-water_print

2.2 缺少授权码和访问令牌​

根據RFC 文檔,獲取到的token 將被發送到授權請求的redirect_uri 參數中的位置,如果服務端沒有正確的校驗這個URI,攻擊者就能夠通過這個漏洞將客戶端的codes 和token 發送到攻擊者控制的redirect_uri 參數指定位置。那麼攻擊者就可以利用這些信息發送到服務端合法的redirect_uri 地址中,就能成功獲取用戶的賬戶的訪問權限。

2.2.1 Flawed redirect_uri validation​

靶場地址:https://portswigger.net/web-security/oauth/lab-oauth-account-hijacking-via-redirect-uri
第一次登錄:
202305051525935.png-water_print

退出後重新登錄:
202305051531546.png-water_print

修改redirect_uri:https://exploit-0ad8005303814d4180b43e2501ed0024.exploit-server.net/exploit
構造CSRF 請求Payload:iframe src='https://oauth-0a8500b803764d57807c3...e_type=codescope=openid profile email'/iframe
在日誌中獲取管理員token:
202305051535342.png-water_print

利用管理員token 進行登錄:
202305051536846.png-water_print

2.2.2 Flawed redirect_uri validation​

有些OAuth 服務或對redirect_uri 參數開啟白名單校驗,如果校驗規則存在問題,同樣可以繞過,比如:
繞過字符串匹配:
https://default-host.com @foo.evil-user.net#@bar.evil-user.net/
提交重複的redirect_uri 參數檢測是否存在服務端參數污染漏洞:

2.2.3 Stealing OAuth access tokens via an open redirect​

靶場地址:https://portswigger.net/web-securit...ling-oauth-access-tokens-via-an-open-redirect
在這個環境中,redirect_uri 不能傳遞到外部域當中,嘗試獲取新的繞過方式。
202305051601876.png-water_print

尋找網站自身URL 重定向漏洞,其中path 參數可以任意指定,並任意跳轉:
202305051558625.png-water_print

重新修改redirect_uri,繞過限制:
202305051604731.png-water_print

提交payload:
202305051619680.png-water_print

查看日誌,獲取code:
202305051618834.png-water_print

獲取admin api key:
 
返回
上方