From bd7bb0b69a9d9202f94284fbf5ffbaff2307106b Mon Sep 17 00:00:00 2001 From: Eli McRae Date: Fri, 17 Feb 2023 09:34:05 -0600 Subject: [PATCH 1/8] testing something --- autorecon/default-plugins/dirbuster.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/autorecon/default-plugins/dirbuster.py b/autorecon/default-plugins/dirbuster.py index 5f77851..844ae1b 100644 --- a/autorecon/default-plugins/dirbuster.py +++ b/autorecon/default-plugins/dirbuster.py @@ -11,9 +11,11 @@ def __init__(self): self.slug = 'dirbuster' self.priority = 0 self.tags = ['default', 'safe', 'long', 'http'] + print('asdfasdf') + exit() def configure(self): - self.add_choice_option('tool', default='feroxbuster', choices=['feroxbuster', 'gobuster', 'dirsearch', 'ffuf', 'dirb'], help='The tool to use for directory busting. Default: %(default)s') + self.add_choice_option('tool', default='feroxbuster', choices=['feroxbuster', 'gobuster', 'dirsearch', 'ffuf', 'dirb', 'none'], help='The tool to use for directory busting. set to "none" to disable dirbusting. Default: %(default)s') self.add_list_option('wordlist', default=[os.path.join(config['data_dir'], 'wordlists', 'dirbuster.txt')], help='The wordlist(s) to use when directory busting. Separate multiple wordlists with spaces. Default: %(default)s') self.add_option('threads', default=10, help='The number of threads to use when directory busting. Default: %(default)s') self.add_option('ext', default='txt,html,php,asp,aspx,jsp', help='The extensions you wish to fuzz (no dot, comma separated). Default: %(default)s') @@ -24,8 +26,11 @@ def configure(self): def check(self): tool = self.get_option('tool') - if tool == 'feroxbuster' and which('feroxbuster') is None: - self.error('The feroxbuster program could not be found. Make sure it is installed. (On Kali, run: sudo apt install feroxbuster)') + if tool == 'none': + self.info('dirbuster disabled via "--dirbuster.tool none"') + return False + elif tool == 'feroxbuster' and which('feroxbuster') is None: + self.error('The feroxbuster program could not be found. Make sure it is installed. (On Kali, run: sudo apt install feroxbuster)s') return False elif tool == 'gobuster' and which('gobuster') is None: self.error('The gobuster program could not be found. Make sure it is installed. (On Kali, run: sudo apt install gobuster)') @@ -41,6 +46,8 @@ def check(self): return False async def run(self, service): + if self.get_option('tool') == 'none': + return dot_extensions = ','.join(['.' + x for x in self.get_option('ext').split(',')]) for wordlist in self.get_option('wordlist'): name = os.path.splitext(os.path.basename(wordlist))[0] From a014c19ac61cf2702bae957967c711f4f3dd8892 Mon Sep 17 00:00:00 2001 From: Eli McRae Date: Fri, 17 Feb 2023 10:01:49 -0600 Subject: [PATCH 2/8] asdf --- .gitignore | 1 + autorecon/default-plugins/dirbuster.py | 5 +++-- autorecon/main.py | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index a89c11f..3b3d60f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ __pycache__ *.pyc results/ +venv/ diff --git a/autorecon/default-plugins/dirbuster.py b/autorecon/default-plugins/dirbuster.py index 844ae1b..94c3081 100644 --- a/autorecon/default-plugins/dirbuster.py +++ b/autorecon/default-plugins/dirbuster.py @@ -11,8 +11,8 @@ def __init__(self): self.slug = 'dirbuster' self.priority = 0 self.tags = ['default', 'safe', 'long', 'http'] - print('asdfasdf') - exit() + # print('asdfasdf') + # exit() def configure(self): self.add_choice_option('tool', default='feroxbuster', choices=['feroxbuster', 'gobuster', 'dirsearch', 'ffuf', 'dirb', 'none'], help='The tool to use for directory busting. set to "none" to disable dirbusting. Default: %(default)s') @@ -25,6 +25,7 @@ def configure(self): self.match_service_name('^nacn_http$', negative_match=True) def check(self): + print('asdfasdfasdf') tool = self.get_option('tool') if tool == 'none': self.info('dirbuster disabled via "--dirbuster.tool none"') diff --git a/autorecon/main.py b/autorecon/main.py index f9542de..50f51f4 100644 --- a/autorecon/main.py +++ b/autorecon/main.py @@ -1111,6 +1111,7 @@ def unknown_help(): autorecon.argparse.set_defaults(**{'global.' + slugify(gkey).replace('-', '_'): gval}) elif isinstance(val, dict): # Process potential plugin arguments. for pkey, pval in config_toml[key].items(): + print(pkey, pval) if autorecon.argparse.get_default(slugify(key).replace('-', '_') + '.' + slugify(pkey).replace('-', '_')) is not None: for action in autorecon.argparse._actions: if action.dest == slugify(key).replace('-', '_') + '.' + slugify(pkey).replace('-', '_'): From da7dc2c097558d9f64361f421ec7740ca6b96be2 Mon Sep 17 00:00:00 2001 From: Eli McRae Date: Mon, 20 Feb 2023 09:16:42 -0600 Subject: [PATCH 3/8] option to disable dirbuster. --- autorecon/default-plugins/__init__.py | 0 autorecon/default-plugins/bruteforce-ftp.py | 17 - autorecon/default-plugins/bruteforce-http.py | 20 - autorecon/default-plugins/bruteforce-rdp.py | 17 - autorecon/default-plugins/bruteforce-smb.py | 17 - autorecon/default-plugins/bruteforce-ssh.py | 17 - .../default-plugins/curl-known-security.py | 26 - autorecon/default-plugins/curl-robots.py | 26 - autorecon/default-plugins/curl.py | 18 - autorecon/default-plugins/dirbuster.py | 11 +- .../default-plugins/dns-reverse-lookup.py | 14 - .../default-plugins/dns-zone-transfer.py | 18 - .../dnsrecon-subdomain-bruteforce.py | 27 - autorecon/default-plugins/dnsrecon.py | 30 - autorecon/default-plugins/enum4linux.py | 34 - autorecon/default-plugins/get-arch.py | 16 - autorecon/default-plugins/ldap-search.py | 16 - autorecon/default-plugins/lookup-sid.py | 16 - autorecon/default-plugins/nbtscan.py | 17 - autorecon/default-plugins/nikto.py | 16 - autorecon/default-plugins/nmap-ajp.py | 14 - autorecon/default-plugins/nmap-cassandra.py | 14 - autorecon/default-plugins/nmap-cups.py | 14 - autorecon/default-plugins/nmap-distccd.py | 14 - autorecon/default-plugins/nmap-dns.py | 14 - autorecon/default-plugins/nmap-finger.py | 14 - autorecon/default-plugins/nmap-ftp.py | 14 - autorecon/default-plugins/nmap-http.py | 17 - autorecon/default-plugins/nmap-imap.py | 14 - autorecon/default-plugins/nmap-irc.py | 14 - autorecon/default-plugins/nmap-kerberos.py | 17 - autorecon/default-plugins/nmap-ldap.py | 14 - autorecon/default-plugins/nmap-mongodb.py | 14 - autorecon/default-plugins/nmap-mountd.py | 14 - autorecon/default-plugins/nmap-msrpc.py | 14 - autorecon/default-plugins/nmap-mssql.py | 18 - .../default-plugins/nmap-multicast-dns.py | 14 - autorecon/default-plugins/nmap-mysql.py | 18 - autorecon/default-plugins/nmap-nfs.py | 14 - autorecon/default-plugins/nmap-nntp.py | 14 - autorecon/default-plugins/nmap-ntp.py | 14 - autorecon/default-plugins/nmap-oracle.py | 17 - autorecon/default-plugins/nmap-pop3.py | 14 - autorecon/default-plugins/nmap-rdp.py | 14 - autorecon/default-plugins/nmap-redis.py | 14 - autorecon/default-plugins/nmap-rmi.py | 14 - autorecon/default-plugins/nmap-rsync.py | 14 - autorecon/default-plugins/nmap-sip.py | 14 - autorecon/default-plugins/nmap-smb.py | 14 - autorecon/default-plugins/nmap-smtp.py | 14 - autorecon/default-plugins/nmap-snmp.py | 14 - autorecon/default-plugins/nmap-ssh.py | 14 - autorecon/default-plugins/nmap-telnet.py | 14 - autorecon/default-plugins/nmap-tftp.py | 14 - autorecon/default-plugins/nmap-vnc.py | 14 - autorecon/default-plugins/onesixtyone.py | 18 - autorecon/default-plugins/oracle-odat.py | 21 - autorecon/default-plugins/oracle-patator.py | 14 - autorecon/default-plugins/oracle-scanner.py | 20 - autorecon/default-plugins/oracle-tnscmd.py | 22 - .../default-plugins/portscan-all-tcp-ports.py | 52 -- .../portscan-guess-tcp-ports.py | 48 -- .../portscan-top-100-udp-ports.py | 40 - autorecon/default-plugins/redis-cli.py | 24 - .../default-plugins/reporting-cherrytree.py | 91 --- .../default-plugins/reporting-markdown.py | 75 -- autorecon/default-plugins/rpcclient.py | 14 - autorecon/default-plugins/rpcdump.py | 16 - autorecon/default-plugins/rsync-list-files.py | 14 - autorecon/default-plugins/showmount.py | 14 - autorecon/default-plugins/sipvicious.py | 15 - autorecon/default-plugins/smb-vuln.py | 18 - autorecon/default-plugins/smbclient.py | 16 - autorecon/default-plugins/smbmap.py | 20 - autorecon/default-plugins/smtp-user-enum.py | 20 - autorecon/default-plugins/snmpwalk.py | 23 - autorecon/default-plugins/sslscan.py | 16 - .../default-plugins/subdomain-enumeration.py | 34 - .../virtual-host-enumeration.py | 39 - autorecon/default-plugins/whatweb.py | 16 - autorecon/default-plugins/winrm-detection.py | 32 - autorecon/default-plugins/wkhtmltoimage.py | 23 - autorecon/default-plugins/wpscan.py | 20 - autorecon/main.py | 15 +- autorecon/plugins.py | 8 +- poetry.lock | 732 +++++++++++++++++- 86 files changed, 727 insertions(+), 1683 deletions(-) delete mode 100644 autorecon/default-plugins/__init__.py delete mode 100644 autorecon/default-plugins/bruteforce-ftp.py delete mode 100644 autorecon/default-plugins/bruteforce-http.py delete mode 100644 autorecon/default-plugins/bruteforce-rdp.py delete mode 100644 autorecon/default-plugins/bruteforce-smb.py delete mode 100644 autorecon/default-plugins/bruteforce-ssh.py delete mode 100644 autorecon/default-plugins/curl-known-security.py delete mode 100644 autorecon/default-plugins/curl-robots.py delete mode 100644 autorecon/default-plugins/curl.py delete mode 100644 autorecon/default-plugins/dns-reverse-lookup.py delete mode 100644 autorecon/default-plugins/dns-zone-transfer.py delete mode 100644 autorecon/default-plugins/dnsrecon-subdomain-bruteforce.py delete mode 100644 autorecon/default-plugins/dnsrecon.py delete mode 100644 autorecon/default-plugins/enum4linux.py delete mode 100644 autorecon/default-plugins/get-arch.py delete mode 100644 autorecon/default-plugins/ldap-search.py delete mode 100644 autorecon/default-plugins/lookup-sid.py delete mode 100644 autorecon/default-plugins/nbtscan.py delete mode 100644 autorecon/default-plugins/nikto.py delete mode 100644 autorecon/default-plugins/nmap-ajp.py delete mode 100644 autorecon/default-plugins/nmap-cassandra.py delete mode 100644 autorecon/default-plugins/nmap-cups.py delete mode 100644 autorecon/default-plugins/nmap-distccd.py delete mode 100644 autorecon/default-plugins/nmap-dns.py delete mode 100644 autorecon/default-plugins/nmap-finger.py delete mode 100644 autorecon/default-plugins/nmap-ftp.py delete mode 100644 autorecon/default-plugins/nmap-http.py delete mode 100644 autorecon/default-plugins/nmap-imap.py delete mode 100644 autorecon/default-plugins/nmap-irc.py delete mode 100644 autorecon/default-plugins/nmap-kerberos.py delete mode 100644 autorecon/default-plugins/nmap-ldap.py delete mode 100644 autorecon/default-plugins/nmap-mongodb.py delete mode 100644 autorecon/default-plugins/nmap-mountd.py delete mode 100644 autorecon/default-plugins/nmap-msrpc.py delete mode 100644 autorecon/default-plugins/nmap-mssql.py delete mode 100644 autorecon/default-plugins/nmap-multicast-dns.py delete mode 100644 autorecon/default-plugins/nmap-mysql.py delete mode 100644 autorecon/default-plugins/nmap-nfs.py delete mode 100644 autorecon/default-plugins/nmap-nntp.py delete mode 100644 autorecon/default-plugins/nmap-ntp.py delete mode 100644 autorecon/default-plugins/nmap-oracle.py delete mode 100644 autorecon/default-plugins/nmap-pop3.py delete mode 100644 autorecon/default-plugins/nmap-rdp.py delete mode 100644 autorecon/default-plugins/nmap-redis.py delete mode 100644 autorecon/default-plugins/nmap-rmi.py delete mode 100644 autorecon/default-plugins/nmap-rsync.py delete mode 100644 autorecon/default-plugins/nmap-sip.py delete mode 100644 autorecon/default-plugins/nmap-smb.py delete mode 100644 autorecon/default-plugins/nmap-smtp.py delete mode 100644 autorecon/default-plugins/nmap-snmp.py delete mode 100644 autorecon/default-plugins/nmap-ssh.py delete mode 100644 autorecon/default-plugins/nmap-telnet.py delete mode 100644 autorecon/default-plugins/nmap-tftp.py delete mode 100644 autorecon/default-plugins/nmap-vnc.py delete mode 100644 autorecon/default-plugins/onesixtyone.py delete mode 100644 autorecon/default-plugins/oracle-odat.py delete mode 100644 autorecon/default-plugins/oracle-patator.py delete mode 100644 autorecon/default-plugins/oracle-scanner.py delete mode 100644 autorecon/default-plugins/oracle-tnscmd.py delete mode 100644 autorecon/default-plugins/portscan-all-tcp-ports.py delete mode 100644 autorecon/default-plugins/portscan-guess-tcp-ports.py delete mode 100644 autorecon/default-plugins/portscan-top-100-udp-ports.py delete mode 100644 autorecon/default-plugins/redis-cli.py delete mode 100644 autorecon/default-plugins/reporting-cherrytree.py delete mode 100644 autorecon/default-plugins/reporting-markdown.py delete mode 100644 autorecon/default-plugins/rpcclient.py delete mode 100644 autorecon/default-plugins/rpcdump.py delete mode 100644 autorecon/default-plugins/rsync-list-files.py delete mode 100644 autorecon/default-plugins/showmount.py delete mode 100644 autorecon/default-plugins/sipvicious.py delete mode 100644 autorecon/default-plugins/smb-vuln.py delete mode 100644 autorecon/default-plugins/smbclient.py delete mode 100644 autorecon/default-plugins/smbmap.py delete mode 100644 autorecon/default-plugins/smtp-user-enum.py delete mode 100644 autorecon/default-plugins/snmpwalk.py delete mode 100644 autorecon/default-plugins/sslscan.py delete mode 100644 autorecon/default-plugins/subdomain-enumeration.py delete mode 100644 autorecon/default-plugins/virtual-host-enumeration.py delete mode 100644 autorecon/default-plugins/whatweb.py delete mode 100644 autorecon/default-plugins/winrm-detection.py delete mode 100644 autorecon/default-plugins/wkhtmltoimage.py delete mode 100644 autorecon/default-plugins/wpscan.py diff --git a/autorecon/default-plugins/__init__.py b/autorecon/default-plugins/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/autorecon/default-plugins/bruteforce-ftp.py b/autorecon/default-plugins/bruteforce-ftp.py deleted file mode 100644 index 24cd7c8..0000000 --- a/autorecon/default-plugins/bruteforce-ftp.py +++ /dev/null @@ -1,17 +0,0 @@ -from autorecon.plugins import ServiceScan - -class BruteforceFTP(ServiceScan): - - def __init__(self): - super().__init__() - self.name = "Bruteforce FTP" - self.tags = ['default', 'ftp'] - - def configure(self): - self.match_service_name(['^ftp', '^ftp\-data']) - - def manual(self, service, plugin_was_run): - service.add_manual_commands('Bruteforce logins:', [ - 'hydra -L "' + self.get_global('username_wordlist', default='/usr/share/seclists/Usernames/top-usernames-shortlist.txt') + '" -P "' + self.get_global('password_wordlist', default='/usr/share/seclists/Passwords/darkweb2017-top100.txt') + '" -e nsr -s {port} -o "{scandir}/{protocol}_{port}_ftp_hydra.txt" ftp://{addressv6}', - 'medusa -U "' + self.get_global('username_wordlist', default='/usr/share/seclists/Usernames/top-usernames-shortlist.txt') + '" -P "' + self.get_global('password_wordlist', default='/usr/share/seclists/Passwords/darkweb2017-top100.txt') + '" -e ns -n {port} -O "{scandir}/{protocol}_{port}_ftp_medusa.txt" -M ftp -h {addressv6}' - ]) diff --git a/autorecon/default-plugins/bruteforce-http.py b/autorecon/default-plugins/bruteforce-http.py deleted file mode 100644 index d735ac4..0000000 --- a/autorecon/default-plugins/bruteforce-http.py +++ /dev/null @@ -1,20 +0,0 @@ -from autorecon.plugins import ServiceScan - -class BruteforceHTTP(ServiceScan): - - def __init__(self): - super().__init__() - self.name = "Bruteforce HTTP" - self.tags = ['default', 'http'] - - def configure(self): - self.match_service_name('^http') - self.match_service_name('^nacn_http$', negative_match=True) - - def manual(self, service, plugin_was_run): - service.add_manual_commands('Credential bruteforcing commands (don\'t run these without modifying them):', [ - 'hydra -L "' + self.get_global('username_wordlist', default='/usr/share/seclists/Usernames/top-usernames-shortlist.txt') + '" -P "' + self.get_global('password_wordlist', default='/usr/share/seclists/Passwords/darkweb2017-top100.txt') + '" -e nsr -s {port} -o "{scandir}/{protocol}_{port}_{http_scheme}_auth_hydra.txt" {http_scheme}-get://{addressv6}/path/to/auth/area', - 'medusa -U "' + self.get_global('username_wordlist', default='/usr/share/seclists/Usernames/top-usernames-shortlist.txt') + '" -P "' + self.get_global('password_wordlist', default='/usr/share/seclists/Passwords/darkweb2017-top100.txt') + '" -e ns -n {port} -O "{scandir}/{protocol}_{port}_{http_scheme}_auth_medusa.txt" -M http -h {addressv6} -m DIR:/path/to/auth/area', - 'hydra -L "' + self.get_global('username_wordlist', default='/usr/share/seclists/Usernames/top-usernames-shortlist.txt') + '" -P "' + self.get_global('password_wordlist', default='/usr/share/seclists/Passwords/darkweb2017-top100.txt') + '" -e nsr -s {port} -o "{scandir}/{protocol}_{port}_{http_scheme}_form_hydra.txt" {http_scheme}-post-form://{addressv6}/path/to/login.php:"username=^USER^&password=^PASS^":"invalid-login-message"', - 'medusa -U "' + self.get_global('username_wordlist', default='/usr/share/seclists/Usernames/top-usernames-shortlist.txt') + '" -P "' + self.get_global('password_wordlist', default='/usr/share/seclists/Passwords/darkweb2017-top100.txt') + '" -e ns -n {port} -O "{scandir}/{protocol}_{port}_{http_scheme}_form_medusa.txt" -M web-form -h {addressv6} -m FORM:/path/to/login.php -m FORM-DATA:"post?username=&password=" -m DENY-SIGNAL:"invalid login message"' - ]) diff --git a/autorecon/default-plugins/bruteforce-rdp.py b/autorecon/default-plugins/bruteforce-rdp.py deleted file mode 100644 index fb38e82..0000000 --- a/autorecon/default-plugins/bruteforce-rdp.py +++ /dev/null @@ -1,17 +0,0 @@ -from autorecon.plugins import ServiceScan - -class BruteforceRDP(ServiceScan): - - def __init__(self): - super().__init__() - self.name = "Bruteforce RDP" - self.tags = ['default', 'rdp'] - - def configure(self): - self.match_service_name(['^rdp', '^ms\-wbt\-server', '^ms\-term\-serv']) - - def manual(self, service, plugin_was_run): - service.add_manual_commands('Bruteforce logins:', [ - 'hydra -L "' + self.get_global('username_wordlist', default='/usr/share/seclists/Usernames/top-usernames-shortlist.txt') + '" -P "' + self.get_global('password_wordlist', default='/usr/share/seclists/Passwords/darkweb2017-top100.txt') + '" -e nsr -s {port} -o "{scandir}/{protocol}_{port}_rdp_hydra.txt" rdp://{addressv6}', - 'medusa -U "' + self.get_global('username_wordlist', default='/usr/share/seclists/Usernames/top-usernames-shortlist.txt') + '" -P "' + self.get_global('password_wordlist', default='/usr/share/seclists/Passwords/darkweb2017-top100.txt') + '" -e ns -n {port} -O "{scandir}/{protocol}_{port}_rdp_medusa.txt" -M rdp -h {addressv6}' - ]) diff --git a/autorecon/default-plugins/bruteforce-smb.py b/autorecon/default-plugins/bruteforce-smb.py deleted file mode 100644 index da658cc..0000000 --- a/autorecon/default-plugins/bruteforce-smb.py +++ /dev/null @@ -1,17 +0,0 @@ -from autorecon.plugins import ServiceScan - -class BruteforceSMB(ServiceScan): - - def __init__(self): - super().__init__() - self.name = 'Bruteforce SMB' - self.tags = ['default', 'safe', 'active-directory'] - - def configure(self): - self.match_service('tcp', 445, '^microsoft\-ds') - self.match_service('tcp', 139, '^netbios') - - def manual(self, service, plugin_was_run): - service.add_manual_command('Bruteforce SMB', [ - 'crackmapexec smb {address} --port={port} -u "' + self.get_global('username_wordlist', default='/usr/share/seclists/Usernames/top-usernames-shortlist.txt') + '" -p "' + self.get_global('password_wordlist', default='/usr/share/seclists/Passwords/darkweb2017-top100.txt') + '"' - ]) diff --git a/autorecon/default-plugins/bruteforce-ssh.py b/autorecon/default-plugins/bruteforce-ssh.py deleted file mode 100644 index 75bb436..0000000 --- a/autorecon/default-plugins/bruteforce-ssh.py +++ /dev/null @@ -1,17 +0,0 @@ -from autorecon.plugins import ServiceScan - -class BruteforceSSH(ServiceScan): - - def __init__(self): - super().__init__() - self.name = "Bruteforce SSH" - self.tags = ['default', 'ssh'] - - def configure(self): - self.match_service_name('ssh') - - def manual(self, service, plugin_was_run): - service.add_manual_command('Bruteforce logins:', [ - 'hydra -L "' + self.get_global('username_wordlist', default='/usr/share/seclists/Usernames/top-usernames-shortlist.txt') + '" -P "' + self.get_global('password_wordlist', default='/usr/share/seclists/Passwords/darkweb2017-top100.txt') + '" -e nsr -s {port} -o "{scandir}/{protocol}_{port}_ssh_hydra.txt" ssh://{addressv6}', - 'medusa -U "' + self.get_global('username_wordlist', default='/usr/share/seclists/Usernames/top-usernames-shortlist.txt') + '" -P "' + self.get_global('password_wordlist', default='/usr/share/seclists/Passwords/darkweb2017-top100.txt') + '" -e ns -n {port} -O "{scandir}/{protocol}_{port}_ssh_medusa.txt" -M ssh -h {addressv6}' - ]) diff --git a/autorecon/default-plugins/curl-known-security.py b/autorecon/default-plugins/curl-known-security.py deleted file mode 100644 index 554db9e..0000000 --- a/autorecon/default-plugins/curl-known-security.py +++ /dev/null @@ -1,26 +0,0 @@ -from autorecon.plugins import ServiceScan -from autorecon.io import fformat - -class CurlKnownSecurity(ServiceScan): - - def __init__(self): - super().__init__() - self.name = "Known Security" - self.tags = ['default', 'safe', 'http'] - - def configure(self): - self.match_service_name('^http') - self.match_service_name('^nacn_http$', negative_match=True) - - async def run(self, service): - if service.protocol == 'tcp': - process, stdout, _ = await service.execute('curl -sSikf {http_scheme}://{addressv6}:{port}/.well-known/security.txt', future_outfile='{protocol}_{port}_{http_scheme}_known-security.txt') - - lines = await stdout.readlines() - - if process.returncode == 0 and lines: - filename = fformat('{scandir}/{protocol}_{port}_{http_scheme}_known-security.txt') - with open(filename, mode='wt', encoding='utf8') as robots: - robots.write('\n'.join(lines)) - else: - service.info('{bblue}[' + fformat('{tag}') + ']{rst} There did not appear to be a .well-known/security.txt file in the webroot (/).') diff --git a/autorecon/default-plugins/curl-robots.py b/autorecon/default-plugins/curl-robots.py deleted file mode 100644 index 7158b25..0000000 --- a/autorecon/default-plugins/curl-robots.py +++ /dev/null @@ -1,26 +0,0 @@ -from autorecon.plugins import ServiceScan -from autorecon.io import fformat - -class CurlRobots(ServiceScan): - - def __init__(self): - super().__init__() - self.name = "Curl Robots" - self.tags = ['default', 'safe', 'http'] - - def configure(self): - self.match_service_name('^http') - self.match_service_name('^nacn_http$', negative_match=True) - - async def run(self, service): - if service.protocol == 'tcp': - process, stdout, _ = await service.execute('curl -sSikf {http_scheme}://{addressv6}:{port}/robots.txt', future_outfile='{protocol}_{port}_{http_scheme}_curl-robots.txt') - - lines = await stdout.readlines() - - if process.returncode == 0 and lines: - filename = fformat('{scandir}/{protocol}_{port}_{http_scheme}_curl-robots.txt') - with open(filename, mode='wt', encoding='utf8') as robots: - robots.write('\n'.join(lines)) - else: - service.info('{bblue}[' + fformat('{tag}') + ']{rst} There did not appear to be a robots.txt file in the webroot (/).') diff --git a/autorecon/default-plugins/curl.py b/autorecon/default-plugins/curl.py deleted file mode 100644 index 5155f50..0000000 --- a/autorecon/default-plugins/curl.py +++ /dev/null @@ -1,18 +0,0 @@ -from autorecon.plugins import ServiceScan - -class Curl(ServiceScan): - - def __init__(self): - super().__init__() - self.name = "Curl" - self.tags = ['default', 'safe', 'http'] - - def configure(self): - self.add_option("path", default="/", help="The path on the web server to curl. Default: %(default)s") - self.match_service_name('^http') - self.match_service_name('^nacn_http$', negative_match=True) - self.add_pattern('(?i)powered[ -]by[^\n]+') - - async def run(self, service): - if service.protocol == 'tcp': - await service.execute('curl -sSik {http_scheme}://{addressv6}:{port}' + self.get_option('path'), outfile='{protocol}_{port}_{http_scheme}_curl.html') diff --git a/autorecon/default-plugins/dirbuster.py b/autorecon/default-plugins/dirbuster.py index 94c3081..adf9e20 100644 --- a/autorecon/default-plugins/dirbuster.py +++ b/autorecon/default-plugins/dirbuster.py @@ -11,11 +11,13 @@ def __init__(self): self.slug = 'dirbuster' self.priority = 0 self.tags = ['default', 'safe', 'long', 'http'] - # print('asdfasdf') - # exit() + self.tool_choices =['feroxbuster', 'gobuster', 'dirsearch', 'ffuf', 'dirb', 'none',] + + # key='plugins_dir' val='/home/user/.local/share/AutoRecon/plugins' # this is where dirbuster.py is being loaded from... not the current directory... I was missing the "install" step via poetry? + def configure(self): - self.add_choice_option('tool', default='feroxbuster', choices=['feroxbuster', 'gobuster', 'dirsearch', 'ffuf', 'dirb', 'none'], help='The tool to use for directory busting. set to "none" to disable dirbusting. Default: %(default)s') + self.add_choice_option('tool', default='feroxbuster', choices=self.tool_choices, help='The tool to use for directory busting. set to "none" to disable dirbusting. Default: %(default)s') self.add_list_option('wordlist', default=[os.path.join(config['data_dir'], 'wordlists', 'dirbuster.txt')], help='The wordlist(s) to use when directory busting. Separate multiple wordlists with spaces. Default: %(default)s') self.add_option('threads', default=10, help='The number of threads to use when directory busting. Default: %(default)s') self.add_option('ext', default='txt,html,php,asp,aspx,jsp', help='The extensions you wish to fuzz (no dot, comma separated). Default: %(default)s') @@ -25,11 +27,10 @@ def configure(self): self.match_service_name('^nacn_http$', negative_match=True) def check(self): - print('asdfasdfasdf') tool = self.get_option('tool') if tool == 'none': self.info('dirbuster disabled via "--dirbuster.tool none"') - return False + return True elif tool == 'feroxbuster' and which('feroxbuster') is None: self.error('The feroxbuster program could not be found. Make sure it is installed. (On Kali, run: sudo apt install feroxbuster)s') return False diff --git a/autorecon/default-plugins/dns-reverse-lookup.py b/autorecon/default-plugins/dns-reverse-lookup.py deleted file mode 100644 index 513cba5..0000000 --- a/autorecon/default-plugins/dns-reverse-lookup.py +++ /dev/null @@ -1,14 +0,0 @@ -from autorecon.plugins import ServiceScan - -class DNSReverseLookup(ServiceScan): - - def __init__(self): - super().__init__() - self.name = 'DNS Reverse Lookup' - self.tags = ['default', 'safe', 'dns'] - - def configure(self): - self.match_service_name('^domain') - - async def run(self, service): - await service.execute('dig -p {port} -x {address} @{address}', outfile='{protocol}_{port}_dns_reverse-lookup.txt') diff --git a/autorecon/default-plugins/dns-zone-transfer.py b/autorecon/default-plugins/dns-zone-transfer.py deleted file mode 100644 index 49bb9cb..0000000 --- a/autorecon/default-plugins/dns-zone-transfer.py +++ /dev/null @@ -1,18 +0,0 @@ -from autorecon.plugins import ServiceScan - -class DNSZoneTransfer(ServiceScan): - - def __init__(self): - super().__init__() - self.name = 'DNS Zone Transfer' - self.tags = ['default', 'safe', 'dns'] - - def configure(self): - self.match_service_name('^domain') - - async def run(self, service): - if self.get_global('domain'): - await service.execute('dig AXFR -p {port} @{address} ' + self.get_global('domain'), outfile='{protocol}_{port}_dns_zone-transfer-domain.txt') - if service.target.type == 'hostname': - await service.execute('dig AXFR -p {port} @{address} {address}', outfile='{protocol}_{port}_dns_zone-transfer-hostname.txt') - await service.execute('dig AXFR -p {port} @{address}', outfile='{protocol}_{port}_dns_zone-transfer.txt') diff --git a/autorecon/default-plugins/dnsrecon-subdomain-bruteforce.py b/autorecon/default-plugins/dnsrecon-subdomain-bruteforce.py deleted file mode 100644 index 8f082bb..0000000 --- a/autorecon/default-plugins/dnsrecon-subdomain-bruteforce.py +++ /dev/null @@ -1,27 +0,0 @@ -from autorecon.plugins import ServiceScan -from shutil import which - -class DnsReconSubdomainBruteforce(ServiceScan): - - def __init__(self): - super().__init__() - self.name = "DnsRecon Bruteforce Subdomains" - self.slug = 'dnsrecon-brute' - self.priority = 0 - self.tags = ['default', 'safe', 'long', 'dns'] - - def configure(self): - self.match_service_name('^domain') - - def check(self): - if which('dnsrecon') is None: - self.error('The program dnsrecon could not be found. Make sure it is installed. (On Kali, run: sudo apt install dnsrecon)') - return False - - def manual(self, service, plugin_was_run): - domain_name = '' - if self.get_global('domain'): - domain_name = self.get_global('domain') - service.add_manual_command('Use dnsrecon to bruteforce subdomains of a DNS domain.', [ - 'dnsrecon -n {address} -d ' + domain_name + ' -D /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt -t brt 2>&1 | tee {scandir}/{protocol}_{port}_dnsrecon_subdomain_bruteforce.txt', - ]) diff --git a/autorecon/default-plugins/dnsrecon.py b/autorecon/default-plugins/dnsrecon.py deleted file mode 100644 index cfb9edc..0000000 --- a/autorecon/default-plugins/dnsrecon.py +++ /dev/null @@ -1,30 +0,0 @@ -from autorecon.plugins import ServiceScan -from shutil import which - -class DnsRecon(ServiceScan): - - def __init__(self): - super().__init__() - self.name = "DnsRecon Default Scan" - self.slug = 'dnsrecon' - self.priority = 0 - self.tags = ['default', 'safe', 'dns'] - - def configure(self): - self.match_service_name('^domain') - - def check(self): - if which('dnsrecon') is None: - self.error('The program dnsrecon could not be found. Make sure it is installed. (On Kali, run: sudo apt install dnsrecon)') - return False - - def manual(self, service, plugin_was_run): - service.add_manual_command('Use dnsrecon to automatically query data from the DNS server. You must specify the target domain name.', [ - 'dnsrecon -n {address} -d 2>&1 | tee {scandir}/{protocol}_{port}_dnsrecon_default_manual.txt' - ]) - - async def run(self, service): - if self.get_global('domain'): - await service.execute('dnsrecon -n {address} -d ' + self.get_global('domain') + ' 2>&1', outfile='{protocol}_{port}_dnsrecon_default.txt') - else: - service.error('A domain name was not specified in the command line options (--global.domain). If you know the domain name, look in the _manual_commands.txt file for the dnsrecon command.') diff --git a/autorecon/default-plugins/enum4linux.py b/autorecon/default-plugins/enum4linux.py deleted file mode 100644 index ac3e787..0000000 --- a/autorecon/default-plugins/enum4linux.py +++ /dev/null @@ -1,34 +0,0 @@ -from autorecon.plugins import ServiceScan -from shutil import which - -class Enum4Linux(ServiceScan): - - def __init__(self): - super().__init__() - self.name = "Enum4Linux" - self.tags = ['default', 'safe', 'active-directory'] - - def configure(self): - self.add_choice_option('tool', default=('enum4linux-ng' if which('enum4linux-ng') else 'enum4linux'), choices=['enum4linux-ng', 'enum4linux'], help='The tool to use for doing Windows and Samba enumeration. Default: %(default)s') - self.match_service_name(['^ldap', '^smb', '^microsoft\-ds', '^netbios']) - self.match_port('tcp', [139, 389, 445]) - self.match_port('udp', 137) - self.run_once(True) - - def check(self): - tool = self.get_option('tool') - if tool == 'enum4linux' and which('enum4linux') is None: - self.error('The enum4linux program could not be found. Make sure it is installed. (On Kali, run: sudo apt install enum4linux)') - return False - elif tool == 'enum4linux-ng' and which('enum4linux-ng') is None: - self.error('The enum4linux-ng program could not be found. Make sure it is installed. (https://github.com/cddmp/enum4linux-ng)') - return False - - async def run(self, service): - if service.target.ipversion == 'IPv4': - tool = self.get_option('tool') - if tool is not None: - if tool == 'enum4linux': - await service.execute('enum4linux -a -M -l -d {address} 2>&1', outfile='enum4linux.txt') - elif tool == 'enum4linux-ng': - await service.execute('enum4linux-ng -A -d -v {address} 2>&1', outfile='enum4linux-ng.txt') diff --git a/autorecon/default-plugins/get-arch.py b/autorecon/default-plugins/get-arch.py deleted file mode 100644 index e6ee411..0000000 --- a/autorecon/default-plugins/get-arch.py +++ /dev/null @@ -1,16 +0,0 @@ -from autorecon.plugins import ServiceScan - -class GetArch(ServiceScan): - - def __init__(self): - super().__init__() - self.name = 'get-arch' - self.tags = ['default', 'safe', 'rpc'] - - def configure(self): - self.match_service_name(['^msrpc']) - self.match_port('tcp', 135) - self.add_pattern(' is ((32|64)-bit)', description='Identified Architecture: {match1}') - - async def run(self, service): - await service.execute('impacket-getArch -target {address}', outfile='{protocol}_{port}_rpc_architecture.txt') diff --git a/autorecon/default-plugins/ldap-search.py b/autorecon/default-plugins/ldap-search.py deleted file mode 100644 index 527d1d8..0000000 --- a/autorecon/default-plugins/ldap-search.py +++ /dev/null @@ -1,16 +0,0 @@ -from autorecon.plugins import ServiceScan - -class LDAPSearch(ServiceScan): - - def __init__(self): - super().__init__() - self.name = 'LDAP Search' - self.tags = ['default', 'safe', 'ldap', 'active-directory'] - - def configure(self): - self.match_service_name('^ldap') - - def manual(self, service, plugin_was_run): - service.add_manual_command('ldapsearch command (modify before running):', [ - 'ldapsearch -x -D "" -w "" -H ldap://{address}:{port} -b "dc=example,dc=com" -s sub "(objectclass=*)" 2>&1 | tee > "{scandir}/{protocol}_{port}_ldap_all-entries.txt"' - ]) diff --git a/autorecon/default-plugins/lookup-sid.py b/autorecon/default-plugins/lookup-sid.py deleted file mode 100644 index 5c4bb4d..0000000 --- a/autorecon/default-plugins/lookup-sid.py +++ /dev/null @@ -1,16 +0,0 @@ -from autorecon.plugins import ServiceScan - -class LookupSID(ServiceScan): - - def __init__(self): - super().__init__() - self.name = 'lookupsid' - self.tags = ['default', 'safe', 'active-directory'] - - def configure(self): - self.match_service('tcp', 445, '^microsoft\-ds') - - def manual(self, service, plugin_was_run): - service.add_manual_command('Lookup SIDs', [ - 'impacket-lookupsid \'[username]:[password]@{address}\'' - ]) diff --git a/autorecon/default-plugins/nbtscan.py b/autorecon/default-plugins/nbtscan.py deleted file mode 100644 index 9036d02..0000000 --- a/autorecon/default-plugins/nbtscan.py +++ /dev/null @@ -1,17 +0,0 @@ -from autorecon.plugins import ServiceScan - -class NBTScan(ServiceScan): - - def __init__(self): - super().__init__() - self.name = 'nbtscan' - self.tags = ['default', 'safe', 'netbios', 'active-directory'] - - def configure(self): - self.match_service_name(['^smb', '^microsoft\-ds', '^netbios']) - self.match_port('udp', 137) - self.run_once(True) - - async def run(self, service): - if service.target.ipversion == 'IPv4': - await service.execute('nbtscan -rvh {ipaddress} 2>&1', outfile='nbtscan.txt') diff --git a/autorecon/default-plugins/nikto.py b/autorecon/default-plugins/nikto.py deleted file mode 100644 index b696cb5..0000000 --- a/autorecon/default-plugins/nikto.py +++ /dev/null @@ -1,16 +0,0 @@ -from autorecon.plugins import ServiceScan - -class Nikto(ServiceScan): - - def __init__(self): - super().__init__() - self.name = 'nikto' - self.tags = ['default', 'safe', 'long', 'http'] - - def configure(self): - self.match_service_name('^http') - self.match_service_name('^nacn_http$', negative_match=True) - - def manual(self, service, plugin_was_run): - if service.target.ipversion == 'IPv4': - service.add_manual_command('(nikto) old but generally reliable web server enumeration tool:', 'nikto -ask=no -h {http_scheme}://{address}:{port} 2>&1 | tee "{scandir}/{protocol}_{port}_{http_scheme}_nikto.txt"') diff --git a/autorecon/default-plugins/nmap-ajp.py b/autorecon/default-plugins/nmap-ajp.py deleted file mode 100644 index fcba5a0..0000000 --- a/autorecon/default-plugins/nmap-ajp.py +++ /dev/null @@ -1,14 +0,0 @@ -from autorecon.plugins import ServiceScan - -class NmapAJP(ServiceScan): - - def __init__(self): - super().__init__() - self.name = 'Nmap AJP' - self.tags = ['default', 'safe', 'ajp'] - - def configure(self): - self.match_service_name(['^ajp13']) - - async def run(self, service): - await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,(ajp-* or ssl*) and not (brute or broadcast or dos or external or fuzzer)" -oN "{scandir}/{protocol}_{port}_ajp_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_ajp_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-cassandra.py b/autorecon/default-plugins/nmap-cassandra.py deleted file mode 100644 index 54778a3..0000000 --- a/autorecon/default-plugins/nmap-cassandra.py +++ /dev/null @@ -1,14 +0,0 @@ -from autorecon.plugins import ServiceScan - -class NmapCassandra(ServiceScan): - - def __init__(self): - super().__init__() - self.name = "Nmap Cassandra" - self.tags = ['default', 'safe', 'cassandra'] - - def configure(self): - self.match_service_name('^apani1') - - async def run(self, service): - await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,(cassandra* or ssl*) and not (brute or broadcast or dos or external or fuzzer)" -oN "{scandir}/{protocol}_{port}_cassandra_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_cassandra_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-cups.py b/autorecon/default-plugins/nmap-cups.py deleted file mode 100644 index d8d532f..0000000 --- a/autorecon/default-plugins/nmap-cups.py +++ /dev/null @@ -1,14 +0,0 @@ -from autorecon.plugins import ServiceScan - -class NmapCUPS(ServiceScan): - - def __init__(self): - super().__init__() - self.name = "Nmap CUPS" - self.tags = ['default', 'safe', 'cups'] - - def configure(self): - self.match_service_name('^ipp') - - async def run(self, service): - await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,(cups* or ssl*) and not (brute or broadcast or dos or external or fuzzer)" -oN "{scandir}/{protocol}_{port}_cups_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_cups_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-distccd.py b/autorecon/default-plugins/nmap-distccd.py deleted file mode 100644 index ecf99c0..0000000 --- a/autorecon/default-plugins/nmap-distccd.py +++ /dev/null @@ -1,14 +0,0 @@ -from autorecon.plugins import ServiceScan - -class NmapDistccd(ServiceScan): - - def __init__(self): - super().__init__() - self.name = "Nmap distccd" - self.tags = ['default', 'safe', 'distccd'] - - def configure(self): - self.match_service_name('^distccd') - - async def run(self, service): - await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,distcc-cve2004-2687" --script-args="distcc-cve2004-2687.cmd=id" -oN "{scandir}/{protocol}_{port}_distcc_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_distcc_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-dns.py b/autorecon/default-plugins/nmap-dns.py deleted file mode 100644 index 479ac42..0000000 --- a/autorecon/default-plugins/nmap-dns.py +++ /dev/null @@ -1,14 +0,0 @@ -from autorecon.plugins import ServiceScan - -class NmapDNS(ServiceScan): - - def __init__(self): - super().__init__() - self.name = 'Nmap DNS' - self.tags = ['default', 'safe', 'dns'] - - def configure(self): - self.match_service_name('^domain') - - async def run(self, service): - await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,(dns* or ssl*) and not (brute or broadcast or dos or external or fuzzer)" -oN "{scandir}/{protocol}_{port}_dns_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_dns_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-finger.py b/autorecon/default-plugins/nmap-finger.py deleted file mode 100644 index 2f8d38c..0000000 --- a/autorecon/default-plugins/nmap-finger.py +++ /dev/null @@ -1,14 +0,0 @@ -from autorecon.plugins import ServiceScan - -class NmapFinger(ServiceScan): - - def __init__(self): - super().__init__() - self.name = "Nmap finger" - self.tags = ['default', 'safe', 'finger'] - - def configure(self): - self.match_service_name('^finger') - - async def run(self, service): - await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,finger" -oN "{scandir}/{protocol}_{port}_finger_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_finger_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-ftp.py b/autorecon/default-plugins/nmap-ftp.py deleted file mode 100644 index ea87573..0000000 --- a/autorecon/default-plugins/nmap-ftp.py +++ /dev/null @@ -1,14 +0,0 @@ -from autorecon.plugins import ServiceScan - -class NmapFTP(ServiceScan): - - def __init__(self): - super().__init__() - self.name = 'Nmap FTP' - self.tags = ['default', 'safe', 'ftp'] - - def configure(self): - self.match_service_name(['^ftp', '^ftp\-data']) - - async def run(self, service): - await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,(ftp* or ssl*) and not (brute or broadcast or dos or external or fuzzer)" -oN "{scandir}/{protocol}_{port}_ftp_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_ftp_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-http.py b/autorecon/default-plugins/nmap-http.py deleted file mode 100644 index 0dbeb69..0000000 --- a/autorecon/default-plugins/nmap-http.py +++ /dev/null @@ -1,17 +0,0 @@ -from autorecon.plugins import ServiceScan - -class NmapHTTP(ServiceScan): - - def __init__(self): - super().__init__() - self.name = "Nmap HTTP" - self.tags = ['default', 'safe', 'http'] - - def configure(self): - self.match_service_name('^http') - self.match_service_name('^nacn_http$', negative_match=True) - self.add_pattern('Server: ([^\n]+)', description='Identified HTTP Server: {match1}') - self.add_pattern('WebDAV is ENABLED', description='WebDAV is enabled') - - async def run(self, service): - await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,(http* or ssl*) and not (brute or broadcast or dos or external or http-slowloris* or fuzzer)" -oN "{scandir}/{protocol}_{port}_{http_scheme}_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_{http_scheme}_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-imap.py b/autorecon/default-plugins/nmap-imap.py deleted file mode 100644 index 95d1169..0000000 --- a/autorecon/default-plugins/nmap-imap.py +++ /dev/null @@ -1,14 +0,0 @@ -from autorecon.plugins import ServiceScan - -class NmapIMAP(ServiceScan): - - def __init__(self): - super().__init__() - self.name = "Nmap IMAP" - self.tags = ['default', 'safe', 'imap', 'email'] - - def configure(self): - self.match_service_name('^imap') - - async def run(self, service): - await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,(imap* or ssl*) and not (brute or broadcast or dos or external or fuzzer)" -oN "{scandir}/{protocol}_{port}_imap_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_imap_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-irc.py b/autorecon/default-plugins/nmap-irc.py deleted file mode 100644 index ebfbf45..0000000 --- a/autorecon/default-plugins/nmap-irc.py +++ /dev/null @@ -1,14 +0,0 @@ -from autorecon.plugins import ServiceScan - -class NmapIrc(ServiceScan): - - def __init__(self): - super().__init__() - self.name = 'Nmap IRC' - self.tags = ['default', 'safe', 'irc'] - - def configure(self): - self.match_service_name('^irc') - - async def run(self, service): - await service.execute('nmap {nmap_extra} -sV --script irc-botnet-channels,irc-info,irc-unrealircd-backdoor -oN "{scandir}/{protocol}_{port}_irc_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_irc_nmap.xml" -p {port} {address}') diff --git a/autorecon/default-plugins/nmap-kerberos.py b/autorecon/default-plugins/nmap-kerberos.py deleted file mode 100644 index 0830ff5..0000000 --- a/autorecon/default-plugins/nmap-kerberos.py +++ /dev/null @@ -1,17 +0,0 @@ -from autorecon.plugins import ServiceScan - -class NmapKerberos(ServiceScan): - - def __init__(self): - super().__init__() - self.name = "Nmap Kerberos" - self.tags = ['default', 'safe', 'kerberos', 'active-directory'] - - def configure(self): - self.match_service_name(['^kerberos', '^kpasswd']) - - async def run(self, service): - if self.get_global('domain') and self.get_global('username-wordlist'): - await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,krb5-enum-users" --script-args krb5-enum-users.realm="' + self.get_global('domain') + '",userdb="' + self.get_global('username-wordlist') + '" -oN "{scandir}/{protocol}_{port}_kerberos_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_kerberos_nmap.xml" {address}') - else: - await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,krb5-enum-users" -oN "{scandir}/{protocol}_{port}_kerberos_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_kerberos_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-ldap.py b/autorecon/default-plugins/nmap-ldap.py deleted file mode 100644 index 77aab20..0000000 --- a/autorecon/default-plugins/nmap-ldap.py +++ /dev/null @@ -1,14 +0,0 @@ -from autorecon.plugins import ServiceScan - -class NmapLDAP(ServiceScan): - - def __init__(self): - super().__init__() - self.name = "Nmap LDAP" - self.tags = ['default', 'safe', 'ldap', 'active-directory'] - - def configure(self): - self.match_service_name('^ldap') - - async def run(self, service): - await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,(ldap* or ssl*) and not (brute or broadcast or dos or external or fuzzer)" -oN "{scandir}/{protocol}_{port}_ldap_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_ldap_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-mongodb.py b/autorecon/default-plugins/nmap-mongodb.py deleted file mode 100644 index 833c628..0000000 --- a/autorecon/default-plugins/nmap-mongodb.py +++ /dev/null @@ -1,14 +0,0 @@ -from autorecon.plugins import ServiceScan - -class NmapMongoDB(ServiceScan): - - def __init__(self): - super().__init__() - self.name = "Nmap MongoDB" - self.tags = ['default', 'safe', 'databases'] - - def configure(self): - self.match_service_name('^mongod') - - async def run(self, service): - await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,(mongodb* or ssl*) and not (brute or broadcast or dos or external or fuzzer)" -oN "{scandir}/{protocol}_{port}_mongodb_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_mongodb_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-mountd.py b/autorecon/default-plugins/nmap-mountd.py deleted file mode 100644 index 848a77a..0000000 --- a/autorecon/default-plugins/nmap-mountd.py +++ /dev/null @@ -1,14 +0,0 @@ -from autorecon.plugins import ServiceScan - -class NmapMountd(ServiceScan): - - def __init__(self): - super().__init__() - self.name = "Nmap Mountd" - self.tags = ['default', 'safe', 'nfs'] - - def configure(self): - self.match_service_name('^mountd') - - async def run(self, service): - await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,nfs* and not (brute or broadcast or dos or external or fuzzer)" -oN "{scandir}/{protocol}_{port}_mountd_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_mountd_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-msrpc.py b/autorecon/default-plugins/nmap-msrpc.py deleted file mode 100644 index e374412..0000000 --- a/autorecon/default-plugins/nmap-msrpc.py +++ /dev/null @@ -1,14 +0,0 @@ -from autorecon.plugins import ServiceScan - -class NmapRPC(ServiceScan): - - def __init__(self): - super().__init__() - self.name = "Nmap MSRPC" - self.tags = ['default', 'rpc'] - - def configure(self): - self.match_service_name(['^msrpc', '^rpcbind', '^erpc']) - - async def run(self, service): - await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,msrpc-enum,rpc-grind,rpcinfo" -oN "{scandir}/{protocol}_{port}_rpc_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_rpc_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-mssql.py b/autorecon/default-plugins/nmap-mssql.py deleted file mode 100644 index 6e55d45..0000000 --- a/autorecon/default-plugins/nmap-mssql.py +++ /dev/null @@ -1,18 +0,0 @@ -from autorecon.plugins import ServiceScan - -class NmapMSSQL(ServiceScan): - - def __init__(self): - super().__init__() - self.name = "Nmap MSSQL" - self.tags = ['default', 'safe', 'databases'] - - def configure(self): - self.match_service_name(['^mssql', '^ms\-sql']) - - def manual(self, service, plugin_was_run): - if service.target.ipversion == 'IPv4': - service.add_manual_command('(sqsh) interactive database shell:', 'sqsh -U -P -S {address}:{port}') - - async def run(self, service): - await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,(ms-sql* or ssl*) and not (brute or broadcast or dos or external or fuzzer)" --script-args="mssql.instance-port={port},mssql.username=sa,mssql.password=sa" -oN "{scandir}/{protocol}_{port}_mssql_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_mssql_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-multicast-dns.py b/autorecon/default-plugins/nmap-multicast-dns.py deleted file mode 100644 index 1edb391..0000000 --- a/autorecon/default-plugins/nmap-multicast-dns.py +++ /dev/null @@ -1,14 +0,0 @@ -from autorecon.plugins import ServiceScan - -class NmapMulticastDNS(ServiceScan): - - def __init__(self): - super().__init__() - self.name = 'Nmap Multicast DNS' - self.tags = ['default', 'safe', 'dns'] - - def configure(self): - self.match_service_name(['^mdns', '^zeroconf']) - - async def run(self, service): - await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,(dns* or ssl*) and not (brute or broadcast or dos or external or fuzzer)" -oN "{scandir}/{protocol}_{port}_multicastdns_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_multicastdns_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-mysql.py b/autorecon/default-plugins/nmap-mysql.py deleted file mode 100644 index 68a01d5..0000000 --- a/autorecon/default-plugins/nmap-mysql.py +++ /dev/null @@ -1,18 +0,0 @@ -from autorecon.plugins import ServiceScan - -class NmapMYSQL(ServiceScan): - - def __init__(self): - super().__init__() - self.name = "Nmap MYSQL" - self.tags = ['default', 'safe', 'databases'] - - def configure(self): - self.match_service_name('^mysql') - - def manual(self, service, plugin_was_run): - if service.target.ipversion == 'IPv4': - service.add_manual_command('(sqsh) interactive database shell:', 'sqsh -U -P -S {address}:{port}') - - async def run(self, service): - await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,(mysql* or ssl*) and not (brute or broadcast or dos or external or fuzzer)" -oN "{scandir}/{protocol}_{port}_mysql_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_mysql_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-nfs.py b/autorecon/default-plugins/nmap-nfs.py deleted file mode 100644 index b8fabce..0000000 --- a/autorecon/default-plugins/nmap-nfs.py +++ /dev/null @@ -1,14 +0,0 @@ -from autorecon.plugins import ServiceScan - -class NmapNFS(ServiceScan): - - def __init__(self): - super().__init__() - self.name = "Nmap NFS" - self.tags = ['default', 'safe', 'nfs'] - - def configure(self): - self.match_service_name(['^nfs', '^rpcbind']) - - async def run(self, service): - await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,(rpcinfo or nfs*) and not (brute or broadcast or dos or external or fuzzer)" -oN "{scandir}/{protocol}_{port}_nfs_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_nfs_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-nntp.py b/autorecon/default-plugins/nmap-nntp.py deleted file mode 100644 index 1c7db5b..0000000 --- a/autorecon/default-plugins/nmap-nntp.py +++ /dev/null @@ -1,14 +0,0 @@ -from autorecon.plugins import ServiceScan - -class NmapNNTP(ServiceScan): - - def __init__(self): - super().__init__() - self.name = "Nmap NNTP" - self.tags = ['default', 'safe', 'nntp'] - - def configure(self): - self.match_service_name('^nntp') - - async def run(self, service): - await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,nntp-ntlm-info" -oN "{scandir}/{protocol}_{port}_nntp_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_nntp_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-ntp.py b/autorecon/default-plugins/nmap-ntp.py deleted file mode 100644 index d04679e..0000000 --- a/autorecon/default-plugins/nmap-ntp.py +++ /dev/null @@ -1,14 +0,0 @@ -from autorecon.plugins import ServiceScan - -class NmapNTP(ServiceScan): - - def __init__(self): - super().__init__() - self.name = "Nmap NTP" - self.tags = ['default', 'safe', 'ntp'] - - def configure(self): - self.match_service_name('^ntp') - - async def run(self, service): - await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,(ntp* or ssl*) and not (brute or broadcast or dos or external or fuzzer)" -oN "{scandir}/{protocol}_{port}_ntp_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_ntp_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-oracle.py b/autorecon/default-plugins/nmap-oracle.py deleted file mode 100644 index d8ff6bd..0000000 --- a/autorecon/default-plugins/nmap-oracle.py +++ /dev/null @@ -1,17 +0,0 @@ -from autorecon.plugins import ServiceScan - -class NmapOracle(ServiceScan): - - def __init__(self): - super().__init__() - self.name = "Nmap Oracle" - self.tags = ['default', 'safe', 'databases'] - - def configure(self): - self.match_service_name('^oracle') - - def manual(self, service, plugin_was_run): - service.add_manual_command('Brute-force SIDs using Nmap:', 'nmap {nmap_extra} -sV -p {port} --script="banner,oracle-sid-brute" -oN "{scandir}/{protocol}_{port}_oracle_sid-brute_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_oracle_sid-brute_nmap.xml" {address}') - - async def run(self, service): - await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,(oracle* or ssl*) and not (brute or broadcast or dos or external or fuzzer)" -oN "{scandir}/{protocol}_{port}_oracle_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_oracle_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-pop3.py b/autorecon/default-plugins/nmap-pop3.py deleted file mode 100644 index f4ed3a6..0000000 --- a/autorecon/default-plugins/nmap-pop3.py +++ /dev/null @@ -1,14 +0,0 @@ -from autorecon.plugins import ServiceScan - -class NmapPOP3(ServiceScan): - - def __init__(self): - super().__init__() - self.name = "Nmap POP3" - self.tags = ['default', 'safe', 'pop3', 'email'] - - def configure(self): - self.match_service_name('^pop3') - - async def run(self, service): - await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,(pop3* or ssl*) and not (brute or broadcast or dos or external or fuzzer)" -oN "{scandir}/{protocol}_{port}_pop3_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_pop3_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-rdp.py b/autorecon/default-plugins/nmap-rdp.py deleted file mode 100644 index 13a16f6..0000000 --- a/autorecon/default-plugins/nmap-rdp.py +++ /dev/null @@ -1,14 +0,0 @@ -from autorecon.plugins import ServiceScan - -class NmapRDP(ServiceScan): - - def __init__(self): - super().__init__() - self.name = "Nmap RDP" - self.tags = ['default', 'safe', 'rdp'] - - def configure(self): - self.match_service_name(['^rdp', '^ms\-wbt\-server', '^ms\-term\-serv']) - - async def run(self, service): - await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,(rdp* or ssl*) and not (brute or broadcast or dos or external or fuzzer)" -oN "{scandir}/{protocol}_{port}_rdp_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_rdp_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-redis.py b/autorecon/default-plugins/nmap-redis.py deleted file mode 100644 index 46fa920..0000000 --- a/autorecon/default-plugins/nmap-redis.py +++ /dev/null @@ -1,14 +0,0 @@ -from autorecon.plugins import ServiceScan - -class NmapRedis(ServiceScan): - - def __init__(self): - super().__init__() - self.name = 'Nmap Redis' - self.tags = ['default', 'safe', 'redis'] - - def configure(self): - self.match_service_name('^redis$') - - async def run(self, service): - await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,redis-info" -oN "{scandir}/{protocol}_{port}_redis_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_redis_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-rmi.py b/autorecon/default-plugins/nmap-rmi.py deleted file mode 100644 index 7c1d277..0000000 --- a/autorecon/default-plugins/nmap-rmi.py +++ /dev/null @@ -1,14 +0,0 @@ -from autorecon.plugins import ServiceScan - -class NmapRMI(ServiceScan): - - def __init__(self): - super().__init__() - self.name = "Nmap RMI" - self.tags = ['default', 'safe', 'rmi'] - - def configure(self): - self.match_service_name(['^java\-rmi', '^rmiregistry']) - - async def run(self, service): - await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,rmi-vuln-classloader,rmi-dumpregistry" -oN "{scandir}/{protocol}_{port}_rmi_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_rmi_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-rsync.py b/autorecon/default-plugins/nmap-rsync.py deleted file mode 100644 index 3e8251d..0000000 --- a/autorecon/default-plugins/nmap-rsync.py +++ /dev/null @@ -1,14 +0,0 @@ -from autorecon.plugins import ServiceScan - -class NmapRsync(ServiceScan): - - def __init__(self): - super().__init__() - self.name = 'Nmap Rsync' - self.tags = ['default', 'safe', 'rsync'] - - def configure(self): - self.match_service_name('^rsync') - - async def run(self, service): - await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,(rsync* or ssl*) and not (brute or broadcast or dos or external or fuzzer)" -oN "{scandir}/{protocol}_{port}_rsync_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_rsync_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-sip.py b/autorecon/default-plugins/nmap-sip.py deleted file mode 100644 index 837b059..0000000 --- a/autorecon/default-plugins/nmap-sip.py +++ /dev/null @@ -1,14 +0,0 @@ -from autorecon.plugins import ServiceScan - -class NmapSIP(ServiceScan): - - def __init__(self): - super().__init__() - self.name = "Nmap SIP" - self.tags = ['default', 'safe', 'sip'] - - def configure(self): - self.match_service_name(['^asterisk', '^sip']) - - async def run(self, service): - await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,sip-enum-users,sip-methods" -oN "{scandir}/{protocol}_{port}_sip_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_sip_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-smb.py b/autorecon/default-plugins/nmap-smb.py deleted file mode 100644 index 5f9bb52..0000000 --- a/autorecon/default-plugins/nmap-smb.py +++ /dev/null @@ -1,14 +0,0 @@ -from autorecon.plugins import ServiceScan - -class NmapSMB(ServiceScan): - - def __init__(self): - super().__init__() - self.name = "Nmap SMB" - self.tags = ['default', 'safe', 'smb', 'active-directory'] - - def configure(self): - self.match_service_name(['^smb', '^microsoft\-ds', '^netbios']) - - async def run(self, service): - await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,(nbstat or smb* or ssl*) and not (brute or broadcast or dos or external or fuzzer)" -oN "{scandir}/{protocol}_{port}_smb_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_smb_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-smtp.py b/autorecon/default-plugins/nmap-smtp.py deleted file mode 100644 index 962d87c..0000000 --- a/autorecon/default-plugins/nmap-smtp.py +++ /dev/null @@ -1,14 +0,0 @@ -from autorecon.plugins import ServiceScan - -class NmapSMTP(ServiceScan): - - def __init__(self): - super().__init__() - self.name = "Nmap SMTP" - self.tags = ['default', 'safe', 'smtp', 'email'] - - def configure(self): - self.match_service_name('^smtp') - - async def run(self, service): - await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,(smtp* or ssl*) and not (brute or broadcast or dos or external or fuzzer)" -oN "{scandir}/{protocol}_{port}_smtp_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_smtp_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-snmp.py b/autorecon/default-plugins/nmap-snmp.py deleted file mode 100644 index 29305f0..0000000 --- a/autorecon/default-plugins/nmap-snmp.py +++ /dev/null @@ -1,14 +0,0 @@ -from autorecon.plugins import ServiceScan - -class NmapSNMP(ServiceScan): - - def __init__(self): - super().__init__() - self.name = "Nmap SNMP" - self.tags = ['default', 'safe', 'snmp'] - - def configure(self): - self.match_service_name('^snmp') - - async def run(self, service): - await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,(snmp* or ssl*) and not (brute or broadcast or dos or external or fuzzer)" -oN "{scandir}/{protocol}_{port}_snmp-nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_snmp_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-ssh.py b/autorecon/default-plugins/nmap-ssh.py deleted file mode 100644 index 6c2acda..0000000 --- a/autorecon/default-plugins/nmap-ssh.py +++ /dev/null @@ -1,14 +0,0 @@ -from autorecon.plugins import ServiceScan - -class NmapSSH(ServiceScan): - - def __init__(self): - super().__init__() - self.name = "Nmap SSH" - self.tags = ['default', 'safe', 'ssh'] - - def configure(self): - self.match_service_name('^ssh') - - async def run(self, service): - await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,ssh2-enum-algos,ssh-hostkey,ssh-auth-methods" -oN "{scandir}/{protocol}_{port}_ssh_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_ssh_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-telnet.py b/autorecon/default-plugins/nmap-telnet.py deleted file mode 100644 index c989d82..0000000 --- a/autorecon/default-plugins/nmap-telnet.py +++ /dev/null @@ -1,14 +0,0 @@ -from autorecon.plugins import ServiceScan - -class NmapTelnet(ServiceScan): - - def __init__(self): - super().__init__() - self.name = 'Nmap Telnet' - self.tags = ['default', 'safe', 'telnet'] - - def configure(self): - self.match_service_name('^telnet') - - async def run(self, service): - await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,telnet-encryption,telnet-ntlm-info" -oN "{scandir}/{protocol}_{port}_telnet-nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_telnet_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-tftp.py b/autorecon/default-plugins/nmap-tftp.py deleted file mode 100644 index c0c0994..0000000 --- a/autorecon/default-plugins/nmap-tftp.py +++ /dev/null @@ -1,14 +0,0 @@ -from autorecon.plugins import ServiceScan - -class NmapTFTP(ServiceScan): - - def __init__(self): - super().__init__() - self.name = 'Nmap TFTP' - self.tags = ['default', 'safe', 'tftp'] - - def configure(self): - self.match_service_name('^tftp') - - async def run(self, service): - await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,tftp-enum" -oN "{scandir}/{protocol}_{port}_tftp-nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_tftp_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-vnc.py b/autorecon/default-plugins/nmap-vnc.py deleted file mode 100644 index 806a8ff..0000000 --- a/autorecon/default-plugins/nmap-vnc.py +++ /dev/null @@ -1,14 +0,0 @@ -from autorecon.plugins import ServiceScan - -class NmapVNC(ServiceScan): - - def __init__(self): - super().__init__() - self.name = 'Nmap VNC' - self.tags = ['default', 'safe', 'vnc'] - - def configure(self): - self.match_service_name('^vnc') - - async def run(self, service): - await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,(vnc* or realvnc* or ssl*) and not (brute or broadcast or dos or external or fuzzer)" --script-args="unsafe=1" -oN "{scandir}/{protocol}_{port}_vnc_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_vnc_nmap.xml" {address}') diff --git a/autorecon/default-plugins/onesixtyone.py b/autorecon/default-plugins/onesixtyone.py deleted file mode 100644 index e99d621..0000000 --- a/autorecon/default-plugins/onesixtyone.py +++ /dev/null @@ -1,18 +0,0 @@ -from autorecon.plugins import ServiceScan - -class OneSixtyOne(ServiceScan): - - def __init__(self): - super().__init__() - self.name = "OneSixtyOne" - self.tags = ['default', 'safe', 'snmp'] - - def configure(self): - self.match_service_name('^snmp') - self.match_port('udp', 161) - self.run_once(True) - self.add_option('community-strings', default='/usr/share/seclists/Discovery/SNMP/common-snmp-community-strings-onesixtyone.txt', help='The file containing a list of community strings to try. Default: %(default)s') - - async def run(self, service): - if service.target.ipversion == 'IPv4': - await service.execute('onesixtyone -c ' + self.get_option('community-strings') + ' -dd {address} 2>&1', outfile='{protocol}_{port}_snmp_onesixtyone.txt') diff --git a/autorecon/default-plugins/oracle-odat.py b/autorecon/default-plugins/oracle-odat.py deleted file mode 100644 index ac4613f..0000000 --- a/autorecon/default-plugins/oracle-odat.py +++ /dev/null @@ -1,21 +0,0 @@ -from autorecon.plugins import ServiceScan - -class OracleODAT(ServiceScan): - - def __init__(self): - super().__init__() - self.name = "Oracle ODAT" - self.tags = ['default', 'safe', 'databases'] - - def configure(self): - self.match_service_name('^oracle') - - def manual(self, service, plugin_was_run): - service.add_manual_commands('Install ODAT (https://github.com/quentinhardy/odat) and run the following commands:', [ - 'python odat.py tnscmd -s {address} -p {port} --ping', - 'python odat.py tnscmd -s {address} -p {port} --version', - 'python odat.py tnscmd -s {address} -p {port} --status', - 'python odat.py sidguesser -s {address} -p {port}', - 'python odat.py passwordguesser -s {address} -p {port} -d --accounts-file accounts/accounts_multiple.txt', - 'python odat.py tnspoison -s {address} -p {port} -d --test-module' - ]) diff --git a/autorecon/default-plugins/oracle-patator.py b/autorecon/default-plugins/oracle-patator.py deleted file mode 100644 index 594b531..0000000 --- a/autorecon/default-plugins/oracle-patator.py +++ /dev/null @@ -1,14 +0,0 @@ -from autorecon.plugins import ServiceScan - -class OraclePatator(ServiceScan): - - def __init__(self): - super().__init__() - self.name = "Oracle Patator" - self.tags = ['default', 'databases'] - - def configure(self): - self.match_service_name('^oracle') - - def manual(self, service, plugin_was_run): - service.add_manual_command('Install Oracle Instant Client (https://github.com/rapid7/metasploit-framework/wiki/How-to-get-Oracle-Support-working-with-Kali-Linux) and then bruteforce with patator:', 'patator oracle_login host={address} port={port} user=COMBO00 password=COMBO01 0=/usr/share/seclists/Passwords/Default-Credentials/oracle-betterdefaultpasslist.txt -x ignore:code=ORA-01017 -x ignore:code=ORA-28000') diff --git a/autorecon/default-plugins/oracle-scanner.py b/autorecon/default-plugins/oracle-scanner.py deleted file mode 100644 index 16653cc..0000000 --- a/autorecon/default-plugins/oracle-scanner.py +++ /dev/null @@ -1,20 +0,0 @@ -from autorecon.plugins import ServiceScan -from shutil import which - -class OracleScanner(ServiceScan): - - def __init__(self): - super().__init__() - self.name = "Oracle Scanner" - self.tags = ['default', 'safe', 'databases'] - - def configure(self): - self.match_service_name('^oracle') - - def check(self): - if which('oscanner') is None: - self.error('The oscanner program could not be found. Make sure it is installed. (On Kali, run: sudo apt install oscanner)') - return False - - async def run(self, service): - await service.execute('oscanner -v -s {address} -P {port} 2>&1', outfile='{protocol}_{port}_oracle_scanner.txt') diff --git a/autorecon/default-plugins/oracle-tnscmd.py b/autorecon/default-plugins/oracle-tnscmd.py deleted file mode 100644 index 7ea12c1..0000000 --- a/autorecon/default-plugins/oracle-tnscmd.py +++ /dev/null @@ -1,22 +0,0 @@ -from autorecon.plugins import ServiceScan -from shutil import which - -class OracleTNScmd(ServiceScan): - - def __init__(self): - super().__init__() - self.name = "Oracle TNScmd" - self.tags = ['default', 'safe', 'databases'] - - def configure(self): - self.match_service_name('^oracle') - - def check(self): - if which('tnscmd10g') is None: - self.error('The tnscmd10g program could not be found. Make sure it is installed. (On Kali, run: sudo apt install tnscmd10g)') - return False - - async def run(self, service): - if service.target.ipversion == 'IPv4': - await service.execute('tnscmd10g ping -h {address} -p {port} 2>&1', outfile='{protocol}_{port}_oracle_tnscmd_ping.txt') - await service.execute('tnscmd10g version -h {address} -p {port} 2>&1', outfile='{protocol}_{port}_oracle_tnscmd_version.txt') diff --git a/autorecon/default-plugins/portscan-all-tcp-ports.py b/autorecon/default-plugins/portscan-all-tcp-ports.py deleted file mode 100644 index c6dc70e..0000000 --- a/autorecon/default-plugins/portscan-all-tcp-ports.py +++ /dev/null @@ -1,52 +0,0 @@ -from autorecon.plugins import PortScan -from autorecon.config import config -import re, requests - -class AllTCPPortScan(PortScan): - - def __init__(self): - super().__init__() - self.name = 'All TCP Ports' - self.description = 'Performs an Nmap scan of all TCP ports.' - self.type = 'tcp' - self.specific_ports = True - self.tags = ['default', 'default-port-scan', 'long'] - - async def run(self, target): - if config['proxychains']: - traceroute_os = '' - else: - traceroute_os = ' -A --osscan-guess' - - if target.ports: - if target.ports['tcp']: - process, stdout, stderr = await target.execute('nmap {nmap_extra} -sV -sC --version-all' + traceroute_os + ' -p ' + target.ports['tcp'] + ' -oN "{scandir}/_full_tcp_nmap.txt" -oX "{scandir}/xml/_full_tcp_nmap.xml" {address}', blocking=False) - else: - return [] - else: - process, stdout, stderr = await target.execute('nmap {nmap_extra} -sV -sC --version-all' + traceroute_os + ' -p- -oN "{scandir}/_full_tcp_nmap.txt" -oX "{scandir}/xml/_full_tcp_nmap.xml" {address}', blocking=False) - services = [] - while True: - line = await stdout.readline() - if line is not None: - match = re.search('^Discovered open port ([0-9]+)/tcp', line) - if match: - target.info('Discovered open port {bmagenta}tcp/' + match.group(1) + '{rst} on {byellow}' + target.address + '{rst}', verbosity=1) - service = target.extract_service(line) - - if service: - # Check if HTTP service appears to be WinRM. If so, override service name as wsman. - if service.name == 'http' and service.port in [5985, 5986]: - wsman = requests.get(('https' if service.secure else 'http') + '://' + target.address + ':' + str(service.port) + '/wsman', verify=False) - if wsman.status_code == 405: - service.name = 'wsman' - wsman = requests.post(('https' if service.secure else 'http') + '://' + target.address + ':' + str(service.port) + '/wsman', verify=False) - else: - if wsman.status_code == 401: - service.name = 'wsman' - - services.append(service) - else: - break - await process.wait() - return services diff --git a/autorecon/default-plugins/portscan-guess-tcp-ports.py b/autorecon/default-plugins/portscan-guess-tcp-ports.py deleted file mode 100644 index 1919fff..0000000 --- a/autorecon/default-plugins/portscan-guess-tcp-ports.py +++ /dev/null @@ -1,48 +0,0 @@ -from autorecon.plugins import PortScan -from autorecon.targets import Service -import re - -class GuessPortScan(PortScan): - - def __init__(self): - super().__init__() - self.name = 'Guess TCP Ports' - self.type = 'tcp' - self.description = 'Performs an Nmap scan of the all TCP ports but guesses services based off the port found. Can be quicker. Proper service matching is performed at the end of the scan.' - self.tags = ['guess-port-scan', 'long'] - self.priority = 0 - - async def run(self, target): - if target.ports: - if target.ports['tcp']: - process, stdout, stderr = await target.execute('nmap {nmap_extra} -A --osscan-guess --version-all -p ' + target.ports['tcp'] + ' -oN "{scandir}/_custom_ports_tcp_nmap.txt" -oX "{scandir}/xml/_custom_ports_tcp_nmap.xml" {address}', blocking=False) - else: - return [] - else: - process, stdout, stderr = await target.execute('nmap {nmap_extra} -A --osscan-guess --version-all -p- -oN "{scandir}/_quick_tcp_nmap.txt" -oX "{scandir}/xml/_quick_tcp_nmap.xml" {address}', blocking=False) - - insecure_ports = { - '20':'ftp', '21':'ftp', '22':'ssh', '23':'telnet', '25':'smtp', '53':'domain', '69':'tftp', '79':'finger', '80':'http', '88':'kerberos', '109':'pop3', '110':'pop3', '111':'rpcbind', '119':'nntp', '135':'msrpc', '139':'netbios-ssn', '143':'imap', '161':'snmp', '220':'imap', '389':'ldap', '433':'nntp', '445':'smb', '587':'smtp', '631':'ipp', '873':'rsync', '1098':'java-rmi', '1099':'java-rmi', '1433':'mssql', '1521':'oracle', '2049':'nfs', '2483':'oracle', '3020':'smb', '3306':'mysql', '3389':'rdp', '3632':'distccd', '5060':'asterisk', '5500':'vnc', '5900':'vnc', '5985':'wsman', '6379':'redis', '8080':'http-proxy', '27017':'mongod', '27018':'mongod', '27019':'mongod' - } - secure_ports = { - '443':'https', '465':'smtp', '563':'nntp', '585':'imaps', '593':'msrpc', '636':'ldap', '989':'ftp', '990':'ftp', '992':'telnet', '993':'imaps', '995':'pop3s', '2484':'oracle', '5061':'asterisk', '5986':'wsman' - } - - services = [] - while True: - line = await stdout.readline() - if line is not None: - match = re.match('^Discovered open port ([0-9]+)/tcp', line) - if match: - if match.group(1) in insecure_ports.keys(): - await target.add_service(Service('tcp', match.group(1), insecure_ports[match.group(1)])) - elif match.group(1) in secure_ports.keys(): - await target.add_service(Service('tcp', match.group(1), secure_ports[match.group(1)], True)) - service = target.extract_service(line) - if service is not None: - services.append(service) - else: - break - - await process.wait() - return services diff --git a/autorecon/default-plugins/portscan-top-100-udp-ports.py b/autorecon/default-plugins/portscan-top-100-udp-ports.py deleted file mode 100644 index 7f28de3..0000000 --- a/autorecon/default-plugins/portscan-top-100-udp-ports.py +++ /dev/null @@ -1,40 +0,0 @@ -from autorecon.plugins import PortScan -from autorecon.config import config -import os, re - -class Top100UDPPortScan(PortScan): - - def __init__(self): - super().__init__() - self.name = 'Top 100 UDP Ports' - self.description = 'Performs an Nmap scan of the top 100 UDP ports.' - self.type = 'udp' - self.specific_ports = True - self.tags = ['default', 'default-port-scan', 'long'] - - async def run(self, target): - # Only run UDP scan if user is root. - if os.getuid() == 0 or config['disable_sanity_checks']: - if target.ports: - if target.ports['udp']: - process, stdout, stderr = await target.execute('nmap {nmap_extra} -sU -A --osscan-guess -p ' + target.ports['udp'] + ' -oN "{scandir}/_custom_ports_udp_nmap.txt" -oX "{scandir}/xml/_custom_ports_udp_nmap.xml" {address}', blocking=False) - else: - return [] - else: - process, stdout, stderr = await target.execute('nmap {nmap_extra} -sU -A --top-ports 100 -oN "{scandir}/_top_100_udp_nmap.txt" -oX "{scandir}/xml/_top_100_udp_nmap.xml" {address}', blocking=False) - services = [] - while True: - line = await stdout.readline() - if line is not None: - match = re.search('^Discovered open port ([0-9]+)/udp', line) - if match: - target.info('Discovered open port {bmagenta}udp/' + match.group(1) + '{rst} on {byellow}' + target.address + '{rst}', verbosity=1) - service = target.extract_service(line) - if service: - services.append(service) - else: - break - await process.wait() - return services - else: - target.error('UDP scan requires AutoRecon be run with root privileges.') diff --git a/autorecon/default-plugins/redis-cli.py b/autorecon/default-plugins/redis-cli.py deleted file mode 100644 index 74b3803..0000000 --- a/autorecon/default-plugins/redis-cli.py +++ /dev/null @@ -1,24 +0,0 @@ -from autorecon.plugins import ServiceScan -from shutil import which - -class RedisCli(ServiceScan): - - def __init__(self): - super().__init__() - self.name = 'Redis Cli' - self.tags = ['default', 'safe', 'redis'] - - def configure(self): - self.match_service_name('^redis$') - - def check(self): - if which('redis-cli') is None: - self.error('The redis-cli program could not be found. Make sure it is installed. (On Kali, run: sudo apt install redis-tools)') - return False - - async def run(self, service): - if which('redis-cli') is not None: - _, stdout, _ = await service.execute('redis-cli -p {port} -h {address} INFO', outfile='{protocol}_{port}_redis_info.txt') - if not (await stdout.readline()).startswith('NOAUTH Authentication required'): - await service.execute('redis-cli -p {port} -h {address} CONFIG GET \'*\'', outfile='{protocol}_{port}_redis_config.txt') - await service.execute('redis-cli -p {port} -h {address} CLIENT LIST', outfile='{protocol}_{port}_redis_client-list.txt') diff --git a/autorecon/default-plugins/reporting-cherrytree.py b/autorecon/default-plugins/reporting-cherrytree.py deleted file mode 100644 index bd1d4d8..0000000 --- a/autorecon/default-plugins/reporting-cherrytree.py +++ /dev/null @@ -1,91 +0,0 @@ -from autorecon.plugins import Report -from autorecon.config import config -from xml.sax.saxutils import escape -import os, glob - -class CherryTree(Report): - - def __init__(self): - super().__init__() - self.name = 'CherryTree' - self.tags = [] - - async def run(self, targets): - if len(targets) > 1: - report = os.path.join(config['output'], 'report.xml.ctd') - elif len(targets) == 1: - report = os.path.join(targets[0].reportdir, 'report.xml.ctd') - else: - return - - with open(report, 'w') as output: - output.writelines('\n\n') - for target in targets: - output.writelines('\n') - - files = [os.path.abspath(filename) for filename in glob.iglob(os.path.join(target.scandir, '**/*'), recursive=True) if os.path.isfile(filename) and filename.endswith(('.txt', '.html'))] - - if target.scans['ports']: - output.writelines('\n') - for scan in target.scans['ports'].keys(): - if len(target.scans['ports'][scan]['commands']) > 0: - output.writelines('\n') - for command in target.scans['ports'][scan]['commands']: - output.writelines('' + escape(command[0])) - for filename in files: - if filename in command[0] or (command[1] is not None and filename == command[1]) or (command[2] is not None and filename == command[2]): - output.writelines('\n\n' + escape(filename) + ':\n\n') - with open(filename, 'r') as file: - output.writelines(escape(file.read()) + '\n') - output.writelines('\n') - output.writelines('\n') - output.writelines('\n') - if target.scans['services']: - output.writelines('\n') - for service in target.scans['services'].keys(): - output.writelines('\n') - for plugin in target.scans['services'][service].keys(): - if len(target.scans['services'][service][plugin]['commands']) > 0: - output.writelines('\n') - for command in target.scans['services'][service][plugin]['commands']: - output.writelines('' + escape(command[0])) - for filename in files: - if filename in command[0] or (command[1] is not None and filename == command[1]) or (command[2] is not None and filename == command[2]): - output.writelines('\n\n' + escape(filename) + ':\n\n') - with open(filename, 'r') as file: - output.writelines(escape(file.read()) + '\n') - output.writelines('\n') - output.writelines('\n') - output.writelines('\n') - output.writelines('\n') - - manual_commands = os.path.join(target.scandir, '_manual_commands.txt') - if os.path.isfile(manual_commands): - output.writelines('\n') - with open(manual_commands, 'r') as file: - output.writelines('' + escape(file.read()) + '\n') - output.writelines('\n') - - patterns = os.path.join(target.scandir, '_patterns.log') - if os.path.isfile(patterns): - output.writelines('\n') - with open(patterns, 'r') as file: - output.writelines('' + escape(file.read()) + '\n') - output.writelines('\n') - - commands = os.path.join(target.scandir, '_commands.log') - if os.path.isfile(commands): - output.writelines('\n') - with open(commands, 'r') as file: - output.writelines('' + escape(file.read()) + '\n') - output.writelines('\n') - - errors = os.path.join(target.scandir, '_errors.log') - if os.path.isfile(errors): - output.writelines('\n') - with open(errors, 'r') as file: - output.writelines('' + escape(file.read()) + '\n') - output.writelines('\n') - output.writelines('\n') - - output.writelines('') diff --git a/autorecon/default-plugins/reporting-markdown.py b/autorecon/default-plugins/reporting-markdown.py deleted file mode 100644 index bba0330..0000000 --- a/autorecon/default-plugins/reporting-markdown.py +++ /dev/null @@ -1,75 +0,0 @@ -from autorecon.plugins import Report -from autorecon.config import config -import os, glob - -class Markdown(Report): - - def __init__(self): - super().__init__() - self.name = 'Markdown' - - async def run(self, targets): - if len(targets) > 1: - report = os.path.join(config['output'], 'report.md') - elif len(targets) == 1: - report = os.path.join(targets[0].reportdir, 'report.md') - else: - return - - os.makedirs(report, exist_ok=True) - - for target in targets: - os.makedirs(os.path.join(report, target.address), exist_ok=True) - - files = [os.path.abspath(filename) for filename in glob.iglob(os.path.join(target.scandir, '**/*'), recursive=True) if os.path.isfile(filename) and filename.endswith(('.txt', '.html'))] - - if target.scans['ports']: - os.makedirs(os.path.join(report, target.address, 'Port Scans'), exist_ok=True) - for scan in target.scans['ports'].keys(): - if len(target.scans['ports'][scan]['commands']) > 0: - with open(os.path.join(report, target.address, 'Port Scans', 'PortScan - ' + target.scans['ports'][scan]['plugin'].name + '.md'), 'w') as output: - for command in target.scans['ports'][scan]['commands']: - output.writelines('```bash\n' + command[0] + '\n```') - for filename in files: - if filename in command[0] or (command[1] is not None and filename == command[1]) or (command[2] is not None and filename == command[2]): - output.writelines('\n\n[' + filename + '](file://' + filename + '):\n\n') - with open(filename, 'r') as file: - output.writelines('```\n' + file.read() + '\n```\n') - if target.scans['services']: - os.makedirs(os.path.join(report, target.address, 'Services'), exist_ok=True) - for service in target.scans['services'].keys(): - os.makedirs(os.path.join(report, target.address, 'Services', 'Service - ' + service.tag().replace('/', '-')), exist_ok=True) - for plugin in target.scans['services'][service].keys(): - if len(target.scans['services'][service][plugin]['commands']) > 0: - with open(os.path.join(report, target.address, 'Services', 'Service - ' + service.tag().replace('/', '-'), target.scans['services'][service][plugin]['plugin'].name + '.md'), 'w') as output: - for command in target.scans['services'][service][plugin]['commands']: - output.writelines('```bash\n' + command[0] + '\n```') - for filename in files: - if filename in command[0] or (command[1] is not None and filename == command[1]) or (command[2] is not None and filename == command[2]): - output.writelines('\n\n[' + filename + '](file://' + filename + '):\n\n') - with open(filename, 'r') as file: - output.writelines('```\n' + file.read() + '\n```\n') - - manual_commands = os.path.join(target.scandir, '_manual_commands.txt') - if os.path.isfile(manual_commands): - with open(os.path.join(report, target.address, 'Manual Commands' + '.md'), 'w') as output: - with open(manual_commands, 'r') as file: - output.writelines('```bash\n' + file.read() + '\n```') - - patterns = os.path.join(target.scandir, '_patterns.log') - if os.path.isfile(patterns): - with open(os.path.join(report, target.address, 'Patterns' + '.md'), 'w') as output: - with open(patterns, 'r') as file: - output.writelines(file.read()) - - commands = os.path.join(target.scandir, '_commands.log') - if os.path.isfile(commands): - with open(os.path.join(report, target.address, 'Commands' + '.md'), 'w') as output: - with open(commands, 'r') as file: - output.writelines('```bash\n' + file.read() + '\n```') - - errors = os.path.join(target.scandir, '_errors.log') - if os.path.isfile(errors): - with open(os.path.join(report, target.address, 'Errors' + '.md'), 'w') as output: - with open(errors, 'r') as file: - output.writelines('```\n' + file.read() + '\n```') diff --git a/autorecon/default-plugins/rpcclient.py b/autorecon/default-plugins/rpcclient.py deleted file mode 100644 index 052b20a..0000000 --- a/autorecon/default-plugins/rpcclient.py +++ /dev/null @@ -1,14 +0,0 @@ -from autorecon.plugins import ServiceScan - -class RPCClient(ServiceScan): - - def __init__(self): - super().__init__() - self.name = "rpcclient" - self.tags = ['default', 'safe', 'rpc'] - - def configure(self): - self.match_service_name(['^msrpc', '^rpcbind', '^erpc']) - - def manual(self, service, plugin_was_run): - service.add_manual_command('RPC Client:', 'rpcclient -p {port} -U "" {address}') diff --git a/autorecon/default-plugins/rpcdump.py b/autorecon/default-plugins/rpcdump.py deleted file mode 100644 index 51aa3e7..0000000 --- a/autorecon/default-plugins/rpcdump.py +++ /dev/null @@ -1,16 +0,0 @@ -from autorecon.plugins import ServiceScan - -class RPCDump(ServiceScan): - - def __init__(self): - super().__init__() - self.name = 'rpcdump' - self.tags = ['default', 'safe', 'rpc'] - - def configure(self): - self.match_service_name(['^msrpc', '^rpcbind', '^erpc', '^ncacn_http$']) - self.match_port('tcp', [135, 139, 443, 445, 593]) - - async def run(self, service): - if service.protocol == 'tcp': - await service.execute('impacket-rpcdump -port {port} {address}', outfile='{protocol}_{port}_rpc_rpcdump.txt') diff --git a/autorecon/default-plugins/rsync-list-files.py b/autorecon/default-plugins/rsync-list-files.py deleted file mode 100644 index a058336..0000000 --- a/autorecon/default-plugins/rsync-list-files.py +++ /dev/null @@ -1,14 +0,0 @@ -from autorecon.plugins import ServiceScan - -class RsyncList(ServiceScan): - - def __init__(self): - super().__init__() - self.name = 'Rsync List Files' - self.tags = ['default', 'safe', 'rsync'] - - def configure(self): - self.match_service_name('^rsync') - - async def run(self, service): - await service.execute('rsync -av --list-only rsync://{addressv6}:{port}', outfile='{protocol}_{port}_rsync_file_list.txt') diff --git a/autorecon/default-plugins/showmount.py b/autorecon/default-plugins/showmount.py deleted file mode 100644 index 6b14951..0000000 --- a/autorecon/default-plugins/showmount.py +++ /dev/null @@ -1,14 +0,0 @@ -from autorecon.plugins import ServiceScan - -class Showmount(ServiceScan): - - def __init__(self): - super().__init__() - self.name = "showmount" - self.tags = ['default', 'safe', 'nfs'] - - def configure(self): - self.match_service_name(['^nfs', '^rpcbind']) - - async def run(self, service): - await service.execute('showmount -e {address} 2>&1', outfile='{protocol}_{port}_showmount.txt') diff --git a/autorecon/default-plugins/sipvicious.py b/autorecon/default-plugins/sipvicious.py deleted file mode 100644 index 86db374..0000000 --- a/autorecon/default-plugins/sipvicious.py +++ /dev/null @@ -1,15 +0,0 @@ -from autorecon.plugins import ServiceScan - -class SIPVicious(ServiceScan): - - def __init__(self): - super().__init__() - self.name = "SIPVicious" - self.tags = ['default', 'safe', 'sip'] - - def configure(self): - self.match_service_name(['^asterisk', '^sip']) - - def manual(self, service, plugin_was_run): - if service.target.ipversion == 'IPv4': - service.add_manual_command('svwar:', 'svwar -D -m INVITE -p {port} {address}') diff --git a/autorecon/default-plugins/smb-vuln.py b/autorecon/default-plugins/smb-vuln.py deleted file mode 100644 index d82ec6f..0000000 --- a/autorecon/default-plugins/smb-vuln.py +++ /dev/null @@ -1,18 +0,0 @@ -from autorecon.plugins import ServiceScan - -class SMBVuln(ServiceScan): - - def __init__(self): - super().__init__() - self.name = "SMB Vulnerabilities" - self.tags = ['unsafe', 'smb', 'active-directory'] - - def configure(self): - self.match_service_name(['^smb', '^microsoft\-ds', '^netbios']) - - async def run(self, service): - await service.execute('nmap {nmap_extra} -sV -p {port} --script="smb-vuln-*" --script-args="unsafe=1" -oN "{scandir}/{protocol}_{port}_smb_vulnerabilities.txt" -oX "{scandir}/xml/{protocol}_{port}_smb_vulnerabilities.xml" {address}') - - def manual(self, service, plugin_was_run): - if not plugin_was_run: # Only suggest these if they weren't run. - service.add_manual_commands('Nmap scans for SMB vulnerabilities that could potentially cause a DoS if scanned (according to Nmap). Be careful:', 'nmap {nmap_extra} -sV -p {port} --script="smb-vuln-* and dos" --script-args="unsafe=1" -oN "{scandir}/{protocol}_{port}_smb_vulnerabilities.txt" -oX "{scandir}/xml/{protocol}_{port}_smb_vulnerabilities.xml" {address}') diff --git a/autorecon/default-plugins/smbclient.py b/autorecon/default-plugins/smbclient.py deleted file mode 100644 index 64ad0df..0000000 --- a/autorecon/default-plugins/smbclient.py +++ /dev/null @@ -1,16 +0,0 @@ -from autorecon.plugins import ServiceScan - -class SMBClient(ServiceScan): - - def __init__(self): - super().__init__() - self.name = "SMBClient" - self.tags = ['default', 'safe', 'smb', 'active-directory'] - - def configure(self): - self.match_service_name(['^smb', '^microsoft\-ds', '^netbios']) - self.match_port('tcp', [139, 445]) - self.run_once(True) - - async def run(self, service): - await service.execute('smbclient -L //{address} -N -I {address} 2>&1', outfile='smbclient.txt') diff --git a/autorecon/default-plugins/smbmap.py b/autorecon/default-plugins/smbmap.py deleted file mode 100644 index de500f7..0000000 --- a/autorecon/default-plugins/smbmap.py +++ /dev/null @@ -1,20 +0,0 @@ -from autorecon.plugins import ServiceScan - -class SMBMap(ServiceScan): - - def __init__(self): - super().__init__() - self.name = "SMBMap" - self.tags = ['default', 'safe', 'smb', 'active-directory'] - - def configure(self): - self.match_service_name(['^smb', '^microsoft\-ds', '^netbios']) - - async def run(self, service): - if service.target.ipversion == 'IPv4': - await service.execute('smbmap -H {address} -P {port} 2>&1', outfile='smbmap-share-permissions.txt') - await service.execute('smbmap -u null -p "" -H {address} -P {port} 2>&1', outfile='smbmap-share-permissions.txt') - await service.execute('smbmap -H {address} -P {port} -R 2>&1', outfile='smbmap-list-contents.txt') - await service.execute('smbmap -u null -p "" -H {address} -P {port} -R 2>&1', outfile='smbmap-list-contents.txt') - await service.execute('smbmap -H {address} -P {port} -x "ipconfig /all" 2>&1', outfile='smbmap-execute-command.txt') - await service.execute('smbmap -u null -p "" -H {address} -P {port} -x "ipconfig /all" 2>&1', outfile='smbmap-execute-command.txt') diff --git a/autorecon/default-plugins/smtp-user-enum.py b/autorecon/default-plugins/smtp-user-enum.py deleted file mode 100644 index 5a995b2..0000000 --- a/autorecon/default-plugins/smtp-user-enum.py +++ /dev/null @@ -1,20 +0,0 @@ -from autorecon.plugins import ServiceScan - -class SMTPUserEnum(ServiceScan): - - def __init__(self): - super().__init__() - self.name = 'SMTP-User-Enum' - self.tags = ['default', 'safe', 'smtp', 'email'] - - def configure(self): - self.match_service_name('^smtp') - - async def run(self, service): - await service.execute('hydra smtp-enum://{addressv6}:{port}/vrfy -L "' + self.get_global('username_wordlist', default='/usr/share/seclists/Usernames/top-usernames-shortlist.txt') + '" 2>&1', outfile='{protocol}_{port}_smtp_user-enum_hydra_vrfy.txt') - await service.execute('hydra smtp-enum://{addressv6}:{port}/expn -L "' + self.get_global('username_wordlist', default='/usr/share/seclists/Usernames/top-usernames-shortlist.txt') + '" 2>&1', outfile='{protocol}_{port}_smtp_user-enum_hydra_expn.txt') - - def manual(self, service, plugin_was_run): - service.add_manual_command('Try User Enumeration using "RCPT TO". Replace with the target\'s domain name:', [ - 'hydra smtp-enum://{addressv6}:{port}/rcpt -L "' + self.get_global('username_wordlist', default='/usr/share/seclists/Usernames/top-usernames-shortlist.txt') + '" -o "{scandir}/{protocol}_{port}_smtp_user-enum_hydra_rcpt.txt" -p ' - ]) diff --git a/autorecon/default-plugins/snmpwalk.py b/autorecon/default-plugins/snmpwalk.py deleted file mode 100644 index 5263700..0000000 --- a/autorecon/default-plugins/snmpwalk.py +++ /dev/null @@ -1,23 +0,0 @@ -from autorecon.plugins import ServiceScan - -class SNMPWalk(ServiceScan): - - def __init__(self): - super().__init__() - self.name = "SNMPWalk" - self.tags = ['default', 'safe', 'snmp'] - - def configure(self): - self.match_service_name('^snmp') - self.match_port('udp', 161) - self.run_once(True) - - async def run(self, service): - await service.execute('snmpwalk -c public -v 1 {address} 2>&1', outfile='{protocol}_{port}_snmp_snmpwalk.txt') - await service.execute('snmpwalk -c public -v 1 {address} 1.3.6.1.2.1.25.1.6.0 2>&1', outfile='{protocol}_{port}_snmp_snmpwalk_system_processes.txt') - await service.execute('snmpwalk -c public -v 1 {address} 1.3.6.1.2.1.25.4.2.1.2 2>&1', outfile='{scandir}/{protocol}_{port}_snmp_snmpwalk_running_processes.txt') - await service.execute('snmpwalk -c public -v 1 {address} 1.3.6.1.2.1.25.4.2.1.4 2>&1', outfile='{protocol}_{port}_snmp_snmpwalk_process_paths.txt') - await service.execute('snmpwalk -c public -v 1 {address} 1.3.6.1.2.1.25.2.3.1.4 2>&1', outfile='{protocol}_{port}_snmp_snmpwalk_storage_units.txt') - await service.execute('snmpwalk -c public -v 1 {address} 1.3.6.1.2.1.25.2.3.1.4 2>&1', outfile='{protocol}_{port}_snmp_snmpwalk_software_names.txt') - await service.execute('snmpwalk -c public -v 1 {address} 1.3.6.1.4.1.77.1.2.25 2>&1', outfile='{protocol}_{port}_snmp_snmpwalk_user_accounts.txt') - await service.execute('snmpwalk -c public -v 1 {address} 1.3.6.1.2.1.6.13.1.3 2>&1', outfile='{protocol}_{port}_snmp_snmpwalk_tcp_ports.txt') diff --git a/autorecon/default-plugins/sslscan.py b/autorecon/default-plugins/sslscan.py deleted file mode 100644 index 43071ac..0000000 --- a/autorecon/default-plugins/sslscan.py +++ /dev/null @@ -1,16 +0,0 @@ -from autorecon.plugins import ServiceScan - -class SSLScan(ServiceScan): - - def __init__(self): - super().__init__() - self.name = "SSL Scan" - self.tags = ['default', 'safe', 'ssl', 'tls'] - - def configure(self): - self.match_all_service_names(True) - self.require_ssl(True) - - async def run(self, service): - if service.protocol == 'tcp' and service.secure: - await service.execute('sslscan --show-certificate --no-colour {addressv6}:{port} 2>&1', outfile='{protocol}_{port}_sslscan.html') diff --git a/autorecon/default-plugins/subdomain-enumeration.py b/autorecon/default-plugins/subdomain-enumeration.py deleted file mode 100644 index 185f5a3..0000000 --- a/autorecon/default-plugins/subdomain-enumeration.py +++ /dev/null @@ -1,34 +0,0 @@ -from autorecon.plugins import ServiceScan -import os - -class SubdomainEnumeration(ServiceScan): - - def __init__(self): - super().__init__() - self.name = "Subdomain Enumeration" - self.slug = "subdomain-enum" - self.tags = ['default', 'safe', 'long', 'dns'] - - def configure(self): - self.add_option('domain', help='The domain to use as the base domain (e.g. example.com) for subdomain enumeration. Default: %(default)s') - self.add_list_option('wordlist', default=['/usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt'], help='The wordlist(s) to use when enumerating subdomains. Separate multiple wordlists with spaces. Default: %(default)s') - self.add_option('threads', default=10, help='The number of threads to use when enumerating subdomains. Default: %(default)s') - self.match_service_name('^domain') - - async def run(self, service): - domains = [] - - if self.get_option('domain'): - domains.append(self.get_option('domain')) - if service.target.type == 'hostname' and service.target.address not in domains: - domains.append(service.target.address) - if self.get_global('domain') and self.get_global('domain') not in domains: - domains.append(self.get_global('domain')) - - if len(domains) > 0: - for wordlist in self.get_option('wordlist'): - name = os.path.splitext(os.path.basename(wordlist))[0] - for domain in domains: - await service.execute('gobuster dns -d ' + domain + ' -r {addressv6} -w ' + wordlist + ' -o "{scandir}/{protocol}_{port}_' + domain + '_subdomains_' + name + '.txt"') - else: - service.info('The target was not a domain, nor was a domain provided as an option. Skipping subdomain enumeration.') diff --git a/autorecon/default-plugins/virtual-host-enumeration.py b/autorecon/default-plugins/virtual-host-enumeration.py deleted file mode 100644 index 96e2561..0000000 --- a/autorecon/default-plugins/virtual-host-enumeration.py +++ /dev/null @@ -1,39 +0,0 @@ -from autorecon.plugins import ServiceScan -from shutil import which -import os, random, string - -class VirtualHost(ServiceScan): - - def __init__(self): - super().__init__() - self.name = 'Virtual Host Enumeration' - self.slug = 'vhost-enum' - self.tags = ['default', 'safe', 'http', 'long'] - - def configure(self): - self.add_option('hostname', help='The hostname to use as the base host (e.g. example.com) for virtual host enumeration. Default: %(default)s') - self.add_list_option('wordlist', default=['/usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt'], help='The wordlist(s) to use when enumerating virtual hosts. Separate multiple wordlists with spaces. Default: %(default)s') - self.add_option('threads', default=10, help='The number of threads to use when enumerating virtual hosts. Default: %(default)s') - self.match_service_name('^http') - self.match_service_name('^nacn_http$', negative_match=True) - - async def run(self, service): - hostnames = [] - if self.get_option('hostname'): - hostnames.append(self.get_option('hostname')) - if service.target.type == 'hostname' and service.target.address not in hostnames: - hostnames.append(service.target.address) - if self.get_global('domain') and self.get_global('domain') not in hostnames: - hostnames.append(self.get_global('domain')) - - if len(hostnames) > 0: - for wordlist in self.get_option('wordlist'): - name = os.path.splitext(os.path.basename(wordlist))[0] - for hostname in hostnames: - _, stdout, _ = await service.execute('curl -sk -o /dev/null -H "Host: ' + ''.join(random.choice(string.ascii_letters) for i in range(20)) + '.' + hostname + '" {http_scheme}://' + hostname + ':{port}/ -w "%{{size_download}}"') - - size = ''.join(await stdout.readlines()) - - await service.execute('ffuf -u {http_scheme}://' + hostname + ':{port}/ -t ' + str(self.get_option('threads')) + ' -w ' + wordlist + ' -H "Host: FUZZ.' + hostname + '" -fs ' + size + ' -noninteractive -s | tee "{scandir}/{protocol}_{port}_{http_scheme}_' + hostname + '_vhosts_' + name + '.txt"') - else: - service.info('The target was not a hostname, nor was a hostname provided as an option. Skipping virtual host enumeration.') diff --git a/autorecon/default-plugins/whatweb.py b/autorecon/default-plugins/whatweb.py deleted file mode 100644 index 017d80c..0000000 --- a/autorecon/default-plugins/whatweb.py +++ /dev/null @@ -1,16 +0,0 @@ -from autorecon.plugins import ServiceScan - -class WhatWeb(ServiceScan): - - def __init__(self): - super().__init__() - self.name = "whatweb" - self.tags = ['default', 'safe', 'http'] - - def configure(self): - self.match_service_name('^http') - self.match_service_name('^nacn_http$', negative_match=True) - - async def run(self, service): - if service.protocol == 'tcp' and service.target.ipversion == 'IPv4': - await service.execute('whatweb --color=never --no-errors -a 3 -v {http_scheme}://{address}:{port} 2>&1', outfile='{protocol}_{port}_{http_scheme}_whatweb.txt') diff --git a/autorecon/default-plugins/winrm-detection.py b/autorecon/default-plugins/winrm-detection.py deleted file mode 100644 index 8742f47..0000000 --- a/autorecon/default-plugins/winrm-detection.py +++ /dev/null @@ -1,32 +0,0 @@ -from autorecon.plugins import ServiceScan -from autorecon.io import fformat - -class WinRMDetection(ServiceScan): - - def __init__(self): - super().__init__() - self.name = 'WinRM Detection' - self.tags = ['default', 'safe', 'winrm'] - - def configure(self): - self.match_service_name('^wsman') - self.match_service('tcp', [5985, 5986], '^http') - - async def run(self, service): - filename = fformat('{scandir}/{protocol}_{port}_winrm-detection.txt') - with open(filename, mode='wt', encoding='utf8') as winrm: - winrm.write('WinRM was possibly detected running on ' + service.protocol + ' port ' + str(service.port) + '.\nCheck _manual_commands.txt for manual commands you can run against this service.') - - def manual(self, service, plugin_was_run): - service.add_manual_commands('Bruteforce logins:', [ - 'crackmapexec winrm {address} -d \'' + self.get_global('domain', default='') + '\' -u \'' + self.get_global('username_wordlist', default='/usr/share/seclists/Usernames/top-usernames-shortlist.txt') + '\' -p \'' + self.get_global('password_wordlist', default='/usr/share/seclists/Passwords/darkweb2017-top100.txt') + '\'' - ]) - - service.add_manual_commands('Check login (requires credentials):', [ - 'crackmapexec winrm {address} -d \'' + self.get_global('domain', default='') + '\' -u \'\' -p \'\'' - ]) - - service.add_manual_commands('Evil WinRM (gem install evil-winrm):', [ - 'evil-winrm -u \'\' -p \'\' -i {address}', - 'evil-winrm -u \'\' -H \'\' -i {address}' - ]) diff --git a/autorecon/default-plugins/wkhtmltoimage.py b/autorecon/default-plugins/wkhtmltoimage.py deleted file mode 100644 index d4d30ba..0000000 --- a/autorecon/default-plugins/wkhtmltoimage.py +++ /dev/null @@ -1,23 +0,0 @@ -from autorecon.plugins import ServiceScan -from shutil import which - -class WkHTMLToImage(ServiceScan): - - def __init__(self): - super().__init__() - self.name = "wkhtmltoimage" - self.tags = ['default', 'safe', 'http'] - - def configure(self): - self.match_service_name('^http') - self.match_service_name('^nacn_http$', negative_match=True) - - def check(self): - if which('wkhtmltoimage') is None: - self.error('The wkhtmltoimage program could not be found. Make sure it is installed. (On Kali, run: sudo apt install wkhtmltopdf)') - return False - - async def run(self, service): - if which('wkhtmltoimage') is not None: - if service.protocol == 'tcp': - await service.execute('wkhtmltoimage --format png {http_scheme}://{addressv6}:{port}/ {scandir}/{protocol}_{port}_{http_scheme}_screenshot.png') diff --git a/autorecon/default-plugins/wpscan.py b/autorecon/default-plugins/wpscan.py deleted file mode 100644 index a5a9249..0000000 --- a/autorecon/default-plugins/wpscan.py +++ /dev/null @@ -1,20 +0,0 @@ -from autorecon.plugins import ServiceScan - -class WPScan(ServiceScan): - - def __init__(self): - super().__init__() - self.name = 'WPScan' - self.tags = ['default', 'safe', 'http'] - - def configure(self): - self.add_option('api-token', help='An API Token from wpvulndb.com to help search for more vulnerabilities.') - self.match_service_name('^http') - self.match_service_name('^nacn_http$', negative_match=True) - - def manual(self, service, plugin_was_run): - api_token = '' - if self.get_option('api-token'): - api_token = ' --api-token ' + self.get_option('api-token') - - service.add_manual_command('(wpscan) WordPress Security Scanner (useful if WordPress is found):', 'wpscan --url {http_scheme}://{addressv6}:{port}/ --no-update -e vp,vt,tt,cb,dbe,u,m --plugins-detection aggressive --plugins-version-detection aggressive -f cli-no-color' + api_token + ' 2>&1 | tee "{scandir}/{protocol}_{port}_{http_scheme}_wpscan.txt"') diff --git a/autorecon/main.py b/autorecon/main.py index e02e206..8611140 100644 --- a/autorecon/main.py +++ b/autorecon/main.py @@ -862,7 +862,7 @@ async def run(): else: config['global_file'] = None - # Find plugins. + # Find plugins. # need to `rm -rf ~/.local/share/AutoRecon && poetry install` before testing changes to plugins... if os.path.isdir(os.path.join(config['data_dir'], 'plugins')): config['plugins_dir'] = os.path.join(config['data_dir'], 'plugins') else: @@ -905,10 +905,10 @@ async def run(): parser.add_argument('--version', action='store_true', help='Prints the AutoRecon version and exits.') parser.error = lambda s: fail(s[0].upper() + s[1:]) args, unknown = parser.parse_known_args() - errors = False autorecon.argparse = parser + if args.version: print('AutoRecon v' + VERSION) @@ -1008,6 +1008,7 @@ def unknown_help(): fail('Plugin ' + plugin.name + ' has a slug (' + plugin.slug + ') with the same name as a tag. Please either change the plugin name or override the slug.') # Add plugin slug to tags. plugin.tags += [plugin.slug] + if len(autorecon.plugin_types['port']) == 0: unknown_help() @@ -1095,7 +1096,6 @@ def unknown_help(): except toml.decoder.TomlDecodeError: unknown_help() fail('Error: Couldn\'t parse ' + g.name + ' file. Check syntax.') - other_options = [] for key, val in config_toml.items(): if key == 'global' and isinstance(val, dict): # Process global plugin options. @@ -1111,7 +1111,6 @@ def unknown_help(): autorecon.argparse.set_defaults(**{'global.' + slugify(gkey).replace('-', '_'): gval}) elif isinstance(val, dict): # Process potential plugin arguments. for pkey, pval in config_toml[key].items(): - print(pkey, pval) if autorecon.argparse.get_default(slugify(key).replace('-', '_') + '.' + slugify(pkey).replace('-', '_')) is not None: for action in autorecon.argparse._actions: if action.dest == slugify(key).replace('-', '_') + '.' + slugify(pkey).replace('-', '_'): @@ -1122,6 +1121,7 @@ def unknown_help(): error('Config option [' + slugify(key) + '] ' + slugify(pkey) + ': invalid value: \'' + pval + '\' (should be ' + str(action.const) + ')') errors = True elif action.choices and pval not in action.choices: + print('line 1130', pval, action.choices) error('Config option [' + slugify(key) + '] ' + slugify(pkey) + ': invalid choice: \'' + pval + '\' (choose from \'' + '\', \''.join(action.choices) + '\')') errors = True elif isinstance(action.default, list) and not isinstance(pval, list): @@ -1139,11 +1139,9 @@ def unknown_help(): for key, val in config.items(): if key not in other_options: autorecon.argparse.set_defaults(**{key: val}) - - parser.add_argument('-h', '--help', action='help', default=argparse.SUPPRESS, help='Show this help message and exit.') + parser.add_argument('-h', '--help', action='help', default=argparse.SUPPRESS, help='Show this help message and exit.') # isn't this addressed around line 920? -shyft parser.error = lambda s: fail(s[0].upper() + s[1:]) - args = parser.parse_args() - + args = parser.parse_args() # this is where bogus /unknown args are killed -shyft args_dict = vars(args) for key in args_dict: if key in configurable_keys and args_dict[key] is not None: @@ -1152,7 +1150,6 @@ def unknown_help(): continue config[key] = args_dict[key] autorecon.args = args - if args.list: type = args.list.lower() if type in ['plugin', 'plugins', 'port', 'ports', 'portscan', 'portscans']: diff --git a/autorecon/plugins.py b/autorecon/plugins.py index 222de4f..ed92db5 100644 --- a/autorecon/plugins.py +++ b/autorecon/plugins.py @@ -58,13 +58,13 @@ def get_option(self, name, default=None): if default: return default else: - return None + return list() else: return vars(self.autorecon.args)[name] else: if default: return default - return None + return list() @final def get_global_option(self, name, default=None): @@ -227,7 +227,7 @@ def __init__(self): self.scanning_targets = [] self.completed_targets = [] self.plugins = {} - self.__slug_regex = re.compile('^[a-z0-9\-]+$') + self.__slug_regex = re.compile(r'^[a-z0-9\-]+$') self.plugin_types = {'port':[], 'service':[], 'report':[]} self.port_scan_semaphore = None self.service_scan_semaphore = None @@ -254,7 +254,7 @@ def add_argument(self, plugin, name, **kwargs): def extract_service(self, line, regex): if regex is None: - regex = '^(?P\d+)\/(?P(tcp|udp))(.*)open(\s*)(?P[\w\-\/]+)(\s*)(.*)$' + regex = r'^(?P\d+)\/(?P(tcp|udp))(.*)open(\s*)(?P[\w\-\/]+)(\s*)(.*)$' match = re.search(regex, line) if match: protocol = match.group('protocol').lower() diff --git a/poetry.lock b/poetry.lock index c8cfa8e..47687cf 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,3 +1,5 @@ +# This file is automatically @generated by Poetry and should not be changed by hand. + [[package]] name = "appdirs" version = "1.4.4" @@ -5,14 +7,661 @@ description = "A small Python module for determining appropriate platform-specif category = "main" optional = false python-versions = "*" +files = [ + {file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"}, + {file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"}, +] + +[[package]] +name = "certifi" +version = "2022.12.7" +description = "Python package for providing Mozilla's CA Bundle." +category = "main" +optional = false +python-versions = ">=3.6" +files = [ + {file = "certifi-2022.12.7-py3-none-any.whl", hash = "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"}, + {file = "certifi-2022.12.7.tar.gz", hash = "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3"}, +] + +[[package]] +name = "cffi" +version = "1.15.1" +description = "Foreign Function Interface for Python calling C code." +category = "main" +optional = false +python-versions = "*" +files = [ + {file = "cffi-1.15.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2"}, + {file = "cffi-1.15.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2"}, + {file = "cffi-1.15.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914"}, + {file = "cffi-1.15.1-cp27-cp27m-win32.whl", hash = "sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3"}, + {file = "cffi-1.15.1-cp27-cp27m-win_amd64.whl", hash = "sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e"}, + {file = "cffi-1.15.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162"}, + {file = "cffi-1.15.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b"}, + {file = "cffi-1.15.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21"}, + {file = "cffi-1.15.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185"}, + {file = "cffi-1.15.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd"}, + {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc"}, + {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f"}, + {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e"}, + {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4"}, + {file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01"}, + {file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e"}, + {file = "cffi-1.15.1-cp310-cp310-win32.whl", hash = "sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2"}, + {file = "cffi-1.15.1-cp310-cp310-win_amd64.whl", hash = "sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d"}, + {file = "cffi-1.15.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac"}, + {file = "cffi-1.15.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83"}, + {file = "cffi-1.15.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9"}, + {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c"}, + {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325"}, + {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c"}, + {file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef"}, + {file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8"}, + {file = "cffi-1.15.1-cp311-cp311-win32.whl", hash = "sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d"}, + {file = "cffi-1.15.1-cp311-cp311-win_amd64.whl", hash = "sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104"}, + {file = "cffi-1.15.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7"}, + {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6"}, + {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d"}, + {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a"}, + {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405"}, + {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e"}, + {file = "cffi-1.15.1-cp36-cp36m-win32.whl", hash = "sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf"}, + {file = "cffi-1.15.1-cp36-cp36m-win_amd64.whl", hash = "sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497"}, + {file = "cffi-1.15.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375"}, + {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e"}, + {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82"}, + {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b"}, + {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c"}, + {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426"}, + {file = "cffi-1.15.1-cp37-cp37m-win32.whl", hash = "sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9"}, + {file = "cffi-1.15.1-cp37-cp37m-win_amd64.whl", hash = "sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045"}, + {file = "cffi-1.15.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3"}, + {file = "cffi-1.15.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a"}, + {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5"}, + {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca"}, + {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02"}, + {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192"}, + {file = "cffi-1.15.1-cp38-cp38-win32.whl", hash = "sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314"}, + {file = "cffi-1.15.1-cp38-cp38-win_amd64.whl", hash = "sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5"}, + {file = "cffi-1.15.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585"}, + {file = "cffi-1.15.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0"}, + {file = "cffi-1.15.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415"}, + {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d"}, + {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984"}, + {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35"}, + {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27"}, + {file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76"}, + {file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3"}, + {file = "cffi-1.15.1-cp39-cp39-win32.whl", hash = "sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee"}, + {file = "cffi-1.15.1-cp39-cp39-win_amd64.whl", hash = "sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c"}, + {file = "cffi-1.15.1.tar.gz", hash = "sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9"}, +] + +[package.dependencies] +pycparser = "*" + +[[package]] +name = "chardet" +version = "5.1.0" +description = "Universal encoding detector for Python 3" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "chardet-5.1.0-py3-none-any.whl", hash = "sha256:362777fb014af596ad31334fde1e8c327dfdb076e1960d1694662d46a6917ab9"}, + {file = "chardet-5.1.0.tar.gz", hash = "sha256:0d62712b956bc154f85fb0a266e2a3c5913c2967e00348701b32411d6def31e5"}, +] + +[[package]] +name = "charset-normalizer" +version = "3.0.1" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +category = "main" +optional = false +python-versions = "*" +files = [ + {file = "charset-normalizer-3.0.1.tar.gz", hash = "sha256:ebea339af930f8ca5d7a699b921106c6e29c617fe9606fa7baa043c1cdae326f"}, + {file = "charset_normalizer-3.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:88600c72ef7587fe1708fd242b385b6ed4b8904976d5da0893e31df8b3480cb6"}, + {file = "charset_normalizer-3.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c75ffc45f25324e68ab238cb4b5c0a38cd1c3d7f1fb1f72b5541de469e2247db"}, + {file = "charset_normalizer-3.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:db72b07027db150f468fbada4d85b3b2729a3db39178abf5c543b784c1254539"}, + {file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:62595ab75873d50d57323a91dd03e6966eb79c41fa834b7a1661ed043b2d404d"}, + {file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ff6f3db31555657f3163b15a6b7c6938d08df7adbfc9dd13d9d19edad678f1e8"}, + {file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:772b87914ff1152b92a197ef4ea40efe27a378606c39446ded52c8f80f79702e"}, + {file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70990b9c51340e4044cfc394a81f614f3f90d41397104d226f21e66de668730d"}, + {file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:292d5e8ba896bbfd6334b096e34bffb56161c81408d6d036a7dfa6929cff8783"}, + {file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:2edb64ee7bf1ed524a1da60cdcd2e1f6e2b4f66ef7c077680739f1641f62f555"}, + {file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:31a9ddf4718d10ae04d9b18801bd776693487cbb57d74cc3458a7673f6f34639"}, + {file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:44ba614de5361b3e5278e1241fda3dc1838deed864b50a10d7ce92983797fa76"}, + {file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:12db3b2c533c23ab812c2b25934f60383361f8a376ae272665f8e48b88e8e1c6"}, + {file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c512accbd6ff0270939b9ac214b84fb5ada5f0409c44298361b2f5e13f9aed9e"}, + {file = "charset_normalizer-3.0.1-cp310-cp310-win32.whl", hash = "sha256:502218f52498a36d6bf5ea77081844017bf7982cdbe521ad85e64cabee1b608b"}, + {file = "charset_normalizer-3.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:601f36512f9e28f029d9481bdaf8e89e5148ac5d89cffd3b05cd533eeb423b59"}, + {file = "charset_normalizer-3.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0298eafff88c99982a4cf66ba2efa1128e4ddaca0b05eec4c456bbc7db691d8d"}, + {file = "charset_normalizer-3.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a8d0fc946c784ff7f7c3742310cc8a57c5c6dc31631269876a88b809dbeff3d3"}, + {file = "charset_normalizer-3.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:87701167f2a5c930b403e9756fab1d31d4d4da52856143b609e30a1ce7160f3c"}, + {file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:14e76c0f23218b8f46c4d87018ca2e441535aed3632ca134b10239dfb6dadd6b"}, + {file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0c0a590235ccd933d9892c627dec5bc7511ce6ad6c1011fdf5b11363022746c1"}, + {file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c7fe7afa480e3e82eed58e0ca89f751cd14d767638e2550c77a92a9e749c317"}, + {file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:79909e27e8e4fcc9db4addea88aa63f6423ebb171db091fb4373e3312cb6d603"}, + {file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8ac7b6a045b814cf0c47f3623d21ebd88b3e8cf216a14790b455ea7ff0135d18"}, + {file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:72966d1b297c741541ca8cf1223ff262a6febe52481af742036a0b296e35fa5a"}, + {file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:f9d0c5c045a3ca9bedfc35dca8526798eb91a07aa7a2c0fee134c6c6f321cbd7"}, + {file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:5995f0164fa7df59db4746112fec3f49c461dd6b31b841873443bdb077c13cfc"}, + {file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4a8fcf28c05c1f6d7e177a9a46a1c52798bfe2ad80681d275b10dcf317deaf0b"}, + {file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:761e8904c07ad053d285670f36dd94e1b6ab7f16ce62b9805c475b7aa1cffde6"}, + {file = "charset_normalizer-3.0.1-cp311-cp311-win32.whl", hash = "sha256:71140351489970dfe5e60fc621ada3e0f41104a5eddaca47a7acb3c1b851d6d3"}, + {file = "charset_normalizer-3.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:9ab77acb98eba3fd2a85cd160851816bfce6871d944d885febf012713f06659c"}, + {file = "charset_normalizer-3.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:84c3990934bae40ea69a82034912ffe5a62c60bbf6ec5bc9691419641d7d5c9a"}, + {file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:74292fc76c905c0ef095fe11e188a32ebd03bc38f3f3e9bcb85e4e6db177b7ea"}, + {file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c95a03c79bbe30eec3ec2b7f076074f4281526724c8685a42872974ef4d36b72"}, + {file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f4c39b0e3eac288fedc2b43055cfc2ca7a60362d0e5e87a637beac5d801ef478"}, + {file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:df2c707231459e8a4028eabcd3cfc827befd635b3ef72eada84ab13b52e1574d"}, + {file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:93ad6d87ac18e2a90b0fe89df7c65263b9a99a0eb98f0a3d2e079f12a0735837"}, + {file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:59e5686dd847347e55dffcc191a96622f016bc0ad89105e24c14e0d6305acbc6"}, + {file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:cd6056167405314a4dc3c173943f11249fa0f1b204f8b51ed4bde1a9cd1834dc"}, + {file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:083c8d17153ecb403e5e1eb76a7ef4babfc2c48d58899c98fcaa04833e7a2f9a"}, + {file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:f5057856d21e7586765171eac8b9fc3f7d44ef39425f85dbcccb13b3ebea806c"}, + {file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:7eb33a30d75562222b64f569c642ff3dc6689e09adda43a082208397f016c39a"}, + {file = "charset_normalizer-3.0.1-cp36-cp36m-win32.whl", hash = "sha256:95dea361dd73757c6f1c0a1480ac499952c16ac83f7f5f4f84f0658a01b8ef41"}, + {file = "charset_normalizer-3.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:eaa379fcd227ca235d04152ca6704c7cb55564116f8bc52545ff357628e10602"}, + {file = "charset_normalizer-3.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3e45867f1f2ab0711d60c6c71746ac53537f1684baa699f4f668d4c6f6ce8e14"}, + {file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cadaeaba78750d58d3cc6ac4d1fd867da6fc73c88156b7a3212a3cd4819d679d"}, + {file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:911d8a40b2bef5b8bbae2e36a0b103f142ac53557ab421dc16ac4aafee6f53dc"}, + {file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:503e65837c71b875ecdd733877d852adbc465bd82c768a067badd953bf1bc5a3"}, + {file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a60332922359f920193b1d4826953c507a877b523b2395ad7bc716ddd386d866"}, + {file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:16a8663d6e281208d78806dbe14ee9903715361cf81f6d4309944e4d1e59ac5b"}, + {file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:a16418ecf1329f71df119e8a65f3aa68004a3f9383821edcb20f0702934d8087"}, + {file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:9d9153257a3f70d5f69edf2325357251ed20f772b12e593f3b3377b5f78e7ef8"}, + {file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:02a51034802cbf38db3f89c66fb5d2ec57e6fe7ef2f4a44d070a593c3688667b"}, + {file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:2e396d70bc4ef5325b72b593a72c8979999aa52fb8bcf03f701c1b03e1166918"}, + {file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:11b53acf2411c3b09e6af37e4b9005cba376c872503c8f28218c7243582df45d"}, + {file = "charset_normalizer-3.0.1-cp37-cp37m-win32.whl", hash = "sha256:0bf2dae5291758b6f84cf923bfaa285632816007db0330002fa1de38bfcb7154"}, + {file = "charset_normalizer-3.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:2c03cc56021a4bd59be889c2b9257dae13bf55041a3372d3295416f86b295fb5"}, + {file = "charset_normalizer-3.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:024e606be3ed92216e2b6952ed859d86b4cfa52cd5bc5f050e7dc28f9b43ec42"}, + {file = "charset_normalizer-3.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4b0d02d7102dd0f997580b51edc4cebcf2ab6397a7edf89f1c73b586c614272c"}, + {file = "charset_normalizer-3.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:358a7c4cb8ba9b46c453b1dd8d9e431452d5249072e4f56cfda3149f6ab1405e"}, + {file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81d6741ab457d14fdedc215516665050f3822d3e56508921cc7239f8c8e66a58"}, + {file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8b8af03d2e37866d023ad0ddea594edefc31e827fee64f8de5611a1dbc373174"}, + {file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9cf4e8ad252f7c38dd1f676b46514f92dc0ebeb0db5552f5f403509705e24753"}, + {file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e696f0dd336161fca9adbb846875d40752e6eba585843c768935ba5c9960722b"}, + {file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c22d3fe05ce11d3671297dc8973267daa0f938b93ec716e12e0f6dee81591dc1"}, + {file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:109487860ef6a328f3eec66f2bf78b0b72400280d8f8ea05f69c51644ba6521a"}, + {file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:37f8febc8ec50c14f3ec9637505f28e58d4f66752207ea177c1d67df25da5aed"}, + {file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:f97e83fa6c25693c7a35de154681fcc257c1c41b38beb0304b9c4d2d9e164479"}, + {file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a152f5f33d64a6be73f1d30c9cc82dfc73cec6477ec268e7c6e4c7d23c2d2291"}, + {file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:39049da0ffb96c8cbb65cbf5c5f3ca3168990adf3551bd1dee10c48fce8ae820"}, + {file = "charset_normalizer-3.0.1-cp38-cp38-win32.whl", hash = "sha256:4457ea6774b5611f4bed5eaa5df55f70abde42364d498c5134b7ef4c6958e20e"}, + {file = "charset_normalizer-3.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:e62164b50f84e20601c1ff8eb55620d2ad25fb81b59e3cd776a1902527a788af"}, + {file = "charset_normalizer-3.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8eade758719add78ec36dc13201483f8e9b5d940329285edcd5f70c0a9edbd7f"}, + {file = "charset_normalizer-3.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8499ca8f4502af841f68135133d8258f7b32a53a1d594aa98cc52013fff55678"}, + {file = "charset_normalizer-3.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3fc1c4a2ffd64890aebdb3f97e1278b0cc72579a08ca4de8cd2c04799a3a22be"}, + {file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:00d3ffdaafe92a5dc603cb9bd5111aaa36dfa187c8285c543be562e61b755f6b"}, + {file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c2ac1b08635a8cd4e0cbeaf6f5e922085908d48eb05d44c5ae9eabab148512ca"}, + {file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f6f45710b4459401609ebebdbcfb34515da4fc2aa886f95107f556ac69a9147e"}, + {file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ae1de54a77dc0d6d5fcf623290af4266412a7c4be0b1ff7444394f03f5c54e3"}, + {file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3b590df687e3c5ee0deef9fc8c547d81986d9a1b56073d82de008744452d6541"}, + {file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab5de034a886f616a5668aa5d098af2b5385ed70142090e2a31bcbd0af0fdb3d"}, + {file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9cb3032517f1627cc012dbc80a8ec976ae76d93ea2b5feaa9d2a5b8882597579"}, + {file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:608862a7bf6957f2333fc54ab4399e405baad0163dc9f8d99cb236816db169d4"}, + {file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0f438ae3532723fb6ead77e7c604be7c8374094ef4ee2c5e03a3a17f1fca256c"}, + {file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:356541bf4381fa35856dafa6a965916e54bed415ad8a24ee6de6e37deccf2786"}, + {file = "charset_normalizer-3.0.1-cp39-cp39-win32.whl", hash = "sha256:39cf9ed17fe3b1bc81f33c9ceb6ce67683ee7526e65fde1447c772afc54a1bb8"}, + {file = "charset_normalizer-3.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:0a11e971ed097d24c534c037d298ad32c6ce81a45736d31e0ff0ad37ab437d59"}, + {file = "charset_normalizer-3.0.1-py3-none-any.whl", hash = "sha256:7e189e2e1d3ed2f4aebabd2d5b0f931e883676e51c7624826e0a4e5fe8a0bf24"}, +] + +[[package]] +name = "click" +version = "8.1.3" +description = "Composable command line interface toolkit" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, + {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} [[package]] name = "colorama" -version = "0.4.4" +version = "0.4.6" description = "Cross-platform colored terminal text." category = "main" optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + +[[package]] +name = "cryptography" +version = "39.0.1" +description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." +category = "main" +optional = false +python-versions = ">=3.6" +files = [ + {file = "cryptography-39.0.1-cp36-abi3-macosx_10_12_universal2.whl", hash = "sha256:6687ef6d0a6497e2b58e7c5b852b53f62142cfa7cd1555795758934da363a965"}, + {file = "cryptography-39.0.1-cp36-abi3-macosx_10_12_x86_64.whl", hash = "sha256:706843b48f9a3f9b9911979761c91541e3d90db1ca905fd63fee540a217698bc"}, + {file = "cryptography-39.0.1-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:5d2d8b87a490bfcd407ed9d49093793d0f75198a35e6eb1a923ce1ee86c62b41"}, + {file = "cryptography-39.0.1-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:83e17b26de248c33f3acffb922748151d71827d6021d98c70e6c1a25ddd78505"}, + {file = "cryptography-39.0.1-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e124352fd3db36a9d4a21c1aa27fd5d051e621845cb87fb851c08f4f75ce8be6"}, + {file = "cryptography-39.0.1-cp36-abi3-manylinux_2_24_x86_64.whl", hash = "sha256:5aa67414fcdfa22cf052e640cb5ddc461924a045cacf325cd164e65312d99502"}, + {file = "cryptography-39.0.1-cp36-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:35f7c7d015d474f4011e859e93e789c87d21f6f4880ebdc29896a60403328f1f"}, + {file = "cryptography-39.0.1-cp36-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:f24077a3b5298a5a06a8e0536e3ea9ec60e4c7ac486755e5fb6e6ea9b3500106"}, + {file = "cryptography-39.0.1-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:f0c64d1bd842ca2633e74a1a28033d139368ad959872533b1bab8c80e8240a0c"}, + {file = "cryptography-39.0.1-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:0f8da300b5c8af9f98111ffd512910bc792b4c77392a9523624680f7956a99d4"}, + {file = "cryptography-39.0.1-cp36-abi3-win32.whl", hash = "sha256:fe913f20024eb2cb2f323e42a64bdf2911bb9738a15dba7d3cce48151034e3a8"}, + {file = "cryptography-39.0.1-cp36-abi3-win_amd64.whl", hash = "sha256:ced4e447ae29ca194449a3f1ce132ded8fcab06971ef5f618605aacaa612beac"}, + {file = "cryptography-39.0.1-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:807ce09d4434881ca3a7594733669bd834f5b2c6d5c7e36f8c00f691887042ad"}, + {file = "cryptography-39.0.1-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c5caeb8188c24888c90b5108a441c106f7faa4c4c075a2bcae438c6e8ca73cef"}, + {file = "cryptography-39.0.1-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:4789d1e3e257965e960232345002262ede4d094d1a19f4d3b52e48d4d8f3b885"}, + {file = "cryptography-39.0.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:96f1157a7c08b5b189b16b47bc9db2332269d6680a196341bf30046330d15388"}, + {file = "cryptography-39.0.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:e422abdec8b5fa8462aa016786680720d78bdce7a30c652b7fadf83a4ba35336"}, + {file = "cryptography-39.0.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:b0afd054cd42f3d213bf82c629efb1ee5f22eba35bf0eec88ea9ea7304f511a2"}, + {file = "cryptography-39.0.1-pp39-pypy39_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:6f8ba7f0328b79f08bdacc3e4e66fb4d7aab0c3584e0bd41328dce5262e26b2e"}, + {file = "cryptography-39.0.1-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:ef8b72fa70b348724ff1218267e7f7375b8de4e8194d1636ee60510aae104cd0"}, + {file = "cryptography-39.0.1-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:aec5a6c9864be7df2240c382740fcf3b96928c46604eaa7f3091f58b878c0bb6"}, + {file = "cryptography-39.0.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:fdd188c8a6ef8769f148f88f859884507b954cc64db6b52f66ef199bb9ad660a"}, + {file = "cryptography-39.0.1.tar.gz", hash = "sha256:d1f6198ee6d9148405e49887803907fe8962a23e6c6f83ea7d98f1c0de375695"}, +] + +[package.dependencies] +cffi = ">=1.12" + +[package.extras] +docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.1.1)"] +docstest = ["pyenchant (>=1.6.11)", "sphinxcontrib-spelling (>=4.0.1)", "twine (>=1.12.0)"] +pep8test = ["black", "check-manifest", "mypy", "ruff", "types-pytz", "types-requests"] +sdist = ["setuptools-rust (>=0.11.4)"] +ssh = ["bcrypt (>=3.1.5)"] +test = ["hypothesis (>=1.11.4,!=3.79.2)", "iso8601", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-shard (>=0.1.2)", "pytest-subtests", "pytest-xdist", "pytz"] +test-randomorder = ["pytest-randomly"] +tox = ["tox"] + +[[package]] +name = "dnspython" +version = "2.3.0" +description = "DNS toolkit" +category = "main" +optional = false +python-versions = ">=3.7,<4.0" +files = [ + {file = "dnspython-2.3.0-py3-none-any.whl", hash = "sha256:89141536394f909066cabd112e3e1a37e4e654db00a25308b0f130bc3152eb46"}, + {file = "dnspython-2.3.0.tar.gz", hash = "sha256:224e32b03eb46be70e12ef6d64e0be123a64e621ab4c0822ff6d450d52a540b9"}, +] + +[package.extras] +curio = ["curio (>=1.2,<2.0)", "sniffio (>=1.1,<2.0)"] +dnssec = ["cryptography (>=2.6,<40.0)"] +doh = ["h2 (>=4.1.0)", "httpx (>=0.21.1)", "requests (>=2.23.0,<3.0.0)", "requests-toolbelt (>=0.9.1,<0.11.0)"] +doq = ["aioquic (>=0.9.20)"] +idna = ["idna (>=2.1,<4.0)"] +trio = ["trio (>=0.14,<0.23)"] +wmi = ["wmi (>=1.5.1,<2.0.0)"] + +[[package]] +name = "flask" +version = "2.2.3" +description = "A simple framework for building complex web applications." +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "Flask-2.2.3-py3-none-any.whl", hash = "sha256:c0bec9477df1cb867e5a67c9e1ab758de9cb4a3e52dd70681f59fa40a62b3f2d"}, + {file = "Flask-2.2.3.tar.gz", hash = "sha256:7eb373984bf1c770023fce9db164ed0c3353cd0b53f130f4693da0ca756a2e6d"}, +] + +[package.dependencies] +click = ">=8.0" +importlib-metadata = {version = ">=3.6.0", markers = "python_version < \"3.10\""} +itsdangerous = ">=2.0" +Jinja2 = ">=3.0" +Werkzeug = ">=2.2.2" + +[package.extras] +async = ["asgiref (>=3.2)"] +dotenv = ["python-dotenv"] + +[[package]] +name = "future" +version = "0.18.3" +description = "Clean single-source support for Python 3 and 2" +category = "main" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "future-0.18.3.tar.gz", hash = "sha256:34a17436ed1e96697a86f9de3d15a3b0be01d8bc8de9c1dffd59fb8234ed5307"}, +] + +[[package]] +name = "idna" +version = "3.4" +description = "Internationalized Domain Names in Applications (IDNA)" +category = "main" +optional = false +python-versions = ">=3.5" +files = [ + {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, + {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, +] + +[[package]] +name = "impacket" +version = "0.10.0" +description = "Network protocols Constructors and Dissectors" +category = "main" +optional = false +python-versions = "*" +files = [ + {file = "impacket-0.10.0.tar.gz", hash = "sha256:b8eb020a2cbb47146669cfe31c64bb2e7d6499d049c493d6418b9716f5c74583"}, +] + +[package.dependencies] +chardet = "*" +flask = ">=1.0" +future = "*" +ldap3 = ">2.5.0,<2.5.2 || >2.5.2,<2.6 || >2.6" +ldapdomaindump = ">=0.9.0" +pyasn1 = ">=0.2.3" +pycryptodomex = "*" +pyOpenSSL = ">=0.16.2" +six = "*" + +[[package]] +name = "importlib-metadata" +version = "6.0.0" +description = "Read metadata from Python packages" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "importlib_metadata-6.0.0-py3-none-any.whl", hash = "sha256:7efb448ec9a5e313a57655d35aa54cd3e01b7e1fbcf72dce1bf06119420f5bad"}, + {file = "importlib_metadata-6.0.0.tar.gz", hash = "sha256:e354bedeb60efa6affdcc8ae121b73544a7aa74156d047311948f6d711cd378d"}, +] + +[package.dependencies] +zipp = ">=0.5" + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +perf = ["ipython"] +testing = ["flake8 (<5)", "flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)"] + +[[package]] +name = "itsdangerous" +version = "2.1.2" +description = "Safely pass data to untrusted environments and back." +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "itsdangerous-2.1.2-py3-none-any.whl", hash = "sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44"}, + {file = "itsdangerous-2.1.2.tar.gz", hash = "sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a"}, +] + +[[package]] +name = "jinja2" +version = "3.1.2" +description = "A very fast and expressive template engine." +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"}, + {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"}, +] + +[package.dependencies] +MarkupSafe = ">=2.0" + +[package.extras] +i18n = ["Babel (>=2.7)"] + +[[package]] +name = "ldap3" +version = "2.9.1" +description = "A strictly RFC 4510 conforming LDAP V3 pure Python client library" +category = "main" +optional = false +python-versions = "*" +files = [ + {file = "ldap3-2.9.1-py2.py3-none-any.whl", hash = "sha256:5869596fc4948797020d3f03b7939da938778a0f9e2009f7a072ccf92b8e8d70"}, + {file = "ldap3-2.9.1.tar.gz", hash = "sha256:f3e7fc4718e3f09dda568b57100095e0ce58633bcabbed8667ce3f8fbaa4229f"}, +] + +[package.dependencies] +pyasn1 = ">=0.4.6" + +[[package]] +name = "ldapdomaindump" +version = "0.9.4" +description = "Active Directory information dumper via LDAP" +category = "main" +optional = false +python-versions = "*" +files = [ + {file = "ldapdomaindump-0.9.4-py2-none-any.whl", hash = "sha256:c05ee1d892e6a0eb2d7bf167242d4bf747ff7758f625588a11795510d06de01f"}, + {file = "ldapdomaindump-0.9.4-py3-none-any.whl", hash = "sha256:51d0c241af1d6fa3eefd79b95d182a798d39c56c4e2efb7ffae244a0b54f58aa"}, + {file = "ldapdomaindump-0.9.4.tar.gz", hash = "sha256:99dcda17050a96549966e53bc89e71da670094d53d9542b3b0d0197d035e6f52"}, +] + +[package.dependencies] +dnspython = "*" +future = "*" +ldap3 = ">2.5.0,<2.5.2 || >2.5.2,<2.6 || >2.6" + +[[package]] +name = "markupsafe" +version = "2.1.2" +description = "Safely add untrusted strings to HTML/XML markup." +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "MarkupSafe-2.1.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:665a36ae6f8f20a4676b53224e33d456a6f5a72657d9c83c2aa00765072f31f7"}, + {file = "MarkupSafe-2.1.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:340bea174e9761308703ae988e982005aedf427de816d1afe98147668cc03036"}, + {file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22152d00bf4a9c7c83960521fc558f55a1adbc0631fbb00a9471e097b19d72e1"}, + {file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28057e985dace2f478e042eaa15606c7efccb700797660629da387eb289b9323"}, + {file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca244fa73f50a800cf8c3ebf7fd93149ec37f5cb9596aa8873ae2c1d23498601"}, + {file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d9d971ec1e79906046aa3ca266de79eac42f1dbf3612a05dc9368125952bd1a1"}, + {file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7e007132af78ea9df29495dbf7b5824cb71648d7133cf7848a2a5dd00d36f9ff"}, + {file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7313ce6a199651c4ed9d7e4cfb4aa56fe923b1adf9af3b420ee14e6d9a73df65"}, + {file = "MarkupSafe-2.1.2-cp310-cp310-win32.whl", hash = "sha256:c4a549890a45f57f1ebf99c067a4ad0cb423a05544accaf2b065246827ed9603"}, + {file = "MarkupSafe-2.1.2-cp310-cp310-win_amd64.whl", hash = "sha256:835fb5e38fd89328e9c81067fd642b3593c33e1e17e2fdbf77f5676abb14a156"}, + {file = "MarkupSafe-2.1.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2ec4f2d48ae59bbb9d1f9d7efb9236ab81429a764dedca114f5fdabbc3788013"}, + {file = "MarkupSafe-2.1.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:608e7073dfa9e38a85d38474c082d4281f4ce276ac0010224eaba11e929dd53a"}, + {file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:65608c35bfb8a76763f37036547f7adfd09270fbdbf96608be2bead319728fcd"}, + {file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2bfb563d0211ce16b63c7cb9395d2c682a23187f54c3d79bfec33e6705473c6"}, + {file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:da25303d91526aac3672ee6d49a2f3db2d9502a4a60b55519feb1a4c7714e07d"}, + {file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:9cad97ab29dfc3f0249b483412c85c8ef4766d96cdf9dcf5a1e3caa3f3661cf1"}, + {file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:085fd3201e7b12809f9e6e9bc1e5c96a368c8523fad5afb02afe3c051ae4afcc"}, + {file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1bea30e9bf331f3fef67e0a3877b2288593c98a21ccb2cf29b74c581a4eb3af0"}, + {file = "MarkupSafe-2.1.2-cp311-cp311-win32.whl", hash = "sha256:7df70907e00c970c60b9ef2938d894a9381f38e6b9db73c5be35e59d92e06625"}, + {file = "MarkupSafe-2.1.2-cp311-cp311-win_amd64.whl", hash = "sha256:e55e40ff0cc8cc5c07996915ad367fa47da6b3fc091fdadca7f5403239c5fec3"}, + {file = "MarkupSafe-2.1.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a6e40afa7f45939ca356f348c8e23048e02cb109ced1eb8420961b2f40fb373a"}, + {file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf877ab4ed6e302ec1d04952ca358b381a882fbd9d1b07cccbfd61783561f98a"}, + {file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63ba06c9941e46fa389d389644e2d8225e0e3e5ebcc4ff1ea8506dce646f8c8a"}, + {file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f1cd098434e83e656abf198f103a8207a8187c0fc110306691a2e94a78d0abb2"}, + {file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:55f44b440d491028addb3b88f72207d71eeebfb7b5dbf0643f7c023ae1fba619"}, + {file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:a6f2fcca746e8d5910e18782f976489939d54a91f9411c32051b4aab2bd7c513"}, + {file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:0b462104ba25f1ac006fdab8b6a01ebbfbce9ed37fd37fd4acd70c67c973e460"}, + {file = "MarkupSafe-2.1.2-cp37-cp37m-win32.whl", hash = "sha256:7668b52e102d0ed87cb082380a7e2e1e78737ddecdde129acadb0eccc5423859"}, + {file = "MarkupSafe-2.1.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6d6607f98fcf17e534162f0709aaad3ab7a96032723d8ac8750ffe17ae5a0666"}, + {file = "MarkupSafe-2.1.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:a806db027852538d2ad7555b203300173dd1b77ba116de92da9afbc3a3be3eed"}, + {file = "MarkupSafe-2.1.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a4abaec6ca3ad8660690236d11bfe28dfd707778e2442b45addd2f086d6ef094"}, + {file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f03a532d7dee1bed20bc4884194a16160a2de9ffc6354b3878ec9682bb623c54"}, + {file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4cf06cdc1dda95223e9d2d3c58d3b178aa5dacb35ee7e3bbac10e4e1faacb419"}, + {file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:22731d79ed2eb25059ae3df1dfc9cb1546691cc41f4e3130fe6bfbc3ecbbecfa"}, + {file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f8ffb705ffcf5ddd0e80b65ddf7bed7ee4f5a441ea7d3419e861a12eaf41af58"}, + {file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8db032bf0ce9022a8e41a22598eefc802314e81b879ae093f36ce9ddf39ab1ba"}, + {file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2298c859cfc5463f1b64bd55cb3e602528db6fa0f3cfd568d3605c50678f8f03"}, + {file = "MarkupSafe-2.1.2-cp38-cp38-win32.whl", hash = "sha256:50c42830a633fa0cf9e7d27664637532791bfc31c731a87b202d2d8ac40c3ea2"}, + {file = "MarkupSafe-2.1.2-cp38-cp38-win_amd64.whl", hash = "sha256:bb06feb762bade6bf3c8b844462274db0c76acc95c52abe8dbed28ae3d44a147"}, + {file = "MarkupSafe-2.1.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:99625a92da8229df6d44335e6fcc558a5037dd0a760e11d84be2260e6f37002f"}, + {file = "MarkupSafe-2.1.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8bca7e26c1dd751236cfb0c6c72d4ad61d986e9a41bbf76cb445f69488b2a2bd"}, + {file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40627dcf047dadb22cd25ea7ecfe9cbf3bbbad0482ee5920b582f3809c97654f"}, + {file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40dfd3fefbef579ee058f139733ac336312663c6706d1163b82b3003fb1925c4"}, + {file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:090376d812fb6ac5f171e5938e82e7f2d7adc2b629101cec0db8b267815c85e2"}, + {file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2e7821bffe00aa6bd07a23913b7f4e01328c3d5cc0b40b36c0bd81d362faeb65"}, + {file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:c0a33bc9f02c2b17c3ea382f91b4db0e6cde90b63b296422a939886a7a80de1c"}, + {file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:b8526c6d437855442cdd3d87eede9c425c4445ea011ca38d937db299382e6fa3"}, + {file = "MarkupSafe-2.1.2-cp39-cp39-win32.whl", hash = "sha256:137678c63c977754abe9086a3ec011e8fd985ab90631145dfb9294ad09c102a7"}, + {file = "MarkupSafe-2.1.2-cp39-cp39-win_amd64.whl", hash = "sha256:0576fe974b40a400449768941d5d0858cc624e3249dfd1e0c33674e5c7ca7aed"}, + {file = "MarkupSafe-2.1.2.tar.gz", hash = "sha256:abcabc8c2b26036d62d4c746381a6f7cf60aafcc653198ad678306986b09450d"}, +] + +[[package]] +name = "psutil" +version = "5.9.4" +description = "Cross-platform lib for process and system monitoring in Python." +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "psutil-5.9.4-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:c1ca331af862803a42677c120aff8a814a804e09832f166f226bfd22b56feee8"}, + {file = "psutil-5.9.4-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:68908971daf802203f3d37e78d3f8831b6d1014864d7a85937941bb35f09aefe"}, + {file = "psutil-5.9.4-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:3ff89f9b835100a825b14c2808a106b6fdcc4b15483141482a12c725e7f78549"}, + {file = "psutil-5.9.4-cp27-cp27m-win32.whl", hash = "sha256:852dd5d9f8a47169fe62fd4a971aa07859476c2ba22c2254d4a1baa4e10b95ad"}, + {file = "psutil-5.9.4-cp27-cp27m-win_amd64.whl", hash = "sha256:9120cd39dca5c5e1c54b59a41d205023d436799b1c8c4d3ff71af18535728e94"}, + {file = "psutil-5.9.4-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:6b92c532979bafc2df23ddc785ed116fced1f492ad90a6830cf24f4d1ea27d24"}, + {file = "psutil-5.9.4-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:efeae04f9516907be44904cc7ce08defb6b665128992a56957abc9b61dca94b7"}, + {file = "psutil-5.9.4-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:54d5b184728298f2ca8567bf83c422b706200bcbbfafdc06718264f9393cfeb7"}, + {file = "psutil-5.9.4-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:16653106f3b59386ffe10e0bad3bb6299e169d5327d3f187614b1cb8f24cf2e1"}, + {file = "psutil-5.9.4-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:54c0d3d8e0078b7666984e11b12b88af2db11d11249a8ac8920dd5ef68a66e08"}, + {file = "psutil-5.9.4-cp36-abi3-win32.whl", hash = "sha256:149555f59a69b33f056ba1c4eb22bb7bf24332ce631c44a319cec09f876aaeff"}, + {file = "psutil-5.9.4-cp36-abi3-win_amd64.whl", hash = "sha256:fd8522436a6ada7b4aad6638662966de0d61d241cb821239b2ae7013d41a43d4"}, + {file = "psutil-5.9.4-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:6001c809253a29599bc0dfd5179d9f8a5779f9dffea1da0f13c53ee568115e1e"}, + {file = "psutil-5.9.4.tar.gz", hash = "sha256:3d7f9739eb435d4b1338944abe23f49584bde5395f27487d2ee25ad9a8774a62"}, +] + +[package.extras] +test = ["enum34", "ipaddress", "mock", "pywin32", "wmi"] + +[[package]] +name = "pyasn1" +version = "0.4.8" +description = "ASN.1 types and codecs" +category = "main" +optional = false +python-versions = "*" +files = [ + {file = "pyasn1-0.4.8-py2.py3-none-any.whl", hash = "sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d"}, + {file = "pyasn1-0.4.8.tar.gz", hash = "sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba"}, +] + +[[package]] +name = "pycparser" +version = "2.21" +description = "C parser in Python" +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, + {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, +] + +[[package]] +name = "pycryptodomex" +version = "3.17" +description = "Cryptographic library for Python" +category = "main" +optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "pycryptodomex-3.17-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:12056c38e49d972f9c553a3d598425f8a1c1d35b2e4330f89d5ff1ffb70de041"}, + {file = "pycryptodomex-3.17-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:ab33c2d9f275e05e235dbca1063753b5346af4a5cac34a51fa0da0d4edfb21d7"}, + {file = "pycryptodomex-3.17-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:caa937ff29d07a665dfcfd7a84f0d4207b2ebf483362fa9054041d67fdfacc20"}, + {file = "pycryptodomex-3.17-cp27-cp27m-manylinux2014_aarch64.whl", hash = "sha256:db23d7341e21b273d2440ec6faf6c8b1ca95c8894da612e165be0b89a8688340"}, + {file = "pycryptodomex-3.17-cp27-cp27m-musllinux_1_1_aarch64.whl", hash = "sha256:f854c8476512cebe6a8681cc4789e4fcff6019c17baa0fd72b459155dc605ab4"}, + {file = "pycryptodomex-3.17-cp27-cp27m-win32.whl", hash = "sha256:a57e3257bacd719769110f1f70dd901c5b6955e9596ad403af11a3e6e7e3311c"}, + {file = "pycryptodomex-3.17-cp27-cp27m-win_amd64.whl", hash = "sha256:d38ab9e53b1c09608ba2d9b8b888f1e75d6f66e2787e437adb1fecbffec6b112"}, + {file = "pycryptodomex-3.17-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:3c2516b42437ae6c7a29ef3ddc73c8d4714e7b6df995b76be4695bbe4b3b5cd2"}, + {file = "pycryptodomex-3.17-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:5c23482860302d0d9883404eaaa54b0615eefa5274f70529703e2c43cc571827"}, + {file = "pycryptodomex-3.17-cp27-cp27mu-manylinux2014_aarch64.whl", hash = "sha256:7a8dc3ee7a99aae202a4db52de5a08aa4d01831eb403c4d21da04ec2f79810db"}, + {file = "pycryptodomex-3.17-cp27-cp27mu-musllinux_1_1_aarch64.whl", hash = "sha256:7cc28dd33f1f3662d6da28ead4f9891035f63f49d30267d3b41194c8778997c8"}, + {file = "pycryptodomex-3.17-cp35-abi3-macosx_10_9_universal2.whl", hash = "sha256:2d4d395f109faba34067a08de36304e846c791808524614c731431ee048fe70a"}, + {file = "pycryptodomex-3.17-cp35-abi3-macosx_10_9_x86_64.whl", hash = "sha256:55eed98b4150a744920597c81b3965b632038781bab8a08a12ea1d004213c600"}, + {file = "pycryptodomex-3.17-cp35-abi3-manylinux2014_aarch64.whl", hash = "sha256:7fa0b52df90343fafe319257b31d909be1d2e8852277fb0376ba89d26d2921db"}, + {file = "pycryptodomex-3.17-cp35-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78f0ddd4adc64baa39b416f3637aaf99f45acb0bcdc16706f0cc7ebfc6f10109"}, + {file = "pycryptodomex-3.17-cp35-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a4fa037078e92c7cc49f6789a8bac3de06856740bb2038d05f2d9a2e4b165d59"}, + {file = "pycryptodomex-3.17-cp35-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:88b0d5bb87eaf2a31e8a759302b89cf30c97f2f8ca7d83b8c9208abe8acb447a"}, + {file = "pycryptodomex-3.17-cp35-abi3-musllinux_1_1_i686.whl", hash = "sha256:6feedf4b0e36b395329b4186a805f60f900129cdf0170e120ecabbfcb763995d"}, + {file = "pycryptodomex-3.17-cp35-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:7a6651a07f67c28b6e978d63aa3a3fccea0feefed9a8453af3f7421a758461b7"}, + {file = "pycryptodomex-3.17-cp35-abi3-win32.whl", hash = "sha256:32e764322e902bbfac49ca1446604d2839381bbbdd5a57920c9daaf2e0b778df"}, + {file = "pycryptodomex-3.17-cp35-abi3-win_amd64.whl", hash = "sha256:4b51e826f0a04d832eda0790bbd0665d9bfe73e5a4d8ea93b6a9b38beeebe935"}, + {file = "pycryptodomex-3.17-pp27-pypy_73-macosx_10_9_x86_64.whl", hash = "sha256:d4cf0128da167562c49b0e034f09e9cedd733997354f2314837c2fa461c87bb1"}, + {file = "pycryptodomex-3.17-pp27-pypy_73-manylinux2010_x86_64.whl", hash = "sha256:c92537b596bd5bffb82f8964cabb9fef1bca8a28a9e0a69ffd3ec92a4a7ad41b"}, + {file = "pycryptodomex-3.17-pp27-pypy_73-win32.whl", hash = "sha256:599bb4ae4bbd614ca05f49bd4e672b7a250b80b13ae1238f05fd0f09d87ed80a"}, + {file = "pycryptodomex-3.17-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:4c4674f4b040321055c596aac926d12f7f6859dfe98cd12f4d9453b43ab6adc8"}, + {file = "pycryptodomex-3.17-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67a3648025e4ddb72d43addab764336ba2e670c8377dba5dd752e42285440d31"}, + {file = "pycryptodomex-3.17-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40e8a11f578bd0851b02719c862d55d3ee18d906c8b68a9c09f8c564d6bb5b92"}, + {file = "pycryptodomex-3.17-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:23d83b610bd97704f0cd3acc48d99b76a15c8c1540d8665c94d514a49905bad7"}, + {file = "pycryptodomex-3.17-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:fd29d35ac80755e5c0a99d96b44fb9abbd7e871849581ea6a4cb826d24267537"}, + {file = "pycryptodomex-3.17-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64b876d57cb894b31056ad8dd6a6ae1099b117ae07a3d39707221133490e5715"}, + {file = "pycryptodomex-3.17-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee8bf4fdcad7d66beb744957db8717afc12d176e3fd9c5d106835133881a049b"}, + {file = "pycryptodomex-3.17-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:c84689c73358dfc23f9fdcff2cb9e7856e65e2ce3b5ed8ff630d4c9bdeb1867b"}, + {file = "pycryptodomex-3.17.tar.gz", hash = "sha256:0af93aad8d62e810247beedef0261c148790c52f3cd33643791cc6396dd217c1"}, +] + +[[package]] +name = "pyopenssl" +version = "23.0.0" +description = "Python wrapper module around the OpenSSL library" +category = "main" +optional = false +python-versions = ">=3.6" +files = [ + {file = "pyOpenSSL-23.0.0-py3-none-any.whl", hash = "sha256:df5fc28af899e74e19fccb5510df423581047e10ab6f1f4ba1763ff5fde844c0"}, + {file = "pyOpenSSL-23.0.0.tar.gz", hash = "sha256:c1cc5f86bcacefc84dada7d31175cae1b1518d5f60d3d0bb595a67822a868a6f"}, +] + +[package.dependencies] +cryptography = ">=38.0.0,<40" + +[package.extras] +docs = ["sphinx (!=5.2.0,!=5.2.0.post0)", "sphinx-rtd-theme"] +test = ["flaky", "pretend", "pytest (>=3.0.1)"] + +[[package]] +name = "requests" +version = "2.28.2" +description = "Python HTTP for Humans." +category = "main" +optional = false +python-versions = ">=3.7, <4" +files = [ + {file = "requests-2.28.2-py3-none-any.whl", hash = "sha256:64299f4909223da747622c030b781c0d7811e359c37124b4bd368fb8c6518baa"}, + {file = "requests-2.28.2.tar.gz", hash = "sha256:98b1b2782e3c6c4904938b84c0eb932721069dfdb9134313beff7c83c2df24bf"}, +] + +[package.dependencies] +certifi = ">=2017.4.17" +charset-normalizer = ">=2,<4" +idna = ">=2.5,<4" +urllib3 = ">=1.21.1,<1.27" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7)"] +use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] + +[[package]] +name = "six" +version = "1.16.0" +description = "Python 2 and 3 compatibility utilities" +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] [[package]] name = "toml" @@ -21,34 +670,75 @@ description = "Python Library for Tom's Obvious, Minimal Language" category = "main" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, + {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, +] [[package]] name = "unidecode" -version = "1.3.2" +version = "1.3.6" description = "ASCII transliterations of Unicode text" category = "main" optional = false python-versions = ">=3.5" - -[metadata] -lock-version = "1.1" -python-versions = "^3.7" -content-hash = "681db41aa556d6d3f79e1e8ee0107bccd078e39c8db7e6e0159860c96ea93c5b" - -[metadata.files] -appdirs = [ - {file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"}, - {file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"}, +files = [ + {file = "Unidecode-1.3.6-py3-none-any.whl", hash = "sha256:547d7c479e4f377b430dd91ac1275d593308dce0fc464fb2ab7d41f82ec653be"}, + {file = "Unidecode-1.3.6.tar.gz", hash = "sha256:fed09cf0be8cf415b391642c2a5addfc72194407caee4f98719e40ec2a72b830"}, ] -colorama = [ - {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, - {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, + +[[package]] +name = "urllib3" +version = "1.26.14" +description = "HTTP library with thread-safe connection pooling, file post, and more." +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +files = [ + {file = "urllib3-1.26.14-py2.py3-none-any.whl", hash = "sha256:75edcdc2f7d85b137124a6c3c9fc3933cdeaa12ecb9a6a959f22797a0feca7e1"}, + {file = "urllib3-1.26.14.tar.gz", hash = "sha256:076907bf8fd355cde77728471316625a4d2f7e713c125f51953bb5b3eecf4f72"}, ] -toml = [ - {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, - {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, + +[package.extras] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] +secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] +socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] + +[[package]] +name = "werkzeug" +version = "2.2.3" +description = "The comprehensive WSGI web application library." +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "Werkzeug-2.2.3-py3-none-any.whl", hash = "sha256:56433961bc1f12533306c624f3be5e744389ac61d722175d543e1751285da612"}, + {file = "Werkzeug-2.2.3.tar.gz", hash = "sha256:2e1ccc9417d4da358b9de6f174e3ac094391ea1d4fbef2d667865d819dfd0afe"}, ] -unidecode = [ - {file = "Unidecode-1.3.2-py3-none-any.whl", hash = "sha256:215fe33c9d1c889fa823ccb66df91b02524eb8cc8c9c80f9c5b8129754d27829"}, - {file = "Unidecode-1.3.2.tar.gz", hash = "sha256:669898c1528912bcf07f9819dc60df18d057f7528271e31f8ec28cc88ef27504"}, + +[package.dependencies] +MarkupSafe = ">=2.1.1" + +[package.extras] +watchdog = ["watchdog"] + +[[package]] +name = "zipp" +version = "3.14.0" +description = "Backport of pathlib-compatible object wrapper for zip files" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "zipp-3.14.0-py3-none-any.whl", hash = "sha256:188834565033387710d046e3fe96acfc9b5e86cbca7f39ff69cf21a4128198b7"}, + {file = "zipp-3.14.0.tar.gz", hash = "sha256:9e5421e176ef5ab4c0ad896624e87a7b2f07aca746c9b2aa305952800cb8eecb"}, ] + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["flake8 (<5)", "func-timeout", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"] + +[metadata] +lock-version = "2.0" +python-versions = "^3.8" +content-hash = "274ddbd3c8b824ca1413c0a7b511a40cf96eb686316b49467dd31ff2449ea96a" From 8b29595f18d73255877f1ebf330bd6b4ebba2d4d Mon Sep 17 00:00:00 2001 From: Eli McRae Date: Mon, 20 Feb 2023 09:35:49 -0600 Subject: [PATCH 4/8] option to disable dirbuster. --- autorecon/default-plugins/__init__.py | 0 autorecon/default-plugins/bruteforce-ftp.py | 17 ++++ autorecon/default-plugins/bruteforce-http.py | 20 ++++ autorecon/default-plugins/bruteforce-rdp.py | 17 ++++ autorecon/default-plugins/bruteforce-smb.py | 17 ++++ autorecon/default-plugins/bruteforce-ssh.py | 17 ++++ .../default-plugins/curl-known-security.py | 26 ++++++ autorecon/default-plugins/curl-robots.py | 26 ++++++ autorecon/default-plugins/curl.py | 18 ++++ .../default-plugins/dns-reverse-lookup.py | 14 +++ .../default-plugins/dns-zone-transfer.py | 18 ++++ .../dnsrecon-subdomain-bruteforce.py | 27 ++++++ autorecon/default-plugins/dnsrecon.py | 30 ++++++ autorecon/default-plugins/enum4linux.py | 34 +++++++ autorecon/default-plugins/get-arch.py | 16 ++++ autorecon/default-plugins/ldap-search.py | 16 ++++ autorecon/default-plugins/lookup-sid.py | 16 ++++ autorecon/default-plugins/nbtscan.py | 17 ++++ autorecon/default-plugins/nikto.py | 16 ++++ autorecon/default-plugins/nmap-ajp.py | 14 +++ autorecon/default-plugins/nmap-cassandra.py | 14 +++ autorecon/default-plugins/nmap-cups.py | 14 +++ autorecon/default-plugins/nmap-distccd.py | 14 +++ autorecon/default-plugins/nmap-dns.py | 14 +++ autorecon/default-plugins/nmap-finger.py | 14 +++ autorecon/default-plugins/nmap-ftp.py | 14 +++ autorecon/default-plugins/nmap-http.py | 17 ++++ autorecon/default-plugins/nmap-imap.py | 14 +++ autorecon/default-plugins/nmap-irc.py | 14 +++ autorecon/default-plugins/nmap-kerberos.py | 17 ++++ autorecon/default-plugins/nmap-ldap.py | 14 +++ autorecon/default-plugins/nmap-mongodb.py | 14 +++ autorecon/default-plugins/nmap-mountd.py | 14 +++ autorecon/default-plugins/nmap-msrpc.py | 14 +++ autorecon/default-plugins/nmap-mssql.py | 18 ++++ .../default-plugins/nmap-multicast-dns.py | 14 +++ autorecon/default-plugins/nmap-mysql.py | 18 ++++ autorecon/default-plugins/nmap-nfs.py | 14 +++ autorecon/default-plugins/nmap-nntp.py | 14 +++ autorecon/default-plugins/nmap-ntp.py | 14 +++ autorecon/default-plugins/nmap-oracle.py | 17 ++++ autorecon/default-plugins/nmap-pop3.py | 14 +++ autorecon/default-plugins/nmap-rdp.py | 14 +++ autorecon/default-plugins/nmap-redis.py | 14 +++ autorecon/default-plugins/nmap-rmi.py | 14 +++ autorecon/default-plugins/nmap-rsync.py | 14 +++ autorecon/default-plugins/nmap-sip.py | 14 +++ autorecon/default-plugins/nmap-smb.py | 14 +++ autorecon/default-plugins/nmap-smtp.py | 14 +++ autorecon/default-plugins/nmap-snmp.py | 14 +++ autorecon/default-plugins/nmap-ssh.py | 14 +++ autorecon/default-plugins/nmap-telnet.py | 14 +++ autorecon/default-plugins/nmap-tftp.py | 14 +++ autorecon/default-plugins/nmap-vnc.py | 14 +++ autorecon/default-plugins/onesixtyone.py | 18 ++++ autorecon/default-plugins/oracle-odat.py | 21 +++++ autorecon/default-plugins/oracle-patator.py | 14 +++ autorecon/default-plugins/oracle-scanner.py | 20 ++++ autorecon/default-plugins/oracle-tnscmd.py | 22 +++++ .../default-plugins/portscan-all-tcp-ports.py | 52 +++++++++++ .../portscan-guess-tcp-ports.py | 48 ++++++++++ .../portscan-top-100-udp-ports.py | 40 ++++++++ autorecon/default-plugins/redis-cli.py | 24 +++++ .../default-plugins/reporting-cherrytree.py | 91 +++++++++++++++++++ .../default-plugins/reporting-markdown.py | 75 +++++++++++++++ autorecon/default-plugins/rpcclient.py | 14 +++ autorecon/default-plugins/rpcdump.py | 16 ++++ autorecon/default-plugins/rsync-list-files.py | 14 +++ autorecon/default-plugins/showmount.py | 14 +++ autorecon/default-plugins/sipvicious.py | 15 +++ autorecon/default-plugins/smb-vuln.py | 18 ++++ autorecon/default-plugins/smbclient.py | 16 ++++ autorecon/default-plugins/smbmap.py | 20 ++++ autorecon/default-plugins/smtp-user-enum.py | 20 ++++ autorecon/default-plugins/snmpwalk.py | 23 +++++ autorecon/default-plugins/sslscan.py | 16 ++++ .../default-plugins/subdomain-enumeration.py | 34 +++++++ .../virtual-host-enumeration.py | 39 ++++++++ autorecon/default-plugins/whatweb.py | 16 ++++ autorecon/default-plugins/winrm-detection.py | 32 +++++++ autorecon/default-plugins/wkhtmltoimage.py | 23 +++++ autorecon/default-plugins/wpscan.py | 20 ++++ 82 files changed, 1644 insertions(+) create mode 100644 autorecon/default-plugins/__init__.py create mode 100644 autorecon/default-plugins/bruteforce-ftp.py create mode 100644 autorecon/default-plugins/bruteforce-http.py create mode 100644 autorecon/default-plugins/bruteforce-rdp.py create mode 100644 autorecon/default-plugins/bruteforce-smb.py create mode 100644 autorecon/default-plugins/bruteforce-ssh.py create mode 100644 autorecon/default-plugins/curl-known-security.py create mode 100644 autorecon/default-plugins/curl-robots.py create mode 100644 autorecon/default-plugins/curl.py create mode 100644 autorecon/default-plugins/dns-reverse-lookup.py create mode 100644 autorecon/default-plugins/dns-zone-transfer.py create mode 100644 autorecon/default-plugins/dnsrecon-subdomain-bruteforce.py create mode 100644 autorecon/default-plugins/dnsrecon.py create mode 100644 autorecon/default-plugins/enum4linux.py create mode 100644 autorecon/default-plugins/get-arch.py create mode 100644 autorecon/default-plugins/ldap-search.py create mode 100644 autorecon/default-plugins/lookup-sid.py create mode 100644 autorecon/default-plugins/nbtscan.py create mode 100644 autorecon/default-plugins/nikto.py create mode 100644 autorecon/default-plugins/nmap-ajp.py create mode 100644 autorecon/default-plugins/nmap-cassandra.py create mode 100644 autorecon/default-plugins/nmap-cups.py create mode 100644 autorecon/default-plugins/nmap-distccd.py create mode 100644 autorecon/default-plugins/nmap-dns.py create mode 100644 autorecon/default-plugins/nmap-finger.py create mode 100644 autorecon/default-plugins/nmap-ftp.py create mode 100644 autorecon/default-plugins/nmap-http.py create mode 100644 autorecon/default-plugins/nmap-imap.py create mode 100644 autorecon/default-plugins/nmap-irc.py create mode 100644 autorecon/default-plugins/nmap-kerberos.py create mode 100644 autorecon/default-plugins/nmap-ldap.py create mode 100644 autorecon/default-plugins/nmap-mongodb.py create mode 100644 autorecon/default-plugins/nmap-mountd.py create mode 100644 autorecon/default-plugins/nmap-msrpc.py create mode 100644 autorecon/default-plugins/nmap-mssql.py create mode 100644 autorecon/default-plugins/nmap-multicast-dns.py create mode 100644 autorecon/default-plugins/nmap-mysql.py create mode 100644 autorecon/default-plugins/nmap-nfs.py create mode 100644 autorecon/default-plugins/nmap-nntp.py create mode 100644 autorecon/default-plugins/nmap-ntp.py create mode 100644 autorecon/default-plugins/nmap-oracle.py create mode 100644 autorecon/default-plugins/nmap-pop3.py create mode 100644 autorecon/default-plugins/nmap-rdp.py create mode 100644 autorecon/default-plugins/nmap-redis.py create mode 100644 autorecon/default-plugins/nmap-rmi.py create mode 100644 autorecon/default-plugins/nmap-rsync.py create mode 100644 autorecon/default-plugins/nmap-sip.py create mode 100644 autorecon/default-plugins/nmap-smb.py create mode 100644 autorecon/default-plugins/nmap-smtp.py create mode 100644 autorecon/default-plugins/nmap-snmp.py create mode 100644 autorecon/default-plugins/nmap-ssh.py create mode 100644 autorecon/default-plugins/nmap-telnet.py create mode 100644 autorecon/default-plugins/nmap-tftp.py create mode 100644 autorecon/default-plugins/nmap-vnc.py create mode 100644 autorecon/default-plugins/onesixtyone.py create mode 100644 autorecon/default-plugins/oracle-odat.py create mode 100644 autorecon/default-plugins/oracle-patator.py create mode 100644 autorecon/default-plugins/oracle-scanner.py create mode 100644 autorecon/default-plugins/oracle-tnscmd.py create mode 100644 autorecon/default-plugins/portscan-all-tcp-ports.py create mode 100644 autorecon/default-plugins/portscan-guess-tcp-ports.py create mode 100644 autorecon/default-plugins/portscan-top-100-udp-ports.py create mode 100644 autorecon/default-plugins/redis-cli.py create mode 100644 autorecon/default-plugins/reporting-cherrytree.py create mode 100644 autorecon/default-plugins/reporting-markdown.py create mode 100644 autorecon/default-plugins/rpcclient.py create mode 100644 autorecon/default-plugins/rpcdump.py create mode 100644 autorecon/default-plugins/rsync-list-files.py create mode 100644 autorecon/default-plugins/showmount.py create mode 100644 autorecon/default-plugins/sipvicious.py create mode 100644 autorecon/default-plugins/smb-vuln.py create mode 100644 autorecon/default-plugins/smbclient.py create mode 100644 autorecon/default-plugins/smbmap.py create mode 100644 autorecon/default-plugins/smtp-user-enum.py create mode 100644 autorecon/default-plugins/snmpwalk.py create mode 100644 autorecon/default-plugins/sslscan.py create mode 100644 autorecon/default-plugins/subdomain-enumeration.py create mode 100644 autorecon/default-plugins/virtual-host-enumeration.py create mode 100644 autorecon/default-plugins/whatweb.py create mode 100644 autorecon/default-plugins/winrm-detection.py create mode 100644 autorecon/default-plugins/wkhtmltoimage.py create mode 100644 autorecon/default-plugins/wpscan.py diff --git a/autorecon/default-plugins/__init__.py b/autorecon/default-plugins/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/autorecon/default-plugins/bruteforce-ftp.py b/autorecon/default-plugins/bruteforce-ftp.py new file mode 100644 index 0000000..24cd7c8 --- /dev/null +++ b/autorecon/default-plugins/bruteforce-ftp.py @@ -0,0 +1,17 @@ +from autorecon.plugins import ServiceScan + +class BruteforceFTP(ServiceScan): + + def __init__(self): + super().__init__() + self.name = "Bruteforce FTP" + self.tags = ['default', 'ftp'] + + def configure(self): + self.match_service_name(['^ftp', '^ftp\-data']) + + def manual(self, service, plugin_was_run): + service.add_manual_commands('Bruteforce logins:', [ + 'hydra -L "' + self.get_global('username_wordlist', default='/usr/share/seclists/Usernames/top-usernames-shortlist.txt') + '" -P "' + self.get_global('password_wordlist', default='/usr/share/seclists/Passwords/darkweb2017-top100.txt') + '" -e nsr -s {port} -o "{scandir}/{protocol}_{port}_ftp_hydra.txt" ftp://{addressv6}', + 'medusa -U "' + self.get_global('username_wordlist', default='/usr/share/seclists/Usernames/top-usernames-shortlist.txt') + '" -P "' + self.get_global('password_wordlist', default='/usr/share/seclists/Passwords/darkweb2017-top100.txt') + '" -e ns -n {port} -O "{scandir}/{protocol}_{port}_ftp_medusa.txt" -M ftp -h {addressv6}' + ]) diff --git a/autorecon/default-plugins/bruteforce-http.py b/autorecon/default-plugins/bruteforce-http.py new file mode 100644 index 0000000..d735ac4 --- /dev/null +++ b/autorecon/default-plugins/bruteforce-http.py @@ -0,0 +1,20 @@ +from autorecon.plugins import ServiceScan + +class BruteforceHTTP(ServiceScan): + + def __init__(self): + super().__init__() + self.name = "Bruteforce HTTP" + self.tags = ['default', 'http'] + + def configure(self): + self.match_service_name('^http') + self.match_service_name('^nacn_http$', negative_match=True) + + def manual(self, service, plugin_was_run): + service.add_manual_commands('Credential bruteforcing commands (don\'t run these without modifying them):', [ + 'hydra -L "' + self.get_global('username_wordlist', default='/usr/share/seclists/Usernames/top-usernames-shortlist.txt') + '" -P "' + self.get_global('password_wordlist', default='/usr/share/seclists/Passwords/darkweb2017-top100.txt') + '" -e nsr -s {port} -o "{scandir}/{protocol}_{port}_{http_scheme}_auth_hydra.txt" {http_scheme}-get://{addressv6}/path/to/auth/area', + 'medusa -U "' + self.get_global('username_wordlist', default='/usr/share/seclists/Usernames/top-usernames-shortlist.txt') + '" -P "' + self.get_global('password_wordlist', default='/usr/share/seclists/Passwords/darkweb2017-top100.txt') + '" -e ns -n {port} -O "{scandir}/{protocol}_{port}_{http_scheme}_auth_medusa.txt" -M http -h {addressv6} -m DIR:/path/to/auth/area', + 'hydra -L "' + self.get_global('username_wordlist', default='/usr/share/seclists/Usernames/top-usernames-shortlist.txt') + '" -P "' + self.get_global('password_wordlist', default='/usr/share/seclists/Passwords/darkweb2017-top100.txt') + '" -e nsr -s {port} -o "{scandir}/{protocol}_{port}_{http_scheme}_form_hydra.txt" {http_scheme}-post-form://{addressv6}/path/to/login.php:"username=^USER^&password=^PASS^":"invalid-login-message"', + 'medusa -U "' + self.get_global('username_wordlist', default='/usr/share/seclists/Usernames/top-usernames-shortlist.txt') + '" -P "' + self.get_global('password_wordlist', default='/usr/share/seclists/Passwords/darkweb2017-top100.txt') + '" -e ns -n {port} -O "{scandir}/{protocol}_{port}_{http_scheme}_form_medusa.txt" -M web-form -h {addressv6} -m FORM:/path/to/login.php -m FORM-DATA:"post?username=&password=" -m DENY-SIGNAL:"invalid login message"' + ]) diff --git a/autorecon/default-plugins/bruteforce-rdp.py b/autorecon/default-plugins/bruteforce-rdp.py new file mode 100644 index 0000000..fb38e82 --- /dev/null +++ b/autorecon/default-plugins/bruteforce-rdp.py @@ -0,0 +1,17 @@ +from autorecon.plugins import ServiceScan + +class BruteforceRDP(ServiceScan): + + def __init__(self): + super().__init__() + self.name = "Bruteforce RDP" + self.tags = ['default', 'rdp'] + + def configure(self): + self.match_service_name(['^rdp', '^ms\-wbt\-server', '^ms\-term\-serv']) + + def manual(self, service, plugin_was_run): + service.add_manual_commands('Bruteforce logins:', [ + 'hydra -L "' + self.get_global('username_wordlist', default='/usr/share/seclists/Usernames/top-usernames-shortlist.txt') + '" -P "' + self.get_global('password_wordlist', default='/usr/share/seclists/Passwords/darkweb2017-top100.txt') + '" -e nsr -s {port} -o "{scandir}/{protocol}_{port}_rdp_hydra.txt" rdp://{addressv6}', + 'medusa -U "' + self.get_global('username_wordlist', default='/usr/share/seclists/Usernames/top-usernames-shortlist.txt') + '" -P "' + self.get_global('password_wordlist', default='/usr/share/seclists/Passwords/darkweb2017-top100.txt') + '" -e ns -n {port} -O "{scandir}/{protocol}_{port}_rdp_medusa.txt" -M rdp -h {addressv6}' + ]) diff --git a/autorecon/default-plugins/bruteforce-smb.py b/autorecon/default-plugins/bruteforce-smb.py new file mode 100644 index 0000000..da658cc --- /dev/null +++ b/autorecon/default-plugins/bruteforce-smb.py @@ -0,0 +1,17 @@ +from autorecon.plugins import ServiceScan + +class BruteforceSMB(ServiceScan): + + def __init__(self): + super().__init__() + self.name = 'Bruteforce SMB' + self.tags = ['default', 'safe', 'active-directory'] + + def configure(self): + self.match_service('tcp', 445, '^microsoft\-ds') + self.match_service('tcp', 139, '^netbios') + + def manual(self, service, plugin_was_run): + service.add_manual_command('Bruteforce SMB', [ + 'crackmapexec smb {address} --port={port} -u "' + self.get_global('username_wordlist', default='/usr/share/seclists/Usernames/top-usernames-shortlist.txt') + '" -p "' + self.get_global('password_wordlist', default='/usr/share/seclists/Passwords/darkweb2017-top100.txt') + '"' + ]) diff --git a/autorecon/default-plugins/bruteforce-ssh.py b/autorecon/default-plugins/bruteforce-ssh.py new file mode 100644 index 0000000..75bb436 --- /dev/null +++ b/autorecon/default-plugins/bruteforce-ssh.py @@ -0,0 +1,17 @@ +from autorecon.plugins import ServiceScan + +class BruteforceSSH(ServiceScan): + + def __init__(self): + super().__init__() + self.name = "Bruteforce SSH" + self.tags = ['default', 'ssh'] + + def configure(self): + self.match_service_name('ssh') + + def manual(self, service, plugin_was_run): + service.add_manual_command('Bruteforce logins:', [ + 'hydra -L "' + self.get_global('username_wordlist', default='/usr/share/seclists/Usernames/top-usernames-shortlist.txt') + '" -P "' + self.get_global('password_wordlist', default='/usr/share/seclists/Passwords/darkweb2017-top100.txt') + '" -e nsr -s {port} -o "{scandir}/{protocol}_{port}_ssh_hydra.txt" ssh://{addressv6}', + 'medusa -U "' + self.get_global('username_wordlist', default='/usr/share/seclists/Usernames/top-usernames-shortlist.txt') + '" -P "' + self.get_global('password_wordlist', default='/usr/share/seclists/Passwords/darkweb2017-top100.txt') + '" -e ns -n {port} -O "{scandir}/{protocol}_{port}_ssh_medusa.txt" -M ssh -h {addressv6}' + ]) diff --git a/autorecon/default-plugins/curl-known-security.py b/autorecon/default-plugins/curl-known-security.py new file mode 100644 index 0000000..554db9e --- /dev/null +++ b/autorecon/default-plugins/curl-known-security.py @@ -0,0 +1,26 @@ +from autorecon.plugins import ServiceScan +from autorecon.io import fformat + +class CurlKnownSecurity(ServiceScan): + + def __init__(self): + super().__init__() + self.name = "Known Security" + self.tags = ['default', 'safe', 'http'] + + def configure(self): + self.match_service_name('^http') + self.match_service_name('^nacn_http$', negative_match=True) + + async def run(self, service): + if service.protocol == 'tcp': + process, stdout, _ = await service.execute('curl -sSikf {http_scheme}://{addressv6}:{port}/.well-known/security.txt', future_outfile='{protocol}_{port}_{http_scheme}_known-security.txt') + + lines = await stdout.readlines() + + if process.returncode == 0 and lines: + filename = fformat('{scandir}/{protocol}_{port}_{http_scheme}_known-security.txt') + with open(filename, mode='wt', encoding='utf8') as robots: + robots.write('\n'.join(lines)) + else: + service.info('{bblue}[' + fformat('{tag}') + ']{rst} There did not appear to be a .well-known/security.txt file in the webroot (/).') diff --git a/autorecon/default-plugins/curl-robots.py b/autorecon/default-plugins/curl-robots.py new file mode 100644 index 0000000..7158b25 --- /dev/null +++ b/autorecon/default-plugins/curl-robots.py @@ -0,0 +1,26 @@ +from autorecon.plugins import ServiceScan +from autorecon.io import fformat + +class CurlRobots(ServiceScan): + + def __init__(self): + super().__init__() + self.name = "Curl Robots" + self.tags = ['default', 'safe', 'http'] + + def configure(self): + self.match_service_name('^http') + self.match_service_name('^nacn_http$', negative_match=True) + + async def run(self, service): + if service.protocol == 'tcp': + process, stdout, _ = await service.execute('curl -sSikf {http_scheme}://{addressv6}:{port}/robots.txt', future_outfile='{protocol}_{port}_{http_scheme}_curl-robots.txt') + + lines = await stdout.readlines() + + if process.returncode == 0 and lines: + filename = fformat('{scandir}/{protocol}_{port}_{http_scheme}_curl-robots.txt') + with open(filename, mode='wt', encoding='utf8') as robots: + robots.write('\n'.join(lines)) + else: + service.info('{bblue}[' + fformat('{tag}') + ']{rst} There did not appear to be a robots.txt file in the webroot (/).') diff --git a/autorecon/default-plugins/curl.py b/autorecon/default-plugins/curl.py new file mode 100644 index 0000000..5155f50 --- /dev/null +++ b/autorecon/default-plugins/curl.py @@ -0,0 +1,18 @@ +from autorecon.plugins import ServiceScan + +class Curl(ServiceScan): + + def __init__(self): + super().__init__() + self.name = "Curl" + self.tags = ['default', 'safe', 'http'] + + def configure(self): + self.add_option("path", default="/", help="The path on the web server to curl. Default: %(default)s") + self.match_service_name('^http') + self.match_service_name('^nacn_http$', negative_match=True) + self.add_pattern('(?i)powered[ -]by[^\n]+') + + async def run(self, service): + if service.protocol == 'tcp': + await service.execute('curl -sSik {http_scheme}://{addressv6}:{port}' + self.get_option('path'), outfile='{protocol}_{port}_{http_scheme}_curl.html') diff --git a/autorecon/default-plugins/dns-reverse-lookup.py b/autorecon/default-plugins/dns-reverse-lookup.py new file mode 100644 index 0000000..513cba5 --- /dev/null +++ b/autorecon/default-plugins/dns-reverse-lookup.py @@ -0,0 +1,14 @@ +from autorecon.plugins import ServiceScan + +class DNSReverseLookup(ServiceScan): + + def __init__(self): + super().__init__() + self.name = 'DNS Reverse Lookup' + self.tags = ['default', 'safe', 'dns'] + + def configure(self): + self.match_service_name('^domain') + + async def run(self, service): + await service.execute('dig -p {port} -x {address} @{address}', outfile='{protocol}_{port}_dns_reverse-lookup.txt') diff --git a/autorecon/default-plugins/dns-zone-transfer.py b/autorecon/default-plugins/dns-zone-transfer.py new file mode 100644 index 0000000..49bb9cb --- /dev/null +++ b/autorecon/default-plugins/dns-zone-transfer.py @@ -0,0 +1,18 @@ +from autorecon.plugins import ServiceScan + +class DNSZoneTransfer(ServiceScan): + + def __init__(self): + super().__init__() + self.name = 'DNS Zone Transfer' + self.tags = ['default', 'safe', 'dns'] + + def configure(self): + self.match_service_name('^domain') + + async def run(self, service): + if self.get_global('domain'): + await service.execute('dig AXFR -p {port} @{address} ' + self.get_global('domain'), outfile='{protocol}_{port}_dns_zone-transfer-domain.txt') + if service.target.type == 'hostname': + await service.execute('dig AXFR -p {port} @{address} {address}', outfile='{protocol}_{port}_dns_zone-transfer-hostname.txt') + await service.execute('dig AXFR -p {port} @{address}', outfile='{protocol}_{port}_dns_zone-transfer.txt') diff --git a/autorecon/default-plugins/dnsrecon-subdomain-bruteforce.py b/autorecon/default-plugins/dnsrecon-subdomain-bruteforce.py new file mode 100644 index 0000000..8f082bb --- /dev/null +++ b/autorecon/default-plugins/dnsrecon-subdomain-bruteforce.py @@ -0,0 +1,27 @@ +from autorecon.plugins import ServiceScan +from shutil import which + +class DnsReconSubdomainBruteforce(ServiceScan): + + def __init__(self): + super().__init__() + self.name = "DnsRecon Bruteforce Subdomains" + self.slug = 'dnsrecon-brute' + self.priority = 0 + self.tags = ['default', 'safe', 'long', 'dns'] + + def configure(self): + self.match_service_name('^domain') + + def check(self): + if which('dnsrecon') is None: + self.error('The program dnsrecon could not be found. Make sure it is installed. (On Kali, run: sudo apt install dnsrecon)') + return False + + def manual(self, service, plugin_was_run): + domain_name = '' + if self.get_global('domain'): + domain_name = self.get_global('domain') + service.add_manual_command('Use dnsrecon to bruteforce subdomains of a DNS domain.', [ + 'dnsrecon -n {address} -d ' + domain_name + ' -D /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt -t brt 2>&1 | tee {scandir}/{protocol}_{port}_dnsrecon_subdomain_bruteforce.txt', + ]) diff --git a/autorecon/default-plugins/dnsrecon.py b/autorecon/default-plugins/dnsrecon.py new file mode 100644 index 0000000..cfb9edc --- /dev/null +++ b/autorecon/default-plugins/dnsrecon.py @@ -0,0 +1,30 @@ +from autorecon.plugins import ServiceScan +from shutil import which + +class DnsRecon(ServiceScan): + + def __init__(self): + super().__init__() + self.name = "DnsRecon Default Scan" + self.slug = 'dnsrecon' + self.priority = 0 + self.tags = ['default', 'safe', 'dns'] + + def configure(self): + self.match_service_name('^domain') + + def check(self): + if which('dnsrecon') is None: + self.error('The program dnsrecon could not be found. Make sure it is installed. (On Kali, run: sudo apt install dnsrecon)') + return False + + def manual(self, service, plugin_was_run): + service.add_manual_command('Use dnsrecon to automatically query data from the DNS server. You must specify the target domain name.', [ + 'dnsrecon -n {address} -d 2>&1 | tee {scandir}/{protocol}_{port}_dnsrecon_default_manual.txt' + ]) + + async def run(self, service): + if self.get_global('domain'): + await service.execute('dnsrecon -n {address} -d ' + self.get_global('domain') + ' 2>&1', outfile='{protocol}_{port}_dnsrecon_default.txt') + else: + service.error('A domain name was not specified in the command line options (--global.domain). If you know the domain name, look in the _manual_commands.txt file for the dnsrecon command.') diff --git a/autorecon/default-plugins/enum4linux.py b/autorecon/default-plugins/enum4linux.py new file mode 100644 index 0000000..ac3e787 --- /dev/null +++ b/autorecon/default-plugins/enum4linux.py @@ -0,0 +1,34 @@ +from autorecon.plugins import ServiceScan +from shutil import which + +class Enum4Linux(ServiceScan): + + def __init__(self): + super().__init__() + self.name = "Enum4Linux" + self.tags = ['default', 'safe', 'active-directory'] + + def configure(self): + self.add_choice_option('tool', default=('enum4linux-ng' if which('enum4linux-ng') else 'enum4linux'), choices=['enum4linux-ng', 'enum4linux'], help='The tool to use for doing Windows and Samba enumeration. Default: %(default)s') + self.match_service_name(['^ldap', '^smb', '^microsoft\-ds', '^netbios']) + self.match_port('tcp', [139, 389, 445]) + self.match_port('udp', 137) + self.run_once(True) + + def check(self): + tool = self.get_option('tool') + if tool == 'enum4linux' and which('enum4linux') is None: + self.error('The enum4linux program could not be found. Make sure it is installed. (On Kali, run: sudo apt install enum4linux)') + return False + elif tool == 'enum4linux-ng' and which('enum4linux-ng') is None: + self.error('The enum4linux-ng program could not be found. Make sure it is installed. (https://github.com/cddmp/enum4linux-ng)') + return False + + async def run(self, service): + if service.target.ipversion == 'IPv4': + tool = self.get_option('tool') + if tool is not None: + if tool == 'enum4linux': + await service.execute('enum4linux -a -M -l -d {address} 2>&1', outfile='enum4linux.txt') + elif tool == 'enum4linux-ng': + await service.execute('enum4linux-ng -A -d -v {address} 2>&1', outfile='enum4linux-ng.txt') diff --git a/autorecon/default-plugins/get-arch.py b/autorecon/default-plugins/get-arch.py new file mode 100644 index 0000000..e6ee411 --- /dev/null +++ b/autorecon/default-plugins/get-arch.py @@ -0,0 +1,16 @@ +from autorecon.plugins import ServiceScan + +class GetArch(ServiceScan): + + def __init__(self): + super().__init__() + self.name = 'get-arch' + self.tags = ['default', 'safe', 'rpc'] + + def configure(self): + self.match_service_name(['^msrpc']) + self.match_port('tcp', 135) + self.add_pattern(' is ((32|64)-bit)', description='Identified Architecture: {match1}') + + async def run(self, service): + await service.execute('impacket-getArch -target {address}', outfile='{protocol}_{port}_rpc_architecture.txt') diff --git a/autorecon/default-plugins/ldap-search.py b/autorecon/default-plugins/ldap-search.py new file mode 100644 index 0000000..527d1d8 --- /dev/null +++ b/autorecon/default-plugins/ldap-search.py @@ -0,0 +1,16 @@ +from autorecon.plugins import ServiceScan + +class LDAPSearch(ServiceScan): + + def __init__(self): + super().__init__() + self.name = 'LDAP Search' + self.tags = ['default', 'safe', 'ldap', 'active-directory'] + + def configure(self): + self.match_service_name('^ldap') + + def manual(self, service, plugin_was_run): + service.add_manual_command('ldapsearch command (modify before running):', [ + 'ldapsearch -x -D "" -w "" -H ldap://{address}:{port} -b "dc=example,dc=com" -s sub "(objectclass=*)" 2>&1 | tee > "{scandir}/{protocol}_{port}_ldap_all-entries.txt"' + ]) diff --git a/autorecon/default-plugins/lookup-sid.py b/autorecon/default-plugins/lookup-sid.py new file mode 100644 index 0000000..5c4bb4d --- /dev/null +++ b/autorecon/default-plugins/lookup-sid.py @@ -0,0 +1,16 @@ +from autorecon.plugins import ServiceScan + +class LookupSID(ServiceScan): + + def __init__(self): + super().__init__() + self.name = 'lookupsid' + self.tags = ['default', 'safe', 'active-directory'] + + def configure(self): + self.match_service('tcp', 445, '^microsoft\-ds') + + def manual(self, service, plugin_was_run): + service.add_manual_command('Lookup SIDs', [ + 'impacket-lookupsid \'[username]:[password]@{address}\'' + ]) diff --git a/autorecon/default-plugins/nbtscan.py b/autorecon/default-plugins/nbtscan.py new file mode 100644 index 0000000..9036d02 --- /dev/null +++ b/autorecon/default-plugins/nbtscan.py @@ -0,0 +1,17 @@ +from autorecon.plugins import ServiceScan + +class NBTScan(ServiceScan): + + def __init__(self): + super().__init__() + self.name = 'nbtscan' + self.tags = ['default', 'safe', 'netbios', 'active-directory'] + + def configure(self): + self.match_service_name(['^smb', '^microsoft\-ds', '^netbios']) + self.match_port('udp', 137) + self.run_once(True) + + async def run(self, service): + if service.target.ipversion == 'IPv4': + await service.execute('nbtscan -rvh {ipaddress} 2>&1', outfile='nbtscan.txt') diff --git a/autorecon/default-plugins/nikto.py b/autorecon/default-plugins/nikto.py new file mode 100644 index 0000000..b696cb5 --- /dev/null +++ b/autorecon/default-plugins/nikto.py @@ -0,0 +1,16 @@ +from autorecon.plugins import ServiceScan + +class Nikto(ServiceScan): + + def __init__(self): + super().__init__() + self.name = 'nikto' + self.tags = ['default', 'safe', 'long', 'http'] + + def configure(self): + self.match_service_name('^http') + self.match_service_name('^nacn_http$', negative_match=True) + + def manual(self, service, plugin_was_run): + if service.target.ipversion == 'IPv4': + service.add_manual_command('(nikto) old but generally reliable web server enumeration tool:', 'nikto -ask=no -h {http_scheme}://{address}:{port} 2>&1 | tee "{scandir}/{protocol}_{port}_{http_scheme}_nikto.txt"') diff --git a/autorecon/default-plugins/nmap-ajp.py b/autorecon/default-plugins/nmap-ajp.py new file mode 100644 index 0000000..fcba5a0 --- /dev/null +++ b/autorecon/default-plugins/nmap-ajp.py @@ -0,0 +1,14 @@ +from autorecon.plugins import ServiceScan + +class NmapAJP(ServiceScan): + + def __init__(self): + super().__init__() + self.name = 'Nmap AJP' + self.tags = ['default', 'safe', 'ajp'] + + def configure(self): + self.match_service_name(['^ajp13']) + + async def run(self, service): + await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,(ajp-* or ssl*) and not (brute or broadcast or dos or external or fuzzer)" -oN "{scandir}/{protocol}_{port}_ajp_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_ajp_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-cassandra.py b/autorecon/default-plugins/nmap-cassandra.py new file mode 100644 index 0000000..54778a3 --- /dev/null +++ b/autorecon/default-plugins/nmap-cassandra.py @@ -0,0 +1,14 @@ +from autorecon.plugins import ServiceScan + +class NmapCassandra(ServiceScan): + + def __init__(self): + super().__init__() + self.name = "Nmap Cassandra" + self.tags = ['default', 'safe', 'cassandra'] + + def configure(self): + self.match_service_name('^apani1') + + async def run(self, service): + await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,(cassandra* or ssl*) and not (brute or broadcast or dos or external or fuzzer)" -oN "{scandir}/{protocol}_{port}_cassandra_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_cassandra_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-cups.py b/autorecon/default-plugins/nmap-cups.py new file mode 100644 index 0000000..d8d532f --- /dev/null +++ b/autorecon/default-plugins/nmap-cups.py @@ -0,0 +1,14 @@ +from autorecon.plugins import ServiceScan + +class NmapCUPS(ServiceScan): + + def __init__(self): + super().__init__() + self.name = "Nmap CUPS" + self.tags = ['default', 'safe', 'cups'] + + def configure(self): + self.match_service_name('^ipp') + + async def run(self, service): + await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,(cups* or ssl*) and not (brute or broadcast or dos or external or fuzzer)" -oN "{scandir}/{protocol}_{port}_cups_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_cups_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-distccd.py b/autorecon/default-plugins/nmap-distccd.py new file mode 100644 index 0000000..ecf99c0 --- /dev/null +++ b/autorecon/default-plugins/nmap-distccd.py @@ -0,0 +1,14 @@ +from autorecon.plugins import ServiceScan + +class NmapDistccd(ServiceScan): + + def __init__(self): + super().__init__() + self.name = "Nmap distccd" + self.tags = ['default', 'safe', 'distccd'] + + def configure(self): + self.match_service_name('^distccd') + + async def run(self, service): + await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,distcc-cve2004-2687" --script-args="distcc-cve2004-2687.cmd=id" -oN "{scandir}/{protocol}_{port}_distcc_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_distcc_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-dns.py b/autorecon/default-plugins/nmap-dns.py new file mode 100644 index 0000000..479ac42 --- /dev/null +++ b/autorecon/default-plugins/nmap-dns.py @@ -0,0 +1,14 @@ +from autorecon.plugins import ServiceScan + +class NmapDNS(ServiceScan): + + def __init__(self): + super().__init__() + self.name = 'Nmap DNS' + self.tags = ['default', 'safe', 'dns'] + + def configure(self): + self.match_service_name('^domain') + + async def run(self, service): + await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,(dns* or ssl*) and not (brute or broadcast or dos or external or fuzzer)" -oN "{scandir}/{protocol}_{port}_dns_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_dns_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-finger.py b/autorecon/default-plugins/nmap-finger.py new file mode 100644 index 0000000..2f8d38c --- /dev/null +++ b/autorecon/default-plugins/nmap-finger.py @@ -0,0 +1,14 @@ +from autorecon.plugins import ServiceScan + +class NmapFinger(ServiceScan): + + def __init__(self): + super().__init__() + self.name = "Nmap finger" + self.tags = ['default', 'safe', 'finger'] + + def configure(self): + self.match_service_name('^finger') + + async def run(self, service): + await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,finger" -oN "{scandir}/{protocol}_{port}_finger_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_finger_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-ftp.py b/autorecon/default-plugins/nmap-ftp.py new file mode 100644 index 0000000..ea87573 --- /dev/null +++ b/autorecon/default-plugins/nmap-ftp.py @@ -0,0 +1,14 @@ +from autorecon.plugins import ServiceScan + +class NmapFTP(ServiceScan): + + def __init__(self): + super().__init__() + self.name = 'Nmap FTP' + self.tags = ['default', 'safe', 'ftp'] + + def configure(self): + self.match_service_name(['^ftp', '^ftp\-data']) + + async def run(self, service): + await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,(ftp* or ssl*) and not (brute or broadcast or dos or external or fuzzer)" -oN "{scandir}/{protocol}_{port}_ftp_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_ftp_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-http.py b/autorecon/default-plugins/nmap-http.py new file mode 100644 index 0000000..0dbeb69 --- /dev/null +++ b/autorecon/default-plugins/nmap-http.py @@ -0,0 +1,17 @@ +from autorecon.plugins import ServiceScan + +class NmapHTTP(ServiceScan): + + def __init__(self): + super().__init__() + self.name = "Nmap HTTP" + self.tags = ['default', 'safe', 'http'] + + def configure(self): + self.match_service_name('^http') + self.match_service_name('^nacn_http$', negative_match=True) + self.add_pattern('Server: ([^\n]+)', description='Identified HTTP Server: {match1}') + self.add_pattern('WebDAV is ENABLED', description='WebDAV is enabled') + + async def run(self, service): + await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,(http* or ssl*) and not (brute or broadcast or dos or external or http-slowloris* or fuzzer)" -oN "{scandir}/{protocol}_{port}_{http_scheme}_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_{http_scheme}_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-imap.py b/autorecon/default-plugins/nmap-imap.py new file mode 100644 index 0000000..95d1169 --- /dev/null +++ b/autorecon/default-plugins/nmap-imap.py @@ -0,0 +1,14 @@ +from autorecon.plugins import ServiceScan + +class NmapIMAP(ServiceScan): + + def __init__(self): + super().__init__() + self.name = "Nmap IMAP" + self.tags = ['default', 'safe', 'imap', 'email'] + + def configure(self): + self.match_service_name('^imap') + + async def run(self, service): + await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,(imap* or ssl*) and not (brute or broadcast or dos or external or fuzzer)" -oN "{scandir}/{protocol}_{port}_imap_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_imap_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-irc.py b/autorecon/default-plugins/nmap-irc.py new file mode 100644 index 0000000..ebfbf45 --- /dev/null +++ b/autorecon/default-plugins/nmap-irc.py @@ -0,0 +1,14 @@ +from autorecon.plugins import ServiceScan + +class NmapIrc(ServiceScan): + + def __init__(self): + super().__init__() + self.name = 'Nmap IRC' + self.tags = ['default', 'safe', 'irc'] + + def configure(self): + self.match_service_name('^irc') + + async def run(self, service): + await service.execute('nmap {nmap_extra} -sV --script irc-botnet-channels,irc-info,irc-unrealircd-backdoor -oN "{scandir}/{protocol}_{port}_irc_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_irc_nmap.xml" -p {port} {address}') diff --git a/autorecon/default-plugins/nmap-kerberos.py b/autorecon/default-plugins/nmap-kerberos.py new file mode 100644 index 0000000..0830ff5 --- /dev/null +++ b/autorecon/default-plugins/nmap-kerberos.py @@ -0,0 +1,17 @@ +from autorecon.plugins import ServiceScan + +class NmapKerberos(ServiceScan): + + def __init__(self): + super().__init__() + self.name = "Nmap Kerberos" + self.tags = ['default', 'safe', 'kerberos', 'active-directory'] + + def configure(self): + self.match_service_name(['^kerberos', '^kpasswd']) + + async def run(self, service): + if self.get_global('domain') and self.get_global('username-wordlist'): + await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,krb5-enum-users" --script-args krb5-enum-users.realm="' + self.get_global('domain') + '",userdb="' + self.get_global('username-wordlist') + '" -oN "{scandir}/{protocol}_{port}_kerberos_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_kerberos_nmap.xml" {address}') + else: + await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,krb5-enum-users" -oN "{scandir}/{protocol}_{port}_kerberos_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_kerberos_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-ldap.py b/autorecon/default-plugins/nmap-ldap.py new file mode 100644 index 0000000..77aab20 --- /dev/null +++ b/autorecon/default-plugins/nmap-ldap.py @@ -0,0 +1,14 @@ +from autorecon.plugins import ServiceScan + +class NmapLDAP(ServiceScan): + + def __init__(self): + super().__init__() + self.name = "Nmap LDAP" + self.tags = ['default', 'safe', 'ldap', 'active-directory'] + + def configure(self): + self.match_service_name('^ldap') + + async def run(self, service): + await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,(ldap* or ssl*) and not (brute or broadcast or dos or external or fuzzer)" -oN "{scandir}/{protocol}_{port}_ldap_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_ldap_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-mongodb.py b/autorecon/default-plugins/nmap-mongodb.py new file mode 100644 index 0000000..833c628 --- /dev/null +++ b/autorecon/default-plugins/nmap-mongodb.py @@ -0,0 +1,14 @@ +from autorecon.plugins import ServiceScan + +class NmapMongoDB(ServiceScan): + + def __init__(self): + super().__init__() + self.name = "Nmap MongoDB" + self.tags = ['default', 'safe', 'databases'] + + def configure(self): + self.match_service_name('^mongod') + + async def run(self, service): + await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,(mongodb* or ssl*) and not (brute or broadcast or dos or external or fuzzer)" -oN "{scandir}/{protocol}_{port}_mongodb_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_mongodb_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-mountd.py b/autorecon/default-plugins/nmap-mountd.py new file mode 100644 index 0000000..848a77a --- /dev/null +++ b/autorecon/default-plugins/nmap-mountd.py @@ -0,0 +1,14 @@ +from autorecon.plugins import ServiceScan + +class NmapMountd(ServiceScan): + + def __init__(self): + super().__init__() + self.name = "Nmap Mountd" + self.tags = ['default', 'safe', 'nfs'] + + def configure(self): + self.match_service_name('^mountd') + + async def run(self, service): + await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,nfs* and not (brute or broadcast or dos or external or fuzzer)" -oN "{scandir}/{protocol}_{port}_mountd_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_mountd_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-msrpc.py b/autorecon/default-plugins/nmap-msrpc.py new file mode 100644 index 0000000..e374412 --- /dev/null +++ b/autorecon/default-plugins/nmap-msrpc.py @@ -0,0 +1,14 @@ +from autorecon.plugins import ServiceScan + +class NmapRPC(ServiceScan): + + def __init__(self): + super().__init__() + self.name = "Nmap MSRPC" + self.tags = ['default', 'rpc'] + + def configure(self): + self.match_service_name(['^msrpc', '^rpcbind', '^erpc']) + + async def run(self, service): + await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,msrpc-enum,rpc-grind,rpcinfo" -oN "{scandir}/{protocol}_{port}_rpc_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_rpc_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-mssql.py b/autorecon/default-plugins/nmap-mssql.py new file mode 100644 index 0000000..6e55d45 --- /dev/null +++ b/autorecon/default-plugins/nmap-mssql.py @@ -0,0 +1,18 @@ +from autorecon.plugins import ServiceScan + +class NmapMSSQL(ServiceScan): + + def __init__(self): + super().__init__() + self.name = "Nmap MSSQL" + self.tags = ['default', 'safe', 'databases'] + + def configure(self): + self.match_service_name(['^mssql', '^ms\-sql']) + + def manual(self, service, plugin_was_run): + if service.target.ipversion == 'IPv4': + service.add_manual_command('(sqsh) interactive database shell:', 'sqsh -U -P -S {address}:{port}') + + async def run(self, service): + await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,(ms-sql* or ssl*) and not (brute or broadcast or dos or external or fuzzer)" --script-args="mssql.instance-port={port},mssql.username=sa,mssql.password=sa" -oN "{scandir}/{protocol}_{port}_mssql_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_mssql_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-multicast-dns.py b/autorecon/default-plugins/nmap-multicast-dns.py new file mode 100644 index 0000000..1edb391 --- /dev/null +++ b/autorecon/default-plugins/nmap-multicast-dns.py @@ -0,0 +1,14 @@ +from autorecon.plugins import ServiceScan + +class NmapMulticastDNS(ServiceScan): + + def __init__(self): + super().__init__() + self.name = 'Nmap Multicast DNS' + self.tags = ['default', 'safe', 'dns'] + + def configure(self): + self.match_service_name(['^mdns', '^zeroconf']) + + async def run(self, service): + await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,(dns* or ssl*) and not (brute or broadcast or dos or external or fuzzer)" -oN "{scandir}/{protocol}_{port}_multicastdns_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_multicastdns_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-mysql.py b/autorecon/default-plugins/nmap-mysql.py new file mode 100644 index 0000000..68a01d5 --- /dev/null +++ b/autorecon/default-plugins/nmap-mysql.py @@ -0,0 +1,18 @@ +from autorecon.plugins import ServiceScan + +class NmapMYSQL(ServiceScan): + + def __init__(self): + super().__init__() + self.name = "Nmap MYSQL" + self.tags = ['default', 'safe', 'databases'] + + def configure(self): + self.match_service_name('^mysql') + + def manual(self, service, plugin_was_run): + if service.target.ipversion == 'IPv4': + service.add_manual_command('(sqsh) interactive database shell:', 'sqsh -U -P -S {address}:{port}') + + async def run(self, service): + await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,(mysql* or ssl*) and not (brute or broadcast or dos or external or fuzzer)" -oN "{scandir}/{protocol}_{port}_mysql_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_mysql_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-nfs.py b/autorecon/default-plugins/nmap-nfs.py new file mode 100644 index 0000000..b8fabce --- /dev/null +++ b/autorecon/default-plugins/nmap-nfs.py @@ -0,0 +1,14 @@ +from autorecon.plugins import ServiceScan + +class NmapNFS(ServiceScan): + + def __init__(self): + super().__init__() + self.name = "Nmap NFS" + self.tags = ['default', 'safe', 'nfs'] + + def configure(self): + self.match_service_name(['^nfs', '^rpcbind']) + + async def run(self, service): + await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,(rpcinfo or nfs*) and not (brute or broadcast or dos or external or fuzzer)" -oN "{scandir}/{protocol}_{port}_nfs_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_nfs_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-nntp.py b/autorecon/default-plugins/nmap-nntp.py new file mode 100644 index 0000000..1c7db5b --- /dev/null +++ b/autorecon/default-plugins/nmap-nntp.py @@ -0,0 +1,14 @@ +from autorecon.plugins import ServiceScan + +class NmapNNTP(ServiceScan): + + def __init__(self): + super().__init__() + self.name = "Nmap NNTP" + self.tags = ['default', 'safe', 'nntp'] + + def configure(self): + self.match_service_name('^nntp') + + async def run(self, service): + await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,nntp-ntlm-info" -oN "{scandir}/{protocol}_{port}_nntp_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_nntp_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-ntp.py b/autorecon/default-plugins/nmap-ntp.py new file mode 100644 index 0000000..d04679e --- /dev/null +++ b/autorecon/default-plugins/nmap-ntp.py @@ -0,0 +1,14 @@ +from autorecon.plugins import ServiceScan + +class NmapNTP(ServiceScan): + + def __init__(self): + super().__init__() + self.name = "Nmap NTP" + self.tags = ['default', 'safe', 'ntp'] + + def configure(self): + self.match_service_name('^ntp') + + async def run(self, service): + await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,(ntp* or ssl*) and not (brute or broadcast or dos or external or fuzzer)" -oN "{scandir}/{protocol}_{port}_ntp_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_ntp_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-oracle.py b/autorecon/default-plugins/nmap-oracle.py new file mode 100644 index 0000000..d8ff6bd --- /dev/null +++ b/autorecon/default-plugins/nmap-oracle.py @@ -0,0 +1,17 @@ +from autorecon.plugins import ServiceScan + +class NmapOracle(ServiceScan): + + def __init__(self): + super().__init__() + self.name = "Nmap Oracle" + self.tags = ['default', 'safe', 'databases'] + + def configure(self): + self.match_service_name('^oracle') + + def manual(self, service, plugin_was_run): + service.add_manual_command('Brute-force SIDs using Nmap:', 'nmap {nmap_extra} -sV -p {port} --script="banner,oracle-sid-brute" -oN "{scandir}/{protocol}_{port}_oracle_sid-brute_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_oracle_sid-brute_nmap.xml" {address}') + + async def run(self, service): + await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,(oracle* or ssl*) and not (brute or broadcast or dos or external or fuzzer)" -oN "{scandir}/{protocol}_{port}_oracle_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_oracle_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-pop3.py b/autorecon/default-plugins/nmap-pop3.py new file mode 100644 index 0000000..f4ed3a6 --- /dev/null +++ b/autorecon/default-plugins/nmap-pop3.py @@ -0,0 +1,14 @@ +from autorecon.plugins import ServiceScan + +class NmapPOP3(ServiceScan): + + def __init__(self): + super().__init__() + self.name = "Nmap POP3" + self.tags = ['default', 'safe', 'pop3', 'email'] + + def configure(self): + self.match_service_name('^pop3') + + async def run(self, service): + await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,(pop3* or ssl*) and not (brute or broadcast or dos or external or fuzzer)" -oN "{scandir}/{protocol}_{port}_pop3_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_pop3_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-rdp.py b/autorecon/default-plugins/nmap-rdp.py new file mode 100644 index 0000000..13a16f6 --- /dev/null +++ b/autorecon/default-plugins/nmap-rdp.py @@ -0,0 +1,14 @@ +from autorecon.plugins import ServiceScan + +class NmapRDP(ServiceScan): + + def __init__(self): + super().__init__() + self.name = "Nmap RDP" + self.tags = ['default', 'safe', 'rdp'] + + def configure(self): + self.match_service_name(['^rdp', '^ms\-wbt\-server', '^ms\-term\-serv']) + + async def run(self, service): + await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,(rdp* or ssl*) and not (brute or broadcast or dos or external or fuzzer)" -oN "{scandir}/{protocol}_{port}_rdp_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_rdp_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-redis.py b/autorecon/default-plugins/nmap-redis.py new file mode 100644 index 0000000..46fa920 --- /dev/null +++ b/autorecon/default-plugins/nmap-redis.py @@ -0,0 +1,14 @@ +from autorecon.plugins import ServiceScan + +class NmapRedis(ServiceScan): + + def __init__(self): + super().__init__() + self.name = 'Nmap Redis' + self.tags = ['default', 'safe', 'redis'] + + def configure(self): + self.match_service_name('^redis$') + + async def run(self, service): + await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,redis-info" -oN "{scandir}/{protocol}_{port}_redis_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_redis_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-rmi.py b/autorecon/default-plugins/nmap-rmi.py new file mode 100644 index 0000000..7c1d277 --- /dev/null +++ b/autorecon/default-plugins/nmap-rmi.py @@ -0,0 +1,14 @@ +from autorecon.plugins import ServiceScan + +class NmapRMI(ServiceScan): + + def __init__(self): + super().__init__() + self.name = "Nmap RMI" + self.tags = ['default', 'safe', 'rmi'] + + def configure(self): + self.match_service_name(['^java\-rmi', '^rmiregistry']) + + async def run(self, service): + await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,rmi-vuln-classloader,rmi-dumpregistry" -oN "{scandir}/{protocol}_{port}_rmi_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_rmi_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-rsync.py b/autorecon/default-plugins/nmap-rsync.py new file mode 100644 index 0000000..3e8251d --- /dev/null +++ b/autorecon/default-plugins/nmap-rsync.py @@ -0,0 +1,14 @@ +from autorecon.plugins import ServiceScan + +class NmapRsync(ServiceScan): + + def __init__(self): + super().__init__() + self.name = 'Nmap Rsync' + self.tags = ['default', 'safe', 'rsync'] + + def configure(self): + self.match_service_name('^rsync') + + async def run(self, service): + await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,(rsync* or ssl*) and not (brute or broadcast or dos or external or fuzzer)" -oN "{scandir}/{protocol}_{port}_rsync_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_rsync_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-sip.py b/autorecon/default-plugins/nmap-sip.py new file mode 100644 index 0000000..837b059 --- /dev/null +++ b/autorecon/default-plugins/nmap-sip.py @@ -0,0 +1,14 @@ +from autorecon.plugins import ServiceScan + +class NmapSIP(ServiceScan): + + def __init__(self): + super().__init__() + self.name = "Nmap SIP" + self.tags = ['default', 'safe', 'sip'] + + def configure(self): + self.match_service_name(['^asterisk', '^sip']) + + async def run(self, service): + await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,sip-enum-users,sip-methods" -oN "{scandir}/{protocol}_{port}_sip_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_sip_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-smb.py b/autorecon/default-plugins/nmap-smb.py new file mode 100644 index 0000000..5f9bb52 --- /dev/null +++ b/autorecon/default-plugins/nmap-smb.py @@ -0,0 +1,14 @@ +from autorecon.plugins import ServiceScan + +class NmapSMB(ServiceScan): + + def __init__(self): + super().__init__() + self.name = "Nmap SMB" + self.tags = ['default', 'safe', 'smb', 'active-directory'] + + def configure(self): + self.match_service_name(['^smb', '^microsoft\-ds', '^netbios']) + + async def run(self, service): + await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,(nbstat or smb* or ssl*) and not (brute or broadcast or dos or external or fuzzer)" -oN "{scandir}/{protocol}_{port}_smb_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_smb_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-smtp.py b/autorecon/default-plugins/nmap-smtp.py new file mode 100644 index 0000000..962d87c --- /dev/null +++ b/autorecon/default-plugins/nmap-smtp.py @@ -0,0 +1,14 @@ +from autorecon.plugins import ServiceScan + +class NmapSMTP(ServiceScan): + + def __init__(self): + super().__init__() + self.name = "Nmap SMTP" + self.tags = ['default', 'safe', 'smtp', 'email'] + + def configure(self): + self.match_service_name('^smtp') + + async def run(self, service): + await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,(smtp* or ssl*) and not (brute or broadcast or dos or external or fuzzer)" -oN "{scandir}/{protocol}_{port}_smtp_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_smtp_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-snmp.py b/autorecon/default-plugins/nmap-snmp.py new file mode 100644 index 0000000..29305f0 --- /dev/null +++ b/autorecon/default-plugins/nmap-snmp.py @@ -0,0 +1,14 @@ +from autorecon.plugins import ServiceScan + +class NmapSNMP(ServiceScan): + + def __init__(self): + super().__init__() + self.name = "Nmap SNMP" + self.tags = ['default', 'safe', 'snmp'] + + def configure(self): + self.match_service_name('^snmp') + + async def run(self, service): + await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,(snmp* or ssl*) and not (brute or broadcast or dos or external or fuzzer)" -oN "{scandir}/{protocol}_{port}_snmp-nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_snmp_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-ssh.py b/autorecon/default-plugins/nmap-ssh.py new file mode 100644 index 0000000..6c2acda --- /dev/null +++ b/autorecon/default-plugins/nmap-ssh.py @@ -0,0 +1,14 @@ +from autorecon.plugins import ServiceScan + +class NmapSSH(ServiceScan): + + def __init__(self): + super().__init__() + self.name = "Nmap SSH" + self.tags = ['default', 'safe', 'ssh'] + + def configure(self): + self.match_service_name('^ssh') + + async def run(self, service): + await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,ssh2-enum-algos,ssh-hostkey,ssh-auth-methods" -oN "{scandir}/{protocol}_{port}_ssh_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_ssh_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-telnet.py b/autorecon/default-plugins/nmap-telnet.py new file mode 100644 index 0000000..c989d82 --- /dev/null +++ b/autorecon/default-plugins/nmap-telnet.py @@ -0,0 +1,14 @@ +from autorecon.plugins import ServiceScan + +class NmapTelnet(ServiceScan): + + def __init__(self): + super().__init__() + self.name = 'Nmap Telnet' + self.tags = ['default', 'safe', 'telnet'] + + def configure(self): + self.match_service_name('^telnet') + + async def run(self, service): + await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,telnet-encryption,telnet-ntlm-info" -oN "{scandir}/{protocol}_{port}_telnet-nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_telnet_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-tftp.py b/autorecon/default-plugins/nmap-tftp.py new file mode 100644 index 0000000..c0c0994 --- /dev/null +++ b/autorecon/default-plugins/nmap-tftp.py @@ -0,0 +1,14 @@ +from autorecon.plugins import ServiceScan + +class NmapTFTP(ServiceScan): + + def __init__(self): + super().__init__() + self.name = 'Nmap TFTP' + self.tags = ['default', 'safe', 'tftp'] + + def configure(self): + self.match_service_name('^tftp') + + async def run(self, service): + await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,tftp-enum" -oN "{scandir}/{protocol}_{port}_tftp-nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_tftp_nmap.xml" {address}') diff --git a/autorecon/default-plugins/nmap-vnc.py b/autorecon/default-plugins/nmap-vnc.py new file mode 100644 index 0000000..806a8ff --- /dev/null +++ b/autorecon/default-plugins/nmap-vnc.py @@ -0,0 +1,14 @@ +from autorecon.plugins import ServiceScan + +class NmapVNC(ServiceScan): + + def __init__(self): + super().__init__() + self.name = 'Nmap VNC' + self.tags = ['default', 'safe', 'vnc'] + + def configure(self): + self.match_service_name('^vnc') + + async def run(self, service): + await service.execute('nmap {nmap_extra} -sV -p {port} --script="banner,(vnc* or realvnc* or ssl*) and not (brute or broadcast or dos or external or fuzzer)" --script-args="unsafe=1" -oN "{scandir}/{protocol}_{port}_vnc_nmap.txt" -oX "{scandir}/xml/{protocol}_{port}_vnc_nmap.xml" {address}') diff --git a/autorecon/default-plugins/onesixtyone.py b/autorecon/default-plugins/onesixtyone.py new file mode 100644 index 0000000..e99d621 --- /dev/null +++ b/autorecon/default-plugins/onesixtyone.py @@ -0,0 +1,18 @@ +from autorecon.plugins import ServiceScan + +class OneSixtyOne(ServiceScan): + + def __init__(self): + super().__init__() + self.name = "OneSixtyOne" + self.tags = ['default', 'safe', 'snmp'] + + def configure(self): + self.match_service_name('^snmp') + self.match_port('udp', 161) + self.run_once(True) + self.add_option('community-strings', default='/usr/share/seclists/Discovery/SNMP/common-snmp-community-strings-onesixtyone.txt', help='The file containing a list of community strings to try. Default: %(default)s') + + async def run(self, service): + if service.target.ipversion == 'IPv4': + await service.execute('onesixtyone -c ' + self.get_option('community-strings') + ' -dd {address} 2>&1', outfile='{protocol}_{port}_snmp_onesixtyone.txt') diff --git a/autorecon/default-plugins/oracle-odat.py b/autorecon/default-plugins/oracle-odat.py new file mode 100644 index 0000000..ac4613f --- /dev/null +++ b/autorecon/default-plugins/oracle-odat.py @@ -0,0 +1,21 @@ +from autorecon.plugins import ServiceScan + +class OracleODAT(ServiceScan): + + def __init__(self): + super().__init__() + self.name = "Oracle ODAT" + self.tags = ['default', 'safe', 'databases'] + + def configure(self): + self.match_service_name('^oracle') + + def manual(self, service, plugin_was_run): + service.add_manual_commands('Install ODAT (https://github.com/quentinhardy/odat) and run the following commands:', [ + 'python odat.py tnscmd -s {address} -p {port} --ping', + 'python odat.py tnscmd -s {address} -p {port} --version', + 'python odat.py tnscmd -s {address} -p {port} --status', + 'python odat.py sidguesser -s {address} -p {port}', + 'python odat.py passwordguesser -s {address} -p {port} -d --accounts-file accounts/accounts_multiple.txt', + 'python odat.py tnspoison -s {address} -p {port} -d --test-module' + ]) diff --git a/autorecon/default-plugins/oracle-patator.py b/autorecon/default-plugins/oracle-patator.py new file mode 100644 index 0000000..594b531 --- /dev/null +++ b/autorecon/default-plugins/oracle-patator.py @@ -0,0 +1,14 @@ +from autorecon.plugins import ServiceScan + +class OraclePatator(ServiceScan): + + def __init__(self): + super().__init__() + self.name = "Oracle Patator" + self.tags = ['default', 'databases'] + + def configure(self): + self.match_service_name('^oracle') + + def manual(self, service, plugin_was_run): + service.add_manual_command('Install Oracle Instant Client (https://github.com/rapid7/metasploit-framework/wiki/How-to-get-Oracle-Support-working-with-Kali-Linux) and then bruteforce with patator:', 'patator oracle_login host={address} port={port} user=COMBO00 password=COMBO01 0=/usr/share/seclists/Passwords/Default-Credentials/oracle-betterdefaultpasslist.txt -x ignore:code=ORA-01017 -x ignore:code=ORA-28000') diff --git a/autorecon/default-plugins/oracle-scanner.py b/autorecon/default-plugins/oracle-scanner.py new file mode 100644 index 0000000..16653cc --- /dev/null +++ b/autorecon/default-plugins/oracle-scanner.py @@ -0,0 +1,20 @@ +from autorecon.plugins import ServiceScan +from shutil import which + +class OracleScanner(ServiceScan): + + def __init__(self): + super().__init__() + self.name = "Oracle Scanner" + self.tags = ['default', 'safe', 'databases'] + + def configure(self): + self.match_service_name('^oracle') + + def check(self): + if which('oscanner') is None: + self.error('The oscanner program could not be found. Make sure it is installed. (On Kali, run: sudo apt install oscanner)') + return False + + async def run(self, service): + await service.execute('oscanner -v -s {address} -P {port} 2>&1', outfile='{protocol}_{port}_oracle_scanner.txt') diff --git a/autorecon/default-plugins/oracle-tnscmd.py b/autorecon/default-plugins/oracle-tnscmd.py new file mode 100644 index 0000000..7ea12c1 --- /dev/null +++ b/autorecon/default-plugins/oracle-tnscmd.py @@ -0,0 +1,22 @@ +from autorecon.plugins import ServiceScan +from shutil import which + +class OracleTNScmd(ServiceScan): + + def __init__(self): + super().__init__() + self.name = "Oracle TNScmd" + self.tags = ['default', 'safe', 'databases'] + + def configure(self): + self.match_service_name('^oracle') + + def check(self): + if which('tnscmd10g') is None: + self.error('The tnscmd10g program could not be found. Make sure it is installed. (On Kali, run: sudo apt install tnscmd10g)') + return False + + async def run(self, service): + if service.target.ipversion == 'IPv4': + await service.execute('tnscmd10g ping -h {address} -p {port} 2>&1', outfile='{protocol}_{port}_oracle_tnscmd_ping.txt') + await service.execute('tnscmd10g version -h {address} -p {port} 2>&1', outfile='{protocol}_{port}_oracle_tnscmd_version.txt') diff --git a/autorecon/default-plugins/portscan-all-tcp-ports.py b/autorecon/default-plugins/portscan-all-tcp-ports.py new file mode 100644 index 0000000..c6dc70e --- /dev/null +++ b/autorecon/default-plugins/portscan-all-tcp-ports.py @@ -0,0 +1,52 @@ +from autorecon.plugins import PortScan +from autorecon.config import config +import re, requests + +class AllTCPPortScan(PortScan): + + def __init__(self): + super().__init__() + self.name = 'All TCP Ports' + self.description = 'Performs an Nmap scan of all TCP ports.' + self.type = 'tcp' + self.specific_ports = True + self.tags = ['default', 'default-port-scan', 'long'] + + async def run(self, target): + if config['proxychains']: + traceroute_os = '' + else: + traceroute_os = ' -A --osscan-guess' + + if target.ports: + if target.ports['tcp']: + process, stdout, stderr = await target.execute('nmap {nmap_extra} -sV -sC --version-all' + traceroute_os + ' -p ' + target.ports['tcp'] + ' -oN "{scandir}/_full_tcp_nmap.txt" -oX "{scandir}/xml/_full_tcp_nmap.xml" {address}', blocking=False) + else: + return [] + else: + process, stdout, stderr = await target.execute('nmap {nmap_extra} -sV -sC --version-all' + traceroute_os + ' -p- -oN "{scandir}/_full_tcp_nmap.txt" -oX "{scandir}/xml/_full_tcp_nmap.xml" {address}', blocking=False) + services = [] + while True: + line = await stdout.readline() + if line is not None: + match = re.search('^Discovered open port ([0-9]+)/tcp', line) + if match: + target.info('Discovered open port {bmagenta}tcp/' + match.group(1) + '{rst} on {byellow}' + target.address + '{rst}', verbosity=1) + service = target.extract_service(line) + + if service: + # Check if HTTP service appears to be WinRM. If so, override service name as wsman. + if service.name == 'http' and service.port in [5985, 5986]: + wsman = requests.get(('https' if service.secure else 'http') + '://' + target.address + ':' + str(service.port) + '/wsman', verify=False) + if wsman.status_code == 405: + service.name = 'wsman' + wsman = requests.post(('https' if service.secure else 'http') + '://' + target.address + ':' + str(service.port) + '/wsman', verify=False) + else: + if wsman.status_code == 401: + service.name = 'wsman' + + services.append(service) + else: + break + await process.wait() + return services diff --git a/autorecon/default-plugins/portscan-guess-tcp-ports.py b/autorecon/default-plugins/portscan-guess-tcp-ports.py new file mode 100644 index 0000000..1919fff --- /dev/null +++ b/autorecon/default-plugins/portscan-guess-tcp-ports.py @@ -0,0 +1,48 @@ +from autorecon.plugins import PortScan +from autorecon.targets import Service +import re + +class GuessPortScan(PortScan): + + def __init__(self): + super().__init__() + self.name = 'Guess TCP Ports' + self.type = 'tcp' + self.description = 'Performs an Nmap scan of the all TCP ports but guesses services based off the port found. Can be quicker. Proper service matching is performed at the end of the scan.' + self.tags = ['guess-port-scan', 'long'] + self.priority = 0 + + async def run(self, target): + if target.ports: + if target.ports['tcp']: + process, stdout, stderr = await target.execute('nmap {nmap_extra} -A --osscan-guess --version-all -p ' + target.ports['tcp'] + ' -oN "{scandir}/_custom_ports_tcp_nmap.txt" -oX "{scandir}/xml/_custom_ports_tcp_nmap.xml" {address}', blocking=False) + else: + return [] + else: + process, stdout, stderr = await target.execute('nmap {nmap_extra} -A --osscan-guess --version-all -p- -oN "{scandir}/_quick_tcp_nmap.txt" -oX "{scandir}/xml/_quick_tcp_nmap.xml" {address}', blocking=False) + + insecure_ports = { + '20':'ftp', '21':'ftp', '22':'ssh', '23':'telnet', '25':'smtp', '53':'domain', '69':'tftp', '79':'finger', '80':'http', '88':'kerberos', '109':'pop3', '110':'pop3', '111':'rpcbind', '119':'nntp', '135':'msrpc', '139':'netbios-ssn', '143':'imap', '161':'snmp', '220':'imap', '389':'ldap', '433':'nntp', '445':'smb', '587':'smtp', '631':'ipp', '873':'rsync', '1098':'java-rmi', '1099':'java-rmi', '1433':'mssql', '1521':'oracle', '2049':'nfs', '2483':'oracle', '3020':'smb', '3306':'mysql', '3389':'rdp', '3632':'distccd', '5060':'asterisk', '5500':'vnc', '5900':'vnc', '5985':'wsman', '6379':'redis', '8080':'http-proxy', '27017':'mongod', '27018':'mongod', '27019':'mongod' + } + secure_ports = { + '443':'https', '465':'smtp', '563':'nntp', '585':'imaps', '593':'msrpc', '636':'ldap', '989':'ftp', '990':'ftp', '992':'telnet', '993':'imaps', '995':'pop3s', '2484':'oracle', '5061':'asterisk', '5986':'wsman' + } + + services = [] + while True: + line = await stdout.readline() + if line is not None: + match = re.match('^Discovered open port ([0-9]+)/tcp', line) + if match: + if match.group(1) in insecure_ports.keys(): + await target.add_service(Service('tcp', match.group(1), insecure_ports[match.group(1)])) + elif match.group(1) in secure_ports.keys(): + await target.add_service(Service('tcp', match.group(1), secure_ports[match.group(1)], True)) + service = target.extract_service(line) + if service is not None: + services.append(service) + else: + break + + await process.wait() + return services diff --git a/autorecon/default-plugins/portscan-top-100-udp-ports.py b/autorecon/default-plugins/portscan-top-100-udp-ports.py new file mode 100644 index 0000000..7f28de3 --- /dev/null +++ b/autorecon/default-plugins/portscan-top-100-udp-ports.py @@ -0,0 +1,40 @@ +from autorecon.plugins import PortScan +from autorecon.config import config +import os, re + +class Top100UDPPortScan(PortScan): + + def __init__(self): + super().__init__() + self.name = 'Top 100 UDP Ports' + self.description = 'Performs an Nmap scan of the top 100 UDP ports.' + self.type = 'udp' + self.specific_ports = True + self.tags = ['default', 'default-port-scan', 'long'] + + async def run(self, target): + # Only run UDP scan if user is root. + if os.getuid() == 0 or config['disable_sanity_checks']: + if target.ports: + if target.ports['udp']: + process, stdout, stderr = await target.execute('nmap {nmap_extra} -sU -A --osscan-guess -p ' + target.ports['udp'] + ' -oN "{scandir}/_custom_ports_udp_nmap.txt" -oX "{scandir}/xml/_custom_ports_udp_nmap.xml" {address}', blocking=False) + else: + return [] + else: + process, stdout, stderr = await target.execute('nmap {nmap_extra} -sU -A --top-ports 100 -oN "{scandir}/_top_100_udp_nmap.txt" -oX "{scandir}/xml/_top_100_udp_nmap.xml" {address}', blocking=False) + services = [] + while True: + line = await stdout.readline() + if line is not None: + match = re.search('^Discovered open port ([0-9]+)/udp', line) + if match: + target.info('Discovered open port {bmagenta}udp/' + match.group(1) + '{rst} on {byellow}' + target.address + '{rst}', verbosity=1) + service = target.extract_service(line) + if service: + services.append(service) + else: + break + await process.wait() + return services + else: + target.error('UDP scan requires AutoRecon be run with root privileges.') diff --git a/autorecon/default-plugins/redis-cli.py b/autorecon/default-plugins/redis-cli.py new file mode 100644 index 0000000..74b3803 --- /dev/null +++ b/autorecon/default-plugins/redis-cli.py @@ -0,0 +1,24 @@ +from autorecon.plugins import ServiceScan +from shutil import which + +class RedisCli(ServiceScan): + + def __init__(self): + super().__init__() + self.name = 'Redis Cli' + self.tags = ['default', 'safe', 'redis'] + + def configure(self): + self.match_service_name('^redis$') + + def check(self): + if which('redis-cli') is None: + self.error('The redis-cli program could not be found. Make sure it is installed. (On Kali, run: sudo apt install redis-tools)') + return False + + async def run(self, service): + if which('redis-cli') is not None: + _, stdout, _ = await service.execute('redis-cli -p {port} -h {address} INFO', outfile='{protocol}_{port}_redis_info.txt') + if not (await stdout.readline()).startswith('NOAUTH Authentication required'): + await service.execute('redis-cli -p {port} -h {address} CONFIG GET \'*\'', outfile='{protocol}_{port}_redis_config.txt') + await service.execute('redis-cli -p {port} -h {address} CLIENT LIST', outfile='{protocol}_{port}_redis_client-list.txt') diff --git a/autorecon/default-plugins/reporting-cherrytree.py b/autorecon/default-plugins/reporting-cherrytree.py new file mode 100644 index 0000000..bd1d4d8 --- /dev/null +++ b/autorecon/default-plugins/reporting-cherrytree.py @@ -0,0 +1,91 @@ +from autorecon.plugins import Report +from autorecon.config import config +from xml.sax.saxutils import escape +import os, glob + +class CherryTree(Report): + + def __init__(self): + super().__init__() + self.name = 'CherryTree' + self.tags = [] + + async def run(self, targets): + if len(targets) > 1: + report = os.path.join(config['output'], 'report.xml.ctd') + elif len(targets) == 1: + report = os.path.join(targets[0].reportdir, 'report.xml.ctd') + else: + return + + with open(report, 'w') as output: + output.writelines('\n\n') + for target in targets: + output.writelines('\n') + + files = [os.path.abspath(filename) for filename in glob.iglob(os.path.join(target.scandir, '**/*'), recursive=True) if os.path.isfile(filename) and filename.endswith(('.txt', '.html'))] + + if target.scans['ports']: + output.writelines('\n') + for scan in target.scans['ports'].keys(): + if len(target.scans['ports'][scan]['commands']) > 0: + output.writelines('\n') + for command in target.scans['ports'][scan]['commands']: + output.writelines('' + escape(command[0])) + for filename in files: + if filename in command[0] or (command[1] is not None and filename == command[1]) or (command[2] is not None and filename == command[2]): + output.writelines('\n\n' + escape(filename) + ':\n\n') + with open(filename, 'r') as file: + output.writelines(escape(file.read()) + '\n') + output.writelines('\n') + output.writelines('\n') + output.writelines('\n') + if target.scans['services']: + output.writelines('\n') + for service in target.scans['services'].keys(): + output.writelines('\n') + for plugin in target.scans['services'][service].keys(): + if len(target.scans['services'][service][plugin]['commands']) > 0: + output.writelines('\n') + for command in target.scans['services'][service][plugin]['commands']: + output.writelines('' + escape(command[0])) + for filename in files: + if filename in command[0] or (command[1] is not None and filename == command[1]) or (command[2] is not None and filename == command[2]): + output.writelines('\n\n' + escape(filename) + ':\n\n') + with open(filename, 'r') as file: + output.writelines(escape(file.read()) + '\n') + output.writelines('\n') + output.writelines('\n') + output.writelines('\n') + output.writelines('\n') + + manual_commands = os.path.join(target.scandir, '_manual_commands.txt') + if os.path.isfile(manual_commands): + output.writelines('\n') + with open(manual_commands, 'r') as file: + output.writelines('' + escape(file.read()) + '\n') + output.writelines('\n') + + patterns = os.path.join(target.scandir, '_patterns.log') + if os.path.isfile(patterns): + output.writelines('\n') + with open(patterns, 'r') as file: + output.writelines('' + escape(file.read()) + '\n') + output.writelines('\n') + + commands = os.path.join(target.scandir, '_commands.log') + if os.path.isfile(commands): + output.writelines('\n') + with open(commands, 'r') as file: + output.writelines('' + escape(file.read()) + '\n') + output.writelines('\n') + + errors = os.path.join(target.scandir, '_errors.log') + if os.path.isfile(errors): + output.writelines('\n') + with open(errors, 'r') as file: + output.writelines('' + escape(file.read()) + '\n') + output.writelines('\n') + output.writelines('\n') + + output.writelines('') diff --git a/autorecon/default-plugins/reporting-markdown.py b/autorecon/default-plugins/reporting-markdown.py new file mode 100644 index 0000000..bba0330 --- /dev/null +++ b/autorecon/default-plugins/reporting-markdown.py @@ -0,0 +1,75 @@ +from autorecon.plugins import Report +from autorecon.config import config +import os, glob + +class Markdown(Report): + + def __init__(self): + super().__init__() + self.name = 'Markdown' + + async def run(self, targets): + if len(targets) > 1: + report = os.path.join(config['output'], 'report.md') + elif len(targets) == 1: + report = os.path.join(targets[0].reportdir, 'report.md') + else: + return + + os.makedirs(report, exist_ok=True) + + for target in targets: + os.makedirs(os.path.join(report, target.address), exist_ok=True) + + files = [os.path.abspath(filename) for filename in glob.iglob(os.path.join(target.scandir, '**/*'), recursive=True) if os.path.isfile(filename) and filename.endswith(('.txt', '.html'))] + + if target.scans['ports']: + os.makedirs(os.path.join(report, target.address, 'Port Scans'), exist_ok=True) + for scan in target.scans['ports'].keys(): + if len(target.scans['ports'][scan]['commands']) > 0: + with open(os.path.join(report, target.address, 'Port Scans', 'PortScan - ' + target.scans['ports'][scan]['plugin'].name + '.md'), 'w') as output: + for command in target.scans['ports'][scan]['commands']: + output.writelines('```bash\n' + command[0] + '\n```') + for filename in files: + if filename in command[0] or (command[1] is not None and filename == command[1]) or (command[2] is not None and filename == command[2]): + output.writelines('\n\n[' + filename + '](file://' + filename + '):\n\n') + with open(filename, 'r') as file: + output.writelines('```\n' + file.read() + '\n```\n') + if target.scans['services']: + os.makedirs(os.path.join(report, target.address, 'Services'), exist_ok=True) + for service in target.scans['services'].keys(): + os.makedirs(os.path.join(report, target.address, 'Services', 'Service - ' + service.tag().replace('/', '-')), exist_ok=True) + for plugin in target.scans['services'][service].keys(): + if len(target.scans['services'][service][plugin]['commands']) > 0: + with open(os.path.join(report, target.address, 'Services', 'Service - ' + service.tag().replace('/', '-'), target.scans['services'][service][plugin]['plugin'].name + '.md'), 'w') as output: + for command in target.scans['services'][service][plugin]['commands']: + output.writelines('```bash\n' + command[0] + '\n```') + for filename in files: + if filename in command[0] or (command[1] is not None and filename == command[1]) or (command[2] is not None and filename == command[2]): + output.writelines('\n\n[' + filename + '](file://' + filename + '):\n\n') + with open(filename, 'r') as file: + output.writelines('```\n' + file.read() + '\n```\n') + + manual_commands = os.path.join(target.scandir, '_manual_commands.txt') + if os.path.isfile(manual_commands): + with open(os.path.join(report, target.address, 'Manual Commands' + '.md'), 'w') as output: + with open(manual_commands, 'r') as file: + output.writelines('```bash\n' + file.read() + '\n```') + + patterns = os.path.join(target.scandir, '_patterns.log') + if os.path.isfile(patterns): + with open(os.path.join(report, target.address, 'Patterns' + '.md'), 'w') as output: + with open(patterns, 'r') as file: + output.writelines(file.read()) + + commands = os.path.join(target.scandir, '_commands.log') + if os.path.isfile(commands): + with open(os.path.join(report, target.address, 'Commands' + '.md'), 'w') as output: + with open(commands, 'r') as file: + output.writelines('```bash\n' + file.read() + '\n```') + + errors = os.path.join(target.scandir, '_errors.log') + if os.path.isfile(errors): + with open(os.path.join(report, target.address, 'Errors' + '.md'), 'w') as output: + with open(errors, 'r') as file: + output.writelines('```\n' + file.read() + '\n```') diff --git a/autorecon/default-plugins/rpcclient.py b/autorecon/default-plugins/rpcclient.py new file mode 100644 index 0000000..052b20a --- /dev/null +++ b/autorecon/default-plugins/rpcclient.py @@ -0,0 +1,14 @@ +from autorecon.plugins import ServiceScan + +class RPCClient(ServiceScan): + + def __init__(self): + super().__init__() + self.name = "rpcclient" + self.tags = ['default', 'safe', 'rpc'] + + def configure(self): + self.match_service_name(['^msrpc', '^rpcbind', '^erpc']) + + def manual(self, service, plugin_was_run): + service.add_manual_command('RPC Client:', 'rpcclient -p {port} -U "" {address}') diff --git a/autorecon/default-plugins/rpcdump.py b/autorecon/default-plugins/rpcdump.py new file mode 100644 index 0000000..51aa3e7 --- /dev/null +++ b/autorecon/default-plugins/rpcdump.py @@ -0,0 +1,16 @@ +from autorecon.plugins import ServiceScan + +class RPCDump(ServiceScan): + + def __init__(self): + super().__init__() + self.name = 'rpcdump' + self.tags = ['default', 'safe', 'rpc'] + + def configure(self): + self.match_service_name(['^msrpc', '^rpcbind', '^erpc', '^ncacn_http$']) + self.match_port('tcp', [135, 139, 443, 445, 593]) + + async def run(self, service): + if service.protocol == 'tcp': + await service.execute('impacket-rpcdump -port {port} {address}', outfile='{protocol}_{port}_rpc_rpcdump.txt') diff --git a/autorecon/default-plugins/rsync-list-files.py b/autorecon/default-plugins/rsync-list-files.py new file mode 100644 index 0000000..a058336 --- /dev/null +++ b/autorecon/default-plugins/rsync-list-files.py @@ -0,0 +1,14 @@ +from autorecon.plugins import ServiceScan + +class RsyncList(ServiceScan): + + def __init__(self): + super().__init__() + self.name = 'Rsync List Files' + self.tags = ['default', 'safe', 'rsync'] + + def configure(self): + self.match_service_name('^rsync') + + async def run(self, service): + await service.execute('rsync -av --list-only rsync://{addressv6}:{port}', outfile='{protocol}_{port}_rsync_file_list.txt') diff --git a/autorecon/default-plugins/showmount.py b/autorecon/default-plugins/showmount.py new file mode 100644 index 0000000..6b14951 --- /dev/null +++ b/autorecon/default-plugins/showmount.py @@ -0,0 +1,14 @@ +from autorecon.plugins import ServiceScan + +class Showmount(ServiceScan): + + def __init__(self): + super().__init__() + self.name = "showmount" + self.tags = ['default', 'safe', 'nfs'] + + def configure(self): + self.match_service_name(['^nfs', '^rpcbind']) + + async def run(self, service): + await service.execute('showmount -e {address} 2>&1', outfile='{protocol}_{port}_showmount.txt') diff --git a/autorecon/default-plugins/sipvicious.py b/autorecon/default-plugins/sipvicious.py new file mode 100644 index 0000000..86db374 --- /dev/null +++ b/autorecon/default-plugins/sipvicious.py @@ -0,0 +1,15 @@ +from autorecon.plugins import ServiceScan + +class SIPVicious(ServiceScan): + + def __init__(self): + super().__init__() + self.name = "SIPVicious" + self.tags = ['default', 'safe', 'sip'] + + def configure(self): + self.match_service_name(['^asterisk', '^sip']) + + def manual(self, service, plugin_was_run): + if service.target.ipversion == 'IPv4': + service.add_manual_command('svwar:', 'svwar -D -m INVITE -p {port} {address}') diff --git a/autorecon/default-plugins/smb-vuln.py b/autorecon/default-plugins/smb-vuln.py new file mode 100644 index 0000000..d82ec6f --- /dev/null +++ b/autorecon/default-plugins/smb-vuln.py @@ -0,0 +1,18 @@ +from autorecon.plugins import ServiceScan + +class SMBVuln(ServiceScan): + + def __init__(self): + super().__init__() + self.name = "SMB Vulnerabilities" + self.tags = ['unsafe', 'smb', 'active-directory'] + + def configure(self): + self.match_service_name(['^smb', '^microsoft\-ds', '^netbios']) + + async def run(self, service): + await service.execute('nmap {nmap_extra} -sV -p {port} --script="smb-vuln-*" --script-args="unsafe=1" -oN "{scandir}/{protocol}_{port}_smb_vulnerabilities.txt" -oX "{scandir}/xml/{protocol}_{port}_smb_vulnerabilities.xml" {address}') + + def manual(self, service, plugin_was_run): + if not plugin_was_run: # Only suggest these if they weren't run. + service.add_manual_commands('Nmap scans for SMB vulnerabilities that could potentially cause a DoS if scanned (according to Nmap). Be careful:', 'nmap {nmap_extra} -sV -p {port} --script="smb-vuln-* and dos" --script-args="unsafe=1" -oN "{scandir}/{protocol}_{port}_smb_vulnerabilities.txt" -oX "{scandir}/xml/{protocol}_{port}_smb_vulnerabilities.xml" {address}') diff --git a/autorecon/default-plugins/smbclient.py b/autorecon/default-plugins/smbclient.py new file mode 100644 index 0000000..64ad0df --- /dev/null +++ b/autorecon/default-plugins/smbclient.py @@ -0,0 +1,16 @@ +from autorecon.plugins import ServiceScan + +class SMBClient(ServiceScan): + + def __init__(self): + super().__init__() + self.name = "SMBClient" + self.tags = ['default', 'safe', 'smb', 'active-directory'] + + def configure(self): + self.match_service_name(['^smb', '^microsoft\-ds', '^netbios']) + self.match_port('tcp', [139, 445]) + self.run_once(True) + + async def run(self, service): + await service.execute('smbclient -L //{address} -N -I {address} 2>&1', outfile='smbclient.txt') diff --git a/autorecon/default-plugins/smbmap.py b/autorecon/default-plugins/smbmap.py new file mode 100644 index 0000000..de500f7 --- /dev/null +++ b/autorecon/default-plugins/smbmap.py @@ -0,0 +1,20 @@ +from autorecon.plugins import ServiceScan + +class SMBMap(ServiceScan): + + def __init__(self): + super().__init__() + self.name = "SMBMap" + self.tags = ['default', 'safe', 'smb', 'active-directory'] + + def configure(self): + self.match_service_name(['^smb', '^microsoft\-ds', '^netbios']) + + async def run(self, service): + if service.target.ipversion == 'IPv4': + await service.execute('smbmap -H {address} -P {port} 2>&1', outfile='smbmap-share-permissions.txt') + await service.execute('smbmap -u null -p "" -H {address} -P {port} 2>&1', outfile='smbmap-share-permissions.txt') + await service.execute('smbmap -H {address} -P {port} -R 2>&1', outfile='smbmap-list-contents.txt') + await service.execute('smbmap -u null -p "" -H {address} -P {port} -R 2>&1', outfile='smbmap-list-contents.txt') + await service.execute('smbmap -H {address} -P {port} -x "ipconfig /all" 2>&1', outfile='smbmap-execute-command.txt') + await service.execute('smbmap -u null -p "" -H {address} -P {port} -x "ipconfig /all" 2>&1', outfile='smbmap-execute-command.txt') diff --git a/autorecon/default-plugins/smtp-user-enum.py b/autorecon/default-plugins/smtp-user-enum.py new file mode 100644 index 0000000..5a995b2 --- /dev/null +++ b/autorecon/default-plugins/smtp-user-enum.py @@ -0,0 +1,20 @@ +from autorecon.plugins import ServiceScan + +class SMTPUserEnum(ServiceScan): + + def __init__(self): + super().__init__() + self.name = 'SMTP-User-Enum' + self.tags = ['default', 'safe', 'smtp', 'email'] + + def configure(self): + self.match_service_name('^smtp') + + async def run(self, service): + await service.execute('hydra smtp-enum://{addressv6}:{port}/vrfy -L "' + self.get_global('username_wordlist', default='/usr/share/seclists/Usernames/top-usernames-shortlist.txt') + '" 2>&1', outfile='{protocol}_{port}_smtp_user-enum_hydra_vrfy.txt') + await service.execute('hydra smtp-enum://{addressv6}:{port}/expn -L "' + self.get_global('username_wordlist', default='/usr/share/seclists/Usernames/top-usernames-shortlist.txt') + '" 2>&1', outfile='{protocol}_{port}_smtp_user-enum_hydra_expn.txt') + + def manual(self, service, plugin_was_run): + service.add_manual_command('Try User Enumeration using "RCPT TO". Replace with the target\'s domain name:', [ + 'hydra smtp-enum://{addressv6}:{port}/rcpt -L "' + self.get_global('username_wordlist', default='/usr/share/seclists/Usernames/top-usernames-shortlist.txt') + '" -o "{scandir}/{protocol}_{port}_smtp_user-enum_hydra_rcpt.txt" -p ' + ]) diff --git a/autorecon/default-plugins/snmpwalk.py b/autorecon/default-plugins/snmpwalk.py new file mode 100644 index 0000000..5263700 --- /dev/null +++ b/autorecon/default-plugins/snmpwalk.py @@ -0,0 +1,23 @@ +from autorecon.plugins import ServiceScan + +class SNMPWalk(ServiceScan): + + def __init__(self): + super().__init__() + self.name = "SNMPWalk" + self.tags = ['default', 'safe', 'snmp'] + + def configure(self): + self.match_service_name('^snmp') + self.match_port('udp', 161) + self.run_once(True) + + async def run(self, service): + await service.execute('snmpwalk -c public -v 1 {address} 2>&1', outfile='{protocol}_{port}_snmp_snmpwalk.txt') + await service.execute('snmpwalk -c public -v 1 {address} 1.3.6.1.2.1.25.1.6.0 2>&1', outfile='{protocol}_{port}_snmp_snmpwalk_system_processes.txt') + await service.execute('snmpwalk -c public -v 1 {address} 1.3.6.1.2.1.25.4.2.1.2 2>&1', outfile='{scandir}/{protocol}_{port}_snmp_snmpwalk_running_processes.txt') + await service.execute('snmpwalk -c public -v 1 {address} 1.3.6.1.2.1.25.4.2.1.4 2>&1', outfile='{protocol}_{port}_snmp_snmpwalk_process_paths.txt') + await service.execute('snmpwalk -c public -v 1 {address} 1.3.6.1.2.1.25.2.3.1.4 2>&1', outfile='{protocol}_{port}_snmp_snmpwalk_storage_units.txt') + await service.execute('snmpwalk -c public -v 1 {address} 1.3.6.1.2.1.25.2.3.1.4 2>&1', outfile='{protocol}_{port}_snmp_snmpwalk_software_names.txt') + await service.execute('snmpwalk -c public -v 1 {address} 1.3.6.1.4.1.77.1.2.25 2>&1', outfile='{protocol}_{port}_snmp_snmpwalk_user_accounts.txt') + await service.execute('snmpwalk -c public -v 1 {address} 1.3.6.1.2.1.6.13.1.3 2>&1', outfile='{protocol}_{port}_snmp_snmpwalk_tcp_ports.txt') diff --git a/autorecon/default-plugins/sslscan.py b/autorecon/default-plugins/sslscan.py new file mode 100644 index 0000000..43071ac --- /dev/null +++ b/autorecon/default-plugins/sslscan.py @@ -0,0 +1,16 @@ +from autorecon.plugins import ServiceScan + +class SSLScan(ServiceScan): + + def __init__(self): + super().__init__() + self.name = "SSL Scan" + self.tags = ['default', 'safe', 'ssl', 'tls'] + + def configure(self): + self.match_all_service_names(True) + self.require_ssl(True) + + async def run(self, service): + if service.protocol == 'tcp' and service.secure: + await service.execute('sslscan --show-certificate --no-colour {addressv6}:{port} 2>&1', outfile='{protocol}_{port}_sslscan.html') diff --git a/autorecon/default-plugins/subdomain-enumeration.py b/autorecon/default-plugins/subdomain-enumeration.py new file mode 100644 index 0000000..185f5a3 --- /dev/null +++ b/autorecon/default-plugins/subdomain-enumeration.py @@ -0,0 +1,34 @@ +from autorecon.plugins import ServiceScan +import os + +class SubdomainEnumeration(ServiceScan): + + def __init__(self): + super().__init__() + self.name = "Subdomain Enumeration" + self.slug = "subdomain-enum" + self.tags = ['default', 'safe', 'long', 'dns'] + + def configure(self): + self.add_option('domain', help='The domain to use as the base domain (e.g. example.com) for subdomain enumeration. Default: %(default)s') + self.add_list_option('wordlist', default=['/usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt'], help='The wordlist(s) to use when enumerating subdomains. Separate multiple wordlists with spaces. Default: %(default)s') + self.add_option('threads', default=10, help='The number of threads to use when enumerating subdomains. Default: %(default)s') + self.match_service_name('^domain') + + async def run(self, service): + domains = [] + + if self.get_option('domain'): + domains.append(self.get_option('domain')) + if service.target.type == 'hostname' and service.target.address not in domains: + domains.append(service.target.address) + if self.get_global('domain') and self.get_global('domain') not in domains: + domains.append(self.get_global('domain')) + + if len(domains) > 0: + for wordlist in self.get_option('wordlist'): + name = os.path.splitext(os.path.basename(wordlist))[0] + for domain in domains: + await service.execute('gobuster dns -d ' + domain + ' -r {addressv6} -w ' + wordlist + ' -o "{scandir}/{protocol}_{port}_' + domain + '_subdomains_' + name + '.txt"') + else: + service.info('The target was not a domain, nor was a domain provided as an option. Skipping subdomain enumeration.') diff --git a/autorecon/default-plugins/virtual-host-enumeration.py b/autorecon/default-plugins/virtual-host-enumeration.py new file mode 100644 index 0000000..96e2561 --- /dev/null +++ b/autorecon/default-plugins/virtual-host-enumeration.py @@ -0,0 +1,39 @@ +from autorecon.plugins import ServiceScan +from shutil import which +import os, random, string + +class VirtualHost(ServiceScan): + + def __init__(self): + super().__init__() + self.name = 'Virtual Host Enumeration' + self.slug = 'vhost-enum' + self.tags = ['default', 'safe', 'http', 'long'] + + def configure(self): + self.add_option('hostname', help='The hostname to use as the base host (e.g. example.com) for virtual host enumeration. Default: %(default)s') + self.add_list_option('wordlist', default=['/usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt'], help='The wordlist(s) to use when enumerating virtual hosts. Separate multiple wordlists with spaces. Default: %(default)s') + self.add_option('threads', default=10, help='The number of threads to use when enumerating virtual hosts. Default: %(default)s') + self.match_service_name('^http') + self.match_service_name('^nacn_http$', negative_match=True) + + async def run(self, service): + hostnames = [] + if self.get_option('hostname'): + hostnames.append(self.get_option('hostname')) + if service.target.type == 'hostname' and service.target.address not in hostnames: + hostnames.append(service.target.address) + if self.get_global('domain') and self.get_global('domain') not in hostnames: + hostnames.append(self.get_global('domain')) + + if len(hostnames) > 0: + for wordlist in self.get_option('wordlist'): + name = os.path.splitext(os.path.basename(wordlist))[0] + for hostname in hostnames: + _, stdout, _ = await service.execute('curl -sk -o /dev/null -H "Host: ' + ''.join(random.choice(string.ascii_letters) for i in range(20)) + '.' + hostname + '" {http_scheme}://' + hostname + ':{port}/ -w "%{{size_download}}"') + + size = ''.join(await stdout.readlines()) + + await service.execute('ffuf -u {http_scheme}://' + hostname + ':{port}/ -t ' + str(self.get_option('threads')) + ' -w ' + wordlist + ' -H "Host: FUZZ.' + hostname + '" -fs ' + size + ' -noninteractive -s | tee "{scandir}/{protocol}_{port}_{http_scheme}_' + hostname + '_vhosts_' + name + '.txt"') + else: + service.info('The target was not a hostname, nor was a hostname provided as an option. Skipping virtual host enumeration.') diff --git a/autorecon/default-plugins/whatweb.py b/autorecon/default-plugins/whatweb.py new file mode 100644 index 0000000..017d80c --- /dev/null +++ b/autorecon/default-plugins/whatweb.py @@ -0,0 +1,16 @@ +from autorecon.plugins import ServiceScan + +class WhatWeb(ServiceScan): + + def __init__(self): + super().__init__() + self.name = "whatweb" + self.tags = ['default', 'safe', 'http'] + + def configure(self): + self.match_service_name('^http') + self.match_service_name('^nacn_http$', negative_match=True) + + async def run(self, service): + if service.protocol == 'tcp' and service.target.ipversion == 'IPv4': + await service.execute('whatweb --color=never --no-errors -a 3 -v {http_scheme}://{address}:{port} 2>&1', outfile='{protocol}_{port}_{http_scheme}_whatweb.txt') diff --git a/autorecon/default-plugins/winrm-detection.py b/autorecon/default-plugins/winrm-detection.py new file mode 100644 index 0000000..8742f47 --- /dev/null +++ b/autorecon/default-plugins/winrm-detection.py @@ -0,0 +1,32 @@ +from autorecon.plugins import ServiceScan +from autorecon.io import fformat + +class WinRMDetection(ServiceScan): + + def __init__(self): + super().__init__() + self.name = 'WinRM Detection' + self.tags = ['default', 'safe', 'winrm'] + + def configure(self): + self.match_service_name('^wsman') + self.match_service('tcp', [5985, 5986], '^http') + + async def run(self, service): + filename = fformat('{scandir}/{protocol}_{port}_winrm-detection.txt') + with open(filename, mode='wt', encoding='utf8') as winrm: + winrm.write('WinRM was possibly detected running on ' + service.protocol + ' port ' + str(service.port) + '.\nCheck _manual_commands.txt for manual commands you can run against this service.') + + def manual(self, service, plugin_was_run): + service.add_manual_commands('Bruteforce logins:', [ + 'crackmapexec winrm {address} -d \'' + self.get_global('domain', default='') + '\' -u \'' + self.get_global('username_wordlist', default='/usr/share/seclists/Usernames/top-usernames-shortlist.txt') + '\' -p \'' + self.get_global('password_wordlist', default='/usr/share/seclists/Passwords/darkweb2017-top100.txt') + '\'' + ]) + + service.add_manual_commands('Check login (requires credentials):', [ + 'crackmapexec winrm {address} -d \'' + self.get_global('domain', default='') + '\' -u \'\' -p \'\'' + ]) + + service.add_manual_commands('Evil WinRM (gem install evil-winrm):', [ + 'evil-winrm -u \'\' -p \'\' -i {address}', + 'evil-winrm -u \'\' -H \'\' -i {address}' + ]) diff --git a/autorecon/default-plugins/wkhtmltoimage.py b/autorecon/default-plugins/wkhtmltoimage.py new file mode 100644 index 0000000..d4d30ba --- /dev/null +++ b/autorecon/default-plugins/wkhtmltoimage.py @@ -0,0 +1,23 @@ +from autorecon.plugins import ServiceScan +from shutil import which + +class WkHTMLToImage(ServiceScan): + + def __init__(self): + super().__init__() + self.name = "wkhtmltoimage" + self.tags = ['default', 'safe', 'http'] + + def configure(self): + self.match_service_name('^http') + self.match_service_name('^nacn_http$', negative_match=True) + + def check(self): + if which('wkhtmltoimage') is None: + self.error('The wkhtmltoimage program could not be found. Make sure it is installed. (On Kali, run: sudo apt install wkhtmltopdf)') + return False + + async def run(self, service): + if which('wkhtmltoimage') is not None: + if service.protocol == 'tcp': + await service.execute('wkhtmltoimage --format png {http_scheme}://{addressv6}:{port}/ {scandir}/{protocol}_{port}_{http_scheme}_screenshot.png') diff --git a/autorecon/default-plugins/wpscan.py b/autorecon/default-plugins/wpscan.py new file mode 100644 index 0000000..a5a9249 --- /dev/null +++ b/autorecon/default-plugins/wpscan.py @@ -0,0 +1,20 @@ +from autorecon.plugins import ServiceScan + +class WPScan(ServiceScan): + + def __init__(self): + super().__init__() + self.name = 'WPScan' + self.tags = ['default', 'safe', 'http'] + + def configure(self): + self.add_option('api-token', help='An API Token from wpvulndb.com to help search for more vulnerabilities.') + self.match_service_name('^http') + self.match_service_name('^nacn_http$', negative_match=True) + + def manual(self, service, plugin_was_run): + api_token = '' + if self.get_option('api-token'): + api_token = ' --api-token ' + self.get_option('api-token') + + service.add_manual_command('(wpscan) WordPress Security Scanner (useful if WordPress is found):', 'wpscan --url {http_scheme}://{addressv6}:{port}/ --no-update -e vp,vt,tt,cb,dbe,u,m --plugins-detection aggressive --plugins-version-detection aggressive -f cli-no-color' + api_token + ' 2>&1 | tee "{scandir}/{protocol}_{port}_{http_scheme}_wpscan.txt"') From 3e39ca2aee2f1686efe24c41f511d04a57fe149f Mon Sep 17 00:00:00 2001 From: Eli McRae Date: Mon, 20 Feb 2023 09:42:27 -0600 Subject: [PATCH 5/8] option to disable dirbuster. --- autorecon/main.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/autorecon/main.py b/autorecon/main.py index bb8a66a..fbadc4a 100644 --- a/autorecon/main.py +++ b/autorecon/main.py @@ -862,7 +862,7 @@ async def run(): else: config['global_file'] = None - # Find plugins. # need to `rm -rf ~/.local/share/AutoRecon && poetry install` before testing changes to plugins... + # Find plugins. if os.path.isdir(os.path.join(config['data_dir'], 'plugins')): config['plugins_dir'] = os.path.join(config['data_dir'], 'plugins') else: @@ -908,7 +908,6 @@ async def run(): errors = False autorecon.argparse = parser - if args.version: print('AutoRecon v' + VERSION) @@ -1121,7 +1120,6 @@ def unknown_help(): error('Config option [' + slugify(key) + '] ' + slugify(pkey) + ': invalid value: \'' + pval + '\' (should be ' + str(action.const) + ')') errors = True elif action.choices and pval not in action.choices: - print('line 1130', pval, action.choices) error('Config option [' + slugify(key) + '] ' + slugify(pkey) + ': invalid choice: \'' + pval + '\' (choose from \'' + '\', \''.join(action.choices) + '\')') errors = True elif isinstance(action.default, list) and not isinstance(pval, list): @@ -1139,9 +1137,9 @@ def unknown_help(): for key, val in config.items(): if key not in other_options: autorecon.argparse.set_defaults(**{key: val}) - parser.add_argument('-h', '--help', action='help', default=argparse.SUPPRESS, help='Show this help message and exit.') # isn't this addressed around line 920? -shyft + parser.add_argument('-h', '--help', action='help', default=argparse.SUPPRESS, help='Show this help message and exit.') parser.error = lambda s: fail(s[0].upper() + s[1:]) - args = parser.parse_args() # this is where bogus /unknown args are killed -shyft + args = parser.parse_args() args_dict = vars(args) for key in args_dict: if key in configurable_keys and args_dict[key] is not None: From 7da315273534ae5d4070a18d63af3dc3ae136344 Mon Sep 17 00:00:00 2001 From: Eli McRae Date: Mon, 20 Feb 2023 09:43:10 -0600 Subject: [PATCH 6/8] option to disable dirbuster. --- .gitignore | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.gitignore b/.gitignore index 9883dd3..a89c11f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,3 @@ __pycache__ *.pyc results/ -<<<<<<< HEAD -======= -poetry.* ->>>>>>> a9608d663df07d61c5098241d97d1ed35609fc3b From d308666cc66d42d84139f4cdde51632a0508af32 Mon Sep 17 00:00:00 2001 From: Eli McRae Date: Mon, 20 Feb 2023 09:43:41 -0600 Subject: [PATCH 7/8] option to disable dirbuster. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index a89c11f..f48b3b9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ __pycache__ *.pyc results/ +poetry.* From cd878e5b983bb09a3e540a484cae3c4fc21f4dd2 Mon Sep 17 00:00:00 2001 From: Eli McRae Date: Mon, 20 Feb 2023 09:45:23 -0600 Subject: [PATCH 8/8] option to disable dirbuster. --- autorecon/default-plugins/dirbuster.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/autorecon/default-plugins/dirbuster.py b/autorecon/default-plugins/dirbuster.py index 6dcfc0e..18da3ba 100644 --- a/autorecon/default-plugins/dirbuster.py +++ b/autorecon/default-plugins/dirbuster.py @@ -13,8 +13,6 @@ def __init__(self): self.tags = ['default', 'safe', 'long', 'http'] self.tool_choices =['feroxbuster', 'gobuster', 'dirsearch', 'ffuf', 'dirb', 'none',] - # key='plugins_dir' val='/home/user/.local/share/AutoRecon/plugins' # this is where dirbuster.py is being loaded from... not the current directory... I was missing the "install" step via poetry? - def configure(self): self.add_choice_option('tool', default='feroxbuster', choices=self.tool_choices, help='The tool to use for directory busting. set to "none" to disable dirbusting. Default: %(default)s')