git-shell 沙盒绕过(CVE-2017-8386)

这次漏洞分为两部分,一个是任意文件读取,一个是命令执行,下面先来讲述yi'xi

读取任意文件

这个实在是骚的不行。。。比如说利用help页面绕过git-shell拦截这一点是真的骚

下面为绕过git-shell语句
ssh -p 22 -i id_rsa -t git@172.17.0.2 "git-upload-archive '--help'"
这里进去的是帮助页面,但是这里有一个骚操作shift +e 然后输入想要读取的文件路径就可以成功读取了。

通过git执行命令:

输入感叹号‘!’后。。。加命令就好了
和上面一样,先来
ssh -p 22 -i id_rsa -t git@172.17.0.2 "git-upload-archive '--help'"
然后加!就好了。。。

其实这个也可以叫做满脑子骚操作?

相关原理

二. 原理

  1. 基于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服务器了呢?

禁止git用户执行系统指令

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

  • 创建系统用户git的时候将其shell设置成git-shell
  • 在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这个命令。
evi1cg大佬的博客中有动图,看的更直观。


最后放上P牛的dockerfile 可以一键制作测试环境啦!

FROM vulhub/ubuntu:trusty

MAINTAINER phithon <root@leavesongs.com>

ENV BUILD_TOOLS gcc \
                make \
                wget \
                dh-autoreconf \
                libcurl4-gnutls-dev \
                libexpat1-dev \
                gettext \
                libz-dev \
                libssl-dev \
                asciidoc \
                xmlto \
                docbook2x

RUN apt-get update \
    && apt-get install -y $BUILD_TOOLS \
    && apt-get install -y man less openssh-server --no-install-recommends \
    && rm -r /var/lib/apt/lists/*

RUN mkdir -p /usr/src/git \
    && wget -qO- https://github.com/git/git/archive/v2.12.2.tar.gz | tar zx -C /usr/src/git --strip-components=1 \
    && cd /usr/src/git \
    && make configure \
    && ./configure --prefix=/usr \
    && make all doc info \
    && make install install-doc \
    && make clean \
    && cd / \
    && rm -rf /usr/src/git

RUN mkdir /var/run/sshd \
	&& chmod 0755 /var/run/sshd \
	&& echo 'git:x:33:33:git:/home/git:/bin/bash' >> /etc/passwd \
	&& echo 'git:*:16462:0:99999:7:::' >> /etc/shadow \
	&& echo 'git:x:33:' >> /etc/group \
	&& mkdir -p /home/git/.ssh \
	&& chown 33.33 -R /home/git

ADD authorized_keys /home/git/.ssh/authorized_keys

RUN chown 33.33 /home/git/.ssh/authorized_keys \
    && chmod 0600 /home/git/.ssh/authorized_keys

RUN apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false $BUILD_TOOLS

EXPOSE 22

CMD ["/usr/sbin/sshd", "-D"]