前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >挖洞经验 | 利用开放重定向漏洞劫持GitHub Gist账户

挖洞经验 | 利用开放重定向漏洞劫持GitHub Gist账户

作者头像
FB客服
修改2023-09-23 20:04:49
6500
修改2023-09-23 20:04:49
举报
文章被收录于专栏:FreeBufFreeBuf
近期,我针对GitHub做了一些安全测试,特别对其不同的CSRF token进行了绕过测试,在此过程中,我顺带研究了urls生成的各种方法函数,希望从中发现用来创建token的相关方法,最后发现了其中的一个开放重定向漏洞,利用该漏洞可以成功劫持GitHub Gist账户。漏洞收获了$10,000的奖励。

漏洞发现

在我测试的urls生成方法中,有一个名为url_for的方法,它通常被用来生成一些与控制器(controller)相关的链接。虽然从该方法中我没找到任何可绕过漏洞,但却发现了利用用户可控哈希(controllable hash)进行url_for方法调用的线索。一般来说,url_for方法调用需要把添加进额外参数的用户哈希附加到url后,作为一个查询字符串进行查询,但我通过阅读github说明文档发现,在该方法调用实现过程中,存在一些可控的选项参数:

:only_path - 如果为真true,即返回相应的URL,默认为假false; :protocol - 即希望连接的协议方式,默认为’http’; :host - 指定连接的特定主机,如果:only_path为false,该选项必须明确提供或显式提示,或通过default_url_options给出信息; :subdomain - 指定连接的特定子域名,使用tld_length从host主机信息中分离出子域名。如果该项为false,则从连接的主机信息中删除所有子域名信息; :domain - 指定连接的特定域名,使用tld_length从host主机信息中分离域名信息; :tld_length - 组成顶级域名TLD id的标签数量,当:subdomain 或 :domain提供时有用,默认为ActionDispatch::Http::URL.tld_length,而该项值又默认为1; :port - 指定可选的连接端口; :anchor - 附加在路径后的属性anchor名称; :params - 附加在路径后的请求参数; :trailing_slash - 如果为true,则在末尾添加’/‘,如/archive/2009/; :script_name - 相对于网站根目录的应用程序路径,如果有该选项,则附上应用程序路径。

由于此前我在其它一些应用中见过:protocol、:host选项,以及blacklisted/removed和 :only_path设置为true的实例,但从没见过:script_name选项的使用。貌似:script_name用在path_for方法中居多,且一般被放在路径path开头,如下path_for方法:

代码语言:javascript
复制
def path_for(options)
    path = options[:script_name].to_s.chomp("/")
    path << options[:path] if options.key?(:path)

    add_trailing_slash(path) if options[:trailing_slash]
    add_params(path, options[:params]) if options.key?(:params)
    add_anchor(path, options[:anchor]) if options.key?(:anchor)

    path
    end

GitHub中有多个地方用类似以下的代码来创建相应链接:

代码语言:javascript
复制
<a class="link" href="<%= url_for(request.query_parameters.merge(only_path: true)) %>">
    Click me
</a>

也就是说,如果构造形如?script_name=javascript:alert(1)// 的请求字符串,将会生成如以html文件代码:

代码语言:javascript
复制
<a class="link" href="javascript:alert(1)//user/repo/...">
    Click me
</a>

可以看出,如果点击’Click me’,将会触发一个反射型XSS,虽然可能会被CSP策略阻拦,但也算是一个有意思的漏洞。

另外我还发现了一个用可控参数调用url_for方法的地方,这一次它会形成一个重定向跳转。该处在应用程序控制器中的源码如下:

代码语言:javascript
复制
before_action :check_source

  def check_source
    source = params["source"]
    return redirect_to(check_source_redirect_url) if source == "message"
  end

  def check_source_redirect_url
    query = Addressable::URI.parse(request.env["REQUEST_URI"]).query_values || {}
    filtered_params = query.except("source", "token").merge(only_path: true)
    url_for(filtered_params)
  end

由于其中使用了only_path: true,它通常只允许现有主机相关的URL,并且只保留查询参数,但使用script_name的技巧却会引发一些有意思结果。script_name选项不需要以斜线开头,且如果用到了redirect_to的话,script_name中的相关信息将会附加到host之后。最终的请求构造如下:

代码语言:javascript
复制
curl -i 'http://local.dev?source=message&script_name=ggg'
HTTP/1.1 302 Found
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Download-Options: noopen
X-Permitted-Cross-Domain-Policies: none
Referrer-Policy: strict-origin-when-cross-origin
Location: http://local.devggg/welcome/index
Content-Type: text/html; charset=utf-8
Cache-Control: no-cache
X-Request-Id: 7c8eedfa-f552-4d5a-bbcd-295f4e7fd9c0
X-Runtime: 0.002744
Transfer-Encoding: chunked

<html><body>You are being <a href="http://local.devggg/welcome/index">redirected</a>.</body></html>

由于最后的域名是可控的,所以如果script_name中用到了.attacker.domain,那将会发生到.attacker.domain的跳转,之后,我就直接把该问题以开放重定向漏洞上报了。

漏洞利用

第二天,我和朋友讨论过后,他建议我可以把开放重定向用到OAuth tokens上试试,看看会否产生影响。一番分析之后,我意识到这个开放重定向漏洞威力还是大的,它会影响几乎所有的Github控制器路径。

GitHub内置了一些集成的OAuth应用服务,其中就包含了Gist,GitHub Gist和GitHub共享同一个rails应用服务,只是暴露的主机名和路径不同而已。当登录Gist时,在进行OAuth机制的同时会发生以下一大堆的跳转:

1、https://github.com/login/oauth/authorize?client_id=7e0a3cd836d3e544dbd9&redirect_uri=https://gist.github.com/auth/github/callback 2、https://gist.github.com/auth/github/callback?browser_session_id=XXX&code=YYY 3、https://gist.github.com/auth/github 4、https://github.com/login/oauth/authorize?client_id=7e0a3cd836d3e544dbd9&redirect_uri=https%3A%2F%2Fgist.github.com%2Fauth%2Fgithub%2Fcallback&response_type=code&state=ZZZ 5、https://gist.github.com/auth/github/callback?browser_session_id=XXX&code=YYY&state=ZZZ 6、https://gist.github.com/

攻击者要成功登录Gist服务,只需要上述过程中的browser_session_id和code参数,由于client_id是公开的,因为这里只有CSRF防护,所以攻击者端在请求时即可生成state参数。

刚开始到redirect_uri 的跳转,可包含code和browser_session_id参数,所以我尝试在其中添加了形如script_name=.wbowling.info域名值,一试竟然有效了,可以成功携带相关请求参数跳转到.wbowling.info。

之后,我通过功能路径https://gist.github.com/auth/github/callback获取到了有效的state参数,然后,再综合前面的browser_session_id和code参数,成功登录了Gist服务,实现了账户劫持攻击。

由于GitHub 和 Gist使用的会话token不同,因此利用该漏洞不能对受害者的github.com服务造成影响,仅会对Gist服务形成访问控制威胁。

漏洞报送和处理进程

2020.6.26 00:33:38 AEST - 以开放重定向漏洞上报 2020.6.26 12:57:38 AEST - 继续测试发现Gist账户劫持漏洞并上报 2020.6.26 23:33:30 AEST - 漏洞分类 2020.6.29 - 告知漏洞仅影响Gist服务,不涉及GitHub Enterprise产品 2020.10.15 05:45:45 AEDT Github官方奖励$10,000

参考来源:devcraft

本文参与?腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-11-15,如有侵权请联系?cloudcommunity@tencent.com 删除

本文分享自 FreeBuf 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与?腾讯云自媒体同步曝光计划? ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 漏洞发现
  • 漏洞利用
  • 漏洞报送和处理进程
相关产品与服务
手游安全测试
手游安全测试(Security Radar,SR)为企业提供私密的安全测试服务,通过主动挖掘游戏业务安全漏洞(如钻石盗刷、服务器宕机、无敌秒杀等40多种漏洞),提前暴露游戏潜在安全风险,提供解决方案及时修复,最大程度降低事后外挂危害与外挂打击成本。该服务为腾讯游戏开放的手游安全漏洞挖掘技术,杜绝游戏外挂损失。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
http://www.vxiaotou.com