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的地址,以我为例:
在test
目录下建立repo:
其余问题,可以直接参考Installing GitList for Local Reposs
漏洞分析
在 gitlist/src/Controller/TreeController.php:51行:
当我们在repo中进行搜索时,以搜索字符串”chybeta”为例
|
|
则对应的变量即为:
进入到searchTree函数中,即gitlist/src/Git/Repository.php第320行:
query
参数经过了escapeshellarg
函数的过滤,官方文档:
escapeshellarg()把字符串转码为可以在 shell 命令里使用的参数。 将给字符串增加一个单引号并且能引用或者转码任何已经存在的单引号,这样以确保能够直接将一个字符串传入 shell 函数,并且还是确保安全的。对于用户输入的部分参数就应该使用这个函数。shell 函数包含 exec(), system() 执行运算符.
之后进入run方法,gitlist/vendor/klaussilveira/gitter/lib/Gitter/Client.php:63:
在$process = new Process()
处最终构成的命令为:
在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.md
或less README.md
。但倘若我们指定--open-files-in-pager=id;
,注意有一个;
,则在匹配到文件后,则相当于执行id; README.md
,在unix中分号表示顺序的执行各条命令而不关心是否失败。
不过在执行之前经过了escapeshellarg
,会在字符串两边加上单引号,这会有影响吗?不会。
所以当构造如下的数据包:
注意修改了tree/master/search
为tree/c/search
,也即使branch
值为c
,这样拼接出来的最后的语句即为:
当进行查找时,由于READEME.md(内容为chybeta)中含有字符c
,因此可以查找成功,之后由于注入参数的关系,将会执行touch /tmp/test/chybeta
,将会在/tmp/test/目录下创建一个新的文件。