文章详情
GitHub企业版RCE漏洞(GitHubEnterprise
简介
GitHub企业版(GHE)的代码默认是混淆的,但是有脚本可以把他们恢复为常规ruby文件.
影响版本:GitHub Enterprise < 2.21.4
修复该漏洞的版本: GitHub Enterprise 2.21.4 released fixing the issue
git基本命令
git revert: 撤销某个单一的commit. 本文中的"撤销"就是gitrevert
。
历史漏洞
参考 https://enterprise.github.com/releases/2.17.6/notes
GitHub Enterprise 2.17.6 August 13, 2019
这与使用分支名称将选项注入git命令有关,分支名称以-允许攻击者截断服务器上的文件开头,因此我认为这是一个开始查看是否引入任何类似错误的好地方。
漏洞原理:使用以一个-
字符开头的"分支名称"(branch names),向git命令中注入选项,允许攻击者截断服务器上的文件。
我认为这个漏洞是一个很好的开始,我看看GitHub企业版(GHE)是否存在类似的漏洞。
发现新漏洞
我开始搜索git进程被调用的所有位置,然后追溯参数以查看它们是否用户可控,以及是否已正确清理(sanitised)。
- 发现是这样的:
- 大多数地方要么将用户控制的数据放在--命令后面,以使它永远不会被解析为选项
- 要么进行检查以确保它是有效的sha1或commitish值,并且不以
-
开头
过了一会儿,我找到了reverse_diff
方法,该方法进行了2次"提交"(commits),最终git diff-tree
与它们一起运行,并且唯一的检查是对于存储库(sha,branch,tag等)都存在有效的git引用(git references)。追溯可知,此函数由revert_range
在之前的2个wiki"提交"(commits)之间进行"撤销"(reverting)时使用的方法调用。
因此,发送POST请求到user/repo/wiki/Home/_revert/57f931f8839c99500c17a148c6aae0ee69ded004/1967827bcd890246b746a5387340356d0ac7710a
会将值(实际参数)57f931f8839c99500c17a148c6aae0ee69ded004
和1967827bcd890246b746a5387340356d0ac7710a
传入reverse_diff
,调用该函数。
完美!我checked out了一个repo(仓库),并通过命令git push origin master:--help
pushed出一个新的分支 名为–help
,之后尝试发送POST请求到user/repo/wiki/Home/_revert/HEAD/--help
。但是没有成功,返回的提示信息是422 Unprocessable Entity
。
为什么会这样?查看服务器日志后发现,是因为 CSRF 令牌无效。事实证明,rails现在具有基于表单的CSRF token,这些token是根据要POST的路径
生成的。
没有检查查询参数,但是在本例中,路由设置为只允许"提交"(commits)的路径参数。
"撤销"(revert)的形式以及有效token是由"wiki比较模板"(wiki compare template)生成的,但遗憾的是,它的验证更加严格,且要求commit具有有效的sha hashes。这意味着我们无法为–help
分支提供有效的表单(form)和token,仅能为具有有效的sha hashes的commit提供:有效的表单(form)和token。
深挖rails中的valid_authenticity_token?
方法(你没看错这个方法最后面是个问号),可以发现,绕过每个表单(form)CSRF的另一种方法是使用全局token,因为存在这样一个"代码路径"(code path),可以在转换时使现有表单向后兼容。
as there is a code path to make existing forms backwards compatible while transitioning.
def valid_authenticity_token?(session, encoded_masked_token) # :doc:
if encoded_masked_token.nil? || encoded_masked_token.empty? || !encoded_masked_token.is_a?(String)
return false
end
begin
masked_token = Base64.strict_decode64(encoded_masked_token)
rescue ArgumentError # encoded_masked_token is invalid Base64
return false
end
# See if it's actually a masked token or not. In order to
# deploy this code, we should be able to handle any unmasked
# tokens that we've issued without error.
# 看看它是否真的是一个masked token。
# 为了部署这段代码,我们应该能够毫无错误地处理任何已发出的unmasked tokens。
if masked_token.length == AUTHENTICITY_TOKEN_LENGTH
# This is actually an unmasked token. This is expected if
# you have just upgraded to masked tokens, but should stop
# happening shortly after installing this gem.
# 这实际上是一个unmasked token。
# 如果你刚刚升级到masked tokens那就是意料之中的,但这种情况应该在安装这个gem后很快就会停止发生。
compare_with_real_token masked_token, session
elsif masked_token.length == AUTHENTICITY_TOKEN_LENGTH * 2
csrf_token = unmask_token(masked_token)
compare_with_real_token(csrf_token, session) ||
valid_per_form_csrf_token?(csrf_token, session)
else
false # Token is malformed.
end
end
上一文章:XSS实战攻击思路总结
下一文章:云上渗透-RDS数据库攻防
相关推荐
- 05-24Vulnstack内网靶场渗透记录
- 05-19LightCMS文件上传
- 10-21CVE-2020-15148Yii2反序列化RCEPOP链分析
- 11-09谈谈Django的RCE
- 11-23从webpack开始发现的漏洞大礼包
- 05-18lightcms后台RCE漏洞挖掘
- 10-21ctf中常见phprce绕过总结
- 10-20我靠seo赚到的几百万收入
- 11-04摩拜单车和QQ合作 7天免押金 送免费骑行月卡
- 10-21探索Mimikatz-第2部分-SSP
- 10-27某nc反序列化回显绕过
- 10-21记一次edu站点从敏感信息泄露到getshell
- 11-16WeblogicIIOP协议NAT网络绕过
- 05-12开放封闭原则的含义(不改代码怎么写新功能)