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
128 lines
7.1 KiB
Markdown
128 lines
7.1 KiB
Markdown
# 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沙盒执行任意命令。
|
||
|
||
参考链接:
|
||
|
||
- https://insinuator.net/2017/05/git-shell-bypass-by-abusing-less-cve-2017-8386/
|
||
- https://www.leavesongs.com/PENETRATION/git-shell-cve-2017-8386.html
|
||
|
||
## 环境搭建
|
||
|
||
编译及运行测试环境:
|
||
|
||
```
|
||
docker compose up -d
|
||
```
|
||
|
||
为了不和docker母机的ssh端口冲突,我将容器的ssh端口设置成3322。本目录下我生成了一个`id_rsa`,这是ssh的私钥,连接的时候请指定之。
|
||
|
||
在连接以前,需要先设置私钥的权限为0600:`chmod 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就是告诉git,ssh用户名是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服务器,可以参考[这篇文章](http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000/00137583770360579bc4b458f044ce7afed3df579123eca000)
|
||
|
||
### 如何禁止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大佬的博客](https://evi1cg.me/archives/CVE-2017-8386.html)中有动图,看的更直观。
|
||
|
||
### 通过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下执行的,所以没有沙盒限制。
|
||
|
||
总的来说,这个漏洞至少能做到任意文件读取,有可能可以执行任意命令。
|