2017-05-11 11:08:38
阅读:583次
点赞(0)
收藏
作者:running_wen
翻译:running_wen
预估稿费:140RMB
投稿方式:发送邮件至linwei#360.cn,或登陆网页版在线投稿
git-shell在git远程会话之上引入了ssh隧道,是一种受限的shell。其背后的基本思想就是,在ssh会话中限制能够执行的命令,使其仅仅能执行git需要的相应命令。git需要执行的命令如下 :
git-receive-pack Receivesrepositoryupdatesfromtheclient. git-upload-pack Pushesrepositoryupdatestotheclient. git-upload-archive Pushesarepositoryarchivetotheclient.
除了上面这几个自带命令,管理员也可以通过shell脚本文件或者其他可执行文件来提供自定义命令。由于这些自定义的都是完全自定义的,因此此处主要讨论自带的命令。
如果你熟悉git,那你可能知道大部分服务器都会将git协议封装在SSH、HTTP/S[3]协议中。这是因为,git协议是基于简单文本的协议[4],在数据传输时并不提供任何认证或者保护机制。通常的做法是利用SSH协议实现repository写权限的控制,因为SSH协议本身提供多种认证机制、可靠的加密、低的协议额外开销。使用SSH的缺点是,期初SSH是为了远程用户提供Shell访问。而通常情况下,git用户是不具备shell访问能力的。为了限制连接,使其仅仅能够访问repository,我们需要将原始shell(典型的就是bash shell,或者类似的)替换为更受限的shell。大型主机厂商通常都自己实现上面git命令的功能。但是也能使用git开发者提供的shell(该shell限制为仅仅允许与调用执行白名单中的命令)。
搭建过程很简单。比较建议在服务器上服务器上创建一个特定用户,并 使用git-shell命令作为
该用户的login shell[5]。另一种方式是,使用SSH force命令,是你能够对每一个客户端进行限制(依赖于登录过程中使用的key),后面还会介绍其他 方式。如果在本地repository中设置好了可远程访问的repository,git push命令本质上会执行下面的命令:
sshgit@remoteserver“git-receive-pack‘/myrepository.git'” 008957d650a081a34bcbacdcdb5a94bddb506adfe8e0refs/heads/developreport-statusdelete-refsside-band-64kquietofs-deltaagent=git/2.1.4 003fbe8910f121957e3326c4fdd328ab9aabd05abdb5refs/heads/master 00000000如果两个repository具有同样的提交,如果执行的命令不在白名单中(不是上面列举的自带命令,也不在home目录下的git-shell-commands目录下),那么会报错提示命令无法识别。由于不是交互式shell,典型的命令注入攻击此处并不适用。相反,命令行仅仅以空格分隔开(引号包含的是整体),并被execve执行。
上面的情况,有让我更多的考虑赋值协议处理的二进制文件本身。git本身提供help命令,能针对特定命令打开帮助页面(man page),如init命令:
$githelpinit GIT-INIT(1)GitManualGIT-INIT(1) NAME git-init-CreateanemptyGitrepositoryorreinitializeanexistingone [...]其他的一些命令也可以通过-help参数来显示该命令对应的帮助页面,如下所示:
$gitinit--help GIT-INIT(1)GitManualGIT-INIT(1) NAME git-init-CreateanemptyGitrepositoryorreinitializeanexistingone [...]同样,这也适用于git-receive-pack、git-upload-archive命令。在服务器上运行git-receive-pack -help命令,如下所示:
$sshgit@remoteserver"git-receive-pack'--help'" GIT-RECEIVE-PACK(1)GitManualGIT-RECEIVE-PACK(1) NAME git-receive-pack-Receivewhatispushedintotherepository [...]但是怎样才能绕过能够执行命令的限制呢?在大多数系统上,如果使用man命令打开帮助页面,man specification被解析、渲染,并以ANSI输出,通过管道传递给pager(通常是less命令)。这样,我们就可以滚动与搜索帮助页面,而与terminal终端的大力与容量无关。
除了作为一个简单的pager,less命令还具有额外的交互性特性。它允许你打开其他的文件并读取,输出当前输出到log文件,在当前shell下执行系统命令。要想能够利用这些特性,需要在交互式模式下运行less命令。在pty可用情况下,交互式模式可用。通常SSH连接到服务器,pty就启用了,但直接运行命令是pty不可用。幸运的是,我们可以强制ssh 客户端分配一个pty(只要服务器端没有禁用它,通常服务端也不会禁用它)。运行实例如下:
$ssh-tgit@remoteserver"git-receive-pack'--help'" GIT-RECEIVE-PACK(1)GitManualGIT-RECEIVE-PACK(1) NAME git-receive-pack-Receivewhatispushedintotherepository Manualpagegit-receive-pack(1)line1(presshforhelporqtoquit)现在我们可以使用less命令的交互特性。上面建议的建立方式有一个限制,那就是由于shell执行任然是在当前git-shell环境下,之前git-shell对ssh中能执行的命令限制同样适用于此时能执行的命令。不管怎样,我们限制可以读文件、列举目录(利用tab补全),并将当前显示结果输出到文件(如果能够控制文件部分内容,则作用更大)
如你所料,还有另一种适用git-shell的方式,虽然不是很常见。该方法适用于限制特定用户能访问repository,或者不允许改变git用户的shell的情况。
此时,我们将login shell提供给用户,并在.ssh/authorized_keys文件中指定git-shell命令来限定用户。限定用户的代码如下:
command="git-shell-c\"$SSH_ORIGINAL_COMMAND\""ssh-rsaAAAAB3NzaC1yc2EA[...]除了能执行less命令,上面的配置其他行为与配置为log shell的相同。
另外,你也可以给force命令提供额外参数来限制ssh的特性。最常见的标记就是no-pty[6],这能防止客户端请求一个pty,这样就不能在交互式模式下运行less命令。
时间线
2017-04-25 Reported to the git-security mailing list
2017-05-01 Assigned CVE-2017-8386
2017-05-10 Release of the fixed versions v2.4.12, v2.5.6, v2.6.7, v2.7.5, v2.8.5, v2.9.4, v2.10.3, v2.11.2, v2.12.3 and v2.13.0
参考
[1] https://about.gitlab.com/2017/04/05/gitlab-9-dot-0-dot-4-security-release/ [2] https://about.gitlab.com/2017/05/08/gitlab-9-dot-1-dot-3-security-release/ [3] https://git-scm.com/book/no-nb/v1/Git-on-the-Server-The-Protocols [4] https://github.com/git/git/blob/master/Documentation/technical/pack-protocol.txt [5] https://git-scm.com/book/en/v2/Git-on-the-Server-Setting-Up-the-Server [6] http://man.openbsd.org/sshd#command=”command”本文由 安全客 翻译,转载请注明“转自安全客”,并附上链接。
原文链接:https://insinuator.net/2017/05/git-shell-bypass-by-abusing-less-cve-2017-8386/