Files
vulhub/git/CVE-2017-8386/README.zh-cn.md
Aaron 63285f61aa
Some checks failed
Vulhub Format Check and Lint / format-check (push) Has been cancelled
Vulhub Format Check and Lint / markdown-check (push) Has been cancelled
Vulhub Docker Image CI / longtime-images-test (push) Has been cancelled
Vulhub Docker Image CI / images-test (push) Has been cancelled
first commit
2025-09-06 16:08:15 +08:00

7.1 KiB
Raw Permalink Blame History

GIT-SHELL 沙盒绕过导致命令执行漏洞CVE-2017-8386

Git shell是一个用于SSH账户的登录shell提供受限的Git访问。在git 2.4.12、2.5.6、2.6.7、2.7.5、2.8.5、2.9.4、2.10.3、2.11.2、2.12.3版本之前可能允许远程认证用户绕过git-shell沙盒执行任意命令。

参考链接:

环境搭建

编译及运行测试环境:

docker compose up -d

为了不和docker母机的ssh端口冲突我将容器的ssh端口设置成3322。本目录下我生成了一个id_rsa这是ssh的私钥连接的时候请指定之。

在连接以前需要先设置私钥的权限为0600chmod 0600 id_rsa,否则连接可能失败。

正常连接其ssh服务ssh -p 3322 -i id_rsa git@127.0.0.1会被git-shell给拦截返回错误fatal: unrecognized command '',并且连接被关闭。

漏洞复现

使用--help技巧连接目标并进入帮助页面

ssh -p 3322 -i id_rsa -t git@127.0.0.1 "git-upload-archive '--help'"

shift+e读取任意文件

回到帮助页面,输入!id执行命令:

(为什么是www-data用户因为git用户和www-data用户编号都是33所以其实他们是一个用户)

原理

基于ssh协议的git拉取流程

git-shell是git服务中重要的组成部分众所周知git服务支持ssh、git、https三种协议来传递项目其中ssh是最安全也最方便的一种方式。

我们随便打开Github上一个项目找到Clone with SSH里列出的地址git@github.com:phith0n/vulhub.git其实这个url就是告诉gitssh用户名是git地址是github.com默认端口是22该项目位于phith0n/vulhub.git这个目录下然后git就通过ssh协议连接上github.com并将对应目录下的项目拉取下来。

所以基于ssh协议的git clone等操作本质上就是通过ssh协议连接上git服务器并将指定目录拉取下来的过程。

那么既然这个过程是个ssh交互的过程那么我直接执行ssh git@github.com是不是就可以登录github服务器了呢显然是不行的你可以试试

说"不行"其实也有偏差实际上我确实是连接上了其ssh服务并验证身份通过了但他给了我一段提示信息"Hi phith0n! You've successfully authenticated, but GitHub does not provide shell access.",就把我的连接关了。

所以正常来说基于ssh的git拉取过程对于git服务器是安全的。

关于如何搭建一个git服务器可以参考这篇文章

如何禁止git用户执行系统shell

那么github这类git服务商是怎么实现上述"安全"通信的流程的呢?

让用户可以通过ssh认证身份但又不给用户shell这个过程有两种方法实现

  1. 创建系统用户git的时候将其shell设置成git-shell
  2. 在authorized_keys文件每个ssh-key的前面设置command覆盖或劫持重写原本的命令

第一种方法比较直观就是创建用户的时候不给其正常的bash或sh的shell而是给它一个git-shell。git-shell是一个沙盒环境在git-shell下只允许执行沙盒内包含的命令。

第二种方法不仅在git服务器上使用很多Linux发行版也会用到。比如aws默认安装后是不允许root登录的实现方法就是在/root/.ssh/authorized_keys中设置command="echo 'Please login as the user \"ec2-user\" rather than the user \"root\".';echo;sleep 10"。这句话相当于覆盖了原本执行的shell变成了echo一段文字。

当然第二种方法内也可以用git-shell比如在添加git用户的时候赋予其正常的/bin/bash但在authorized_keys中设置command="git-shell -c \"$SSH_ORIGINAL_COMMAND\""实际上还是使用了git-shell。

git-shell 沙盒绕过漏洞CVE-2017-8386

git-shell是一个可以限制用户执行命令的shell如果我们在git用户家目录下创建一个新目录git-shell-commands然后将你允许用户执行的命令放在这个目录下这就创建好了一个沙盒。在git-shell中只能执行/home/git/git-shell-commands目录下的命令。

如果系统是没有git-shell-commands目录那么git-shell默认只允许执行如下三个命令

  • git-receive-pack <argument>
  • git-upload-pack <argument>
  • git-upload-archive <argument>

这就是白名单。

但CVE-2017-8386的作者发现执行git-upload-archive --help(或git-receive-pack --help将会进入一个交互式的man页面man又调用了less命令最后是一个可以上下翻页的帮助文档。

本来这也没什么但是less命令有一个特性就是其支持一些交互式的方法。比如在less页面中shift+e可以打开Examine功能通过这个功能可以读取任意文件输入!id就可以执行id这个命令。

可以随便找台linux计算机试一下执行less /etc/passwd来到less的页面然后在英文输入法下输入!id就可以执行id命令

所以利用这个特性我们就可以绕过git-shell的沙盒读取任意文件或执行任意命令了

我们可以先试试在Linux下直接执行git-receive-pack --help,再输入!id,看到的效果和上图是类似的。

evi1cg大佬的博客中有动图,看的更直观。

通过ssh进行利用

那么,如何远程利用这个漏洞?

我们前面试了,直接ssh git@gitserver只能拿到git-shell或返回一段提醒文字我们就利用上一节里提到的沙盒绕过漏洞执行命令

ssh -p 3322 -i id_rsa -t git@127.0.0.1 "git-upload-archive '--help'"

进入帮助页面然后按shift+e或!id即可。

一些限制

我前文说了一般配置git用户不让ssh拥有shell有两种方法一是创建用户的时候设置其shell为/usr/bin/git-shell二是在authorized_keys中覆盖command。

如果目标服务器使用了第一种方法,我们即使成功执行了git-upload-archive '--help'进入帮助页面,也不能执行命令。因为!id还是在git-shell下执行git-shell中没有id命令所以依旧执行不成功。

但读取文件是一定可以的因为读取文件不是通过命令读取的所以不受git-shell沙盒的影响。

如果目标服务器是用第二种方法配置的git-shell比如我这里这个测试环境我是在/etc/passwd文件设置git用户的shell是bash而在authorized_keys中覆盖command执行git-shell。

这种情况下,如果我进入了帮助页面,输入!id是可以成功执行id命令的因为此时id是在bash下执行的而不是在git-shell下执行的所以没有沙盒限制。

总的来说,这个漏洞至少能做到任意文件读取,有可能可以执行任意命令。