组合漏洞导致的账号劫持

在最近参与的一次对站点A的众测中,我发现A可以使用QQ账号进行登陆。在过去的几个月里,我发现了大量关于OAuth登陆劫持的漏洞,如果你有兴趣,可以参考:OAuth回调参数漏洞案例解析

尽管我相信目标A已经不存在OAuth登陆劫持漏洞(因为QQ已经在redirect_uri参数上做了强校验),但是我仍打算对它的登陆流程一探究竟。

下面,我以A.com代表目标A的域名来展示我是怎样发现一个账号劫持漏洞的。

打开A的QQ登陆链接后,我发现了一些奇妙的事。

image

如上图,redirect_uri并没有指向A.com,而是指向了B.com。将参数URL解码,

image

不难推测,这里涉及到2次跨域登陆:

  1. redirect_uri: qq.com => B.com
  2. s_url: B.com => A.com

在开头已经说过,QQ已经对redirect_uri参数做了强校验,要想劫持到B.com的登陆账号已经不太可能。所以,我的目标放在了s_url这个参数上。

简单分析一下登陆流程就能发现s_url是如何工作的。

(a) 首先,用户使用QQ账号登陆到B.com;

(b) 然后B.com发送如下请求,获取token,并引导用户携带token跳转到A.com;

image

(c) A.com验证token是合法的,则种下cookie。

image

至此,用户成功登陆到A.com。

从整个登陆流程来看,只要我们能想办法窃取到token,就能劫持用户的登陆账号。

unsafe URL redirect

我的目标是窃取到token,最直接的办法当然是修改参数s_url,让用户携带token跳转到恶意域名,从而泄露token。

image

一番测试后,我发现s_url的校验也很严格,即使在路径后面附加一些字符,生成的跳转链接中都不会携带token。

image

经过一些fuzz后,我发现我似乎能在最后一个字符后面附加一些符号。

image

我可以在s_url的结尾附加3种符号,而不影响token的生成,分别是:

%3f => ?
%20 => 空格
%23 => #

#让我眼前一亮,众所周知,URL中的#将被浏览器视作锚点,其后的数据不会发送到服务器。

1539588381753.png
image

当用户跳转到这个地址,自然会无法认证成功,并停留在Login页面。

image

此时token也将出现在URL中。

image

至此,我们已经在窃取token的道路上迈出了重要的一步。


为您推荐了相关的技术文章:

  1. Struts2 历史 RCE 漏洞回顾不完全系列
  2. Oauth协议介绍与安全隐患
  3. scikit-learn随机森林调参小结
  4. 记一次ThinkPHP源码审计
  5. CVE-2017-6920:Drupal远程代码执行漏洞分析及POC构造

原文链接: xz.aliyun.com