Plugin Updates

Separated plugins out into separate files to make them easier to understand.
This commit is contained in:
Tib3rius 2022-02-14 22:15:20 -05:00
parent 0e27e3b1c4
commit ae0eb0629a
90 changed files with 1356 additions and 1287 deletions

View File

@ -1,18 +1,5 @@
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}')
class BruteforceFTP(ServiceScan):
def __init__(self):

View File

@ -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"'
])

View File

@ -1,18 +1,5 @@
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}')
class BruteforceRDP(ServiceScan):
def __init__(self):

View File

@ -1,18 +1,5 @@
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}')
class BruteforceSSH(ServiceScan):
def __init__(self):

View File

@ -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 (/).')

View File

@ -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 (/).')

View File

@ -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')

View File

@ -1,134 +0,0 @@
from autorecon.plugins import ServiceScan
from shutil import which
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}')
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 <username> -P <password> -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}')
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 <username> -P <password> -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}')
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}')
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)')
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')
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)')
async def run(self, service):
await service.execute('oscanner -v -s {address} -P {port} 2>&1', outfile='{protocol}_{port}_oracle_scanner.txt')
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 <sid> --accounts-file accounts/accounts_multiple.txt',
'python odat.py tnspoison -s {address} -p {port} -d <sid> --test-module'
])
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')

View File

@ -1,102 +0,0 @@
from autorecon.plugins import PortScan
from autorecon.config import config
import os, re
class QuickTCPPortScan(PortScan):
def __init__(self):
super().__init__()
self.name = 'Top TCP Ports'
self.description = 'Performs an Nmap scan of the top 1000 TCP ports.'
self.type = 'tcp'
self.tags = ['default', 'default-port-scan']
self.priority = 0
async def run(self, target):
if target.ports: # Don't run this plugin if there are custom ports.
return []
if config['proxychains']:
traceroute_os = ''
else:
traceroute_os = ' -A --osscan-guess'
process, stdout, stderr = await target.execute('nmap {nmap_extra} -sV -sC --version-all' + traceroute_os + ' -oN "{scandir}/_quick_tcp_nmap.txt" -oX "{scandir}/xml/_quick_tcp_nmap.xml" {address}', blocking=False)
services = await target.extract_services(stdout)
await process.wait()
return services
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:
services.append(service)
else:
break
await process.wait()
return services
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:
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.')

View File

@ -0,0 +1,75 @@
from autorecon.plugins import ServiceScan
from autorecon.config import config
from shutil import which
import os
class DirBuster(ServiceScan):
def __init__(self):
super().__init__()
self.name = "Directory Buster"
self.slug = 'dirbuster'
self.priority = 0
self.tags = ['default', 'safe', 'long', 'http']
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_list_option('wordlist', default=[os.path.join(config['config_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')
self.match_service_name('^http')
self.match_service_name('^nacn_http$', negative_match=True)
def check(self):
tool = self.get_option('tool')
if tool == 'feroxbuster':
if 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)')
elif tool == 'gobuster':
if 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)')
elif tool == 'dirsearch':
if which('dirsearch') is None:
self.error('The dirsearch program could not be found. Make sure it is installed. (On Kali, run: sudo apt install dirsearch)')
async def run(self, service):
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]
if self.get_option('tool') == 'feroxbuster':
await service.execute('feroxbuster -u {http_scheme}://{addressv6}:{port}/ -t ' + str(self.get_option('threads')) + ' -w ' + wordlist + ' -x "' + self.get_option('ext') + '" -v -k -n -q -e -o "{scandir}/{protocol}_{port}_{http_scheme}_feroxbuster_' + name + '.txt"')
elif self.get_option('tool') == 'gobuster':
await service.execute('gobuster dir -u {http_scheme}://{addressv6}:{port}/ -t ' + str(self.get_option('threads')) + ' -w ' + wordlist + ' -e -k -x "' + self.get_option('ext') + '" -z -d -o "{scandir}/{protocol}_{port}_{http_scheme}_gobuster_' + name + '.txt"')
elif self.get_option('tool') == 'dirsearch':
if service.target.ipversion == 'IPv6':
service.error('dirsearch does not support IPv6.')
else:
await service.execute('dirsearch -u {http_scheme}://{address}:{port}/ -t ' + str(self.get_option('threads')) + ' -e "' + self.get_option('ext') + '" -f -q -w ' + wordlist + ' --format=plain -o "{scandir}/{protocol}_{port}_{http_scheme}_dirsearch_' + name + '.txt"')
elif self.get_option('tool') == 'ffuf':
await service.execute('ffuf -u {http_scheme}://{addressv6}:{port}/FUZZ -t ' + str(self.get_option('threads')) + ' -w ' + wordlist + ' -e "' + dot_extensions + '" -v -noninteractive | tee {scandir}/{protocol}_{port}_{http_scheme}_ffuf_' + name + '.txt')
elif self.get_option('tool') == 'dirb':
await service.execute('dirb {http_scheme}://{addressv6}:{port}/ ' + wordlist + ' -l -r -S -X ",' + dot_extensions + '" -o "{scandir}/{protocol}_{port}_{http_scheme}_dirb_' + name + '.txt"')
def manual(self, service, plugin_was_run):
dot_extensions = ','.join(['.' + x for x in self.get_option('ext').split(',')])
if self.get_option('tool') == 'feroxbuster':
service.add_manual_command('(feroxbuster) Multi-threaded recursive directory/file enumeration for web servers using various wordlists:', [
'feroxbuster -u {http_scheme}://{addressv6}:{port} -t ' + str(self.get_option('threads')) + ' -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x "' + self.get_option('ext') + '" -v -k -n -o {scandir}/{protocol}_{port}_{http_scheme}_feroxbuster_dirbuster.txt'
])
elif self.get_option('tool') == 'gobuster':
service.add_manual_command('(gobuster v3) Multi-threaded directory/file enumeration for web servers using various wordlists:', [
'gobuster dir -u {http_scheme}://{addressv6}:{port}/ -t ' + str(self.get_option('threads')) + ' -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -e -k -x "' + self.get_option('ext') + '" -z -o "{scandir}/{protocol}_{port}_{http_scheme}_gobuster_dirbuster.txt"'
])
elif self.get_option('tool') == 'dirsearch':
if service.target.ipversion == 'IPv4':
service.add_manual_command('(dirsearch) Multi-threaded recursive directory/file enumeration for web servers using various wordlists:', [
'dirsearch -u {http_scheme}://{address}:{port}/ -t ' + str(self.get_option('threads')) + ' -r -e "' + self.get_option('ext') + '" -f -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt --format=plain --output="{scandir}/{protocol}_{port}_{http_scheme}_dirsearch_dirbuster.txt"'
])
elif self.get_option('tool') == 'ffuf':
service.add_manual_command('(ffuf) Multi-threaded recursive directory/file enumeration for web servers using various wordlists:', [
'ffuf -u {http_scheme}://{addressv6}:{port}/FUZZ -t ' + str(self.get_option('threads')) + ' -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -e "' + dot_extensions + '" -v -noninteractive | tee {scandir}/{protocol}_{port}_{http_scheme}_ffuf_dirbuster.txt'
])
elif self.get_option('tool') == 'dirb':
service.add_manual_command('(dirb) Recursive directory/file enumeration for web servers using various wordlists:', [
'dirb {http_scheme}://{addressv6}:{port}/ /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -l -r -S -X ",' + dot_extensions + '" -o "{scandir}/{protocol}_{port}_{http_scheme}_dirb_dirbuster.txt"'
])

View File

@ -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')

View File

@ -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')

View File

@ -1,143 +0,0 @@
from autorecon.plugins import ServiceScan
from shutil import which
import os
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}')
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')
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')
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}')
class DnsReconDefault(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)')
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 <DOMAIN-NAME> 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.')
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)')
def manual(self, service, plugin_was_run):
domain_name = '<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',
])
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.')

View File

@ -0,0 +1,26 @@
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)')
def manual(self, service, plugin_was_run):
domain_name = '<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',
])

View File

@ -0,0 +1,29 @@
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)')
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 <DOMAIN-NAME> 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.')

View File

@ -0,0 +1,18 @@
from autorecon.plugins import ServiceScan
class Enum4Linux(ServiceScan):
def __init__(self):
super().__init__()
self.name = "Enum4Linux"
self.tags = ['default', 'safe', 'active-directory']
def configure(self):
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)
async def run(self, service):
if service.target.ipversion == 'IPv4':
await service.execute('enum4linux -a -M -l -d {address} 2>&1', outfile='enum4linux.txt')

View File

@ -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('getArch.py -target {address}', outfile='{protocol}_{port}_rpc_architecture.txt')

View File

@ -1,282 +0,0 @@
from autorecon.plugins import ServiceScan
from autorecon.io import fformat
from autorecon.config import config
from shutil import which
import os
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}')
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"'
])
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')
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 (/).')
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 (/).')
class DirBuster(ServiceScan):
def __init__(self):
super().__init__()
self.name = "Directory Buster"
self.slug = 'dirbuster'
self.priority = 0
self.tags = ['default', 'safe', 'long', 'http']
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_list_option('wordlist', default=[os.path.join(config['config_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')
self.match_service_name('^http')
self.match_service_name('^nacn_http$', negative_match=True)
def check(self):
tool = self.get_option('tool')
if tool == 'feroxbuster':
if 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)')
elif tool == 'gobuster':
if 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)')
elif tool == 'dirsearch':
if which('dirsearch') is None:
self.error('The dirsearch program could not be found. Make sure it is installed. (On Kali, run: sudo apt install dirsearch)')
async def run(self, service):
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]
if self.get_option('tool') == 'feroxbuster':
await service.execute('feroxbuster -u {http_scheme}://{addressv6}:{port}/ -t ' + str(self.get_option('threads')) + ' -w ' + wordlist + ' -x "' + self.get_option('ext') + '" -v -k -n -q -e -o "{scandir}/{protocol}_{port}_{http_scheme}_feroxbuster_' + name + '.txt"')
elif self.get_option('tool') == 'gobuster':
await service.execute('gobuster dir -u {http_scheme}://{addressv6}:{port}/ -t ' + str(self.get_option('threads')) + ' -w ' + wordlist + ' -e -k -x "' + self.get_option('ext') + '" -z -d -o "{scandir}/{protocol}_{port}_{http_scheme}_gobuster_' + name + '.txt"')
elif self.get_option('tool') == 'dirsearch':
if service.target.ipversion == 'IPv6':
service.error('dirsearch does not support IPv6.')
else:
await service.execute('dirsearch -u {http_scheme}://{address}:{port}/ -t ' + str(self.get_option('threads')) + ' -e "' + self.get_option('ext') + '" -f -q -w ' + wordlist + ' --format=plain -o "{scandir}/{protocol}_{port}_{http_scheme}_dirsearch_' + name + '.txt"')
elif self.get_option('tool') == 'ffuf':
await service.execute('ffuf -u {http_scheme}://{addressv6}:{port}/FUZZ -t ' + str(self.get_option('threads')) + ' -w ' + wordlist + ' -e "' + dot_extensions + '" -v -noninteractive | tee {scandir}/{protocol}_{port}_{http_scheme}_ffuf_' + name + '.txt')
elif self.get_option('tool') == 'dirb':
await service.execute('dirb {http_scheme}://{addressv6}:{port}/ ' + wordlist + ' -l -r -S -X ",' + dot_extensions + '" -o "{scandir}/{protocol}_{port}_{http_scheme}_dirb_' + name + '.txt"')
def manual(self, service, plugin_was_run):
dot_extensions = ','.join(['.' + x for x in self.get_option('ext').split(',')])
if self.get_option('tool') == 'feroxbuster':
service.add_manual_command('(feroxbuster) Multi-threaded recursive directory/file enumeration for web servers using various wordlists:', [
'feroxbuster -u {http_scheme}://{addressv6}:{port} -t ' + str(self.get_option('threads')) + ' -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x "' + self.get_option('ext') + '" -v -k -n -o {scandir}/{protocol}_{port}_{http_scheme}_feroxbuster_dirbuster.txt'
])
elif self.get_option('tool') == 'gobuster':
service.add_manual_command('(gobuster v3) Multi-threaded directory/file enumeration for web servers using various wordlists:', [
'gobuster dir -u {http_scheme}://{addressv6}:{port}/ -t ' + str(self.get_option('threads')) + ' -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -e -k -x "' + self.get_option('ext') + '" -z -o "{scandir}/{protocol}_{port}_{http_scheme}_gobuster_dirbuster.txt"'
])
elif self.get_option('tool') == 'dirsearch':
if service.target.ipversion == 'IPv4':
service.add_manual_command('(dirsearch) Multi-threaded recursive directory/file enumeration for web servers using various wordlists:', [
'dirsearch -u {http_scheme}://{address}:{port}/ -t ' + str(self.get_option('threads')) + ' -r -e "' + self.get_option('ext') + '" -f -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt --format=plain --output="{scandir}/{protocol}_{port}_{http_scheme}_dirsearch_dirbuster.txt"'
])
elif self.get_option('tool') == 'ffuf':
service.add_manual_command('(ffuf) Multi-threaded recursive directory/file enumeration for web servers using various wordlists:', [
'ffuf -u {http_scheme}://{addressv6}:{port}/FUZZ -t ' + str(self.get_option('threads')) + ' -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -e "' + dot_extensions + '" -v -noninteractive | tee {scandir}/{protocol}_{port}_{http_scheme}_ffuf_dirbuster.txt'
])
elif self.get_option('tool') == 'dirb':
service.add_manual_command('(dirb) Recursive directory/file enumeration for web servers using various wordlists:', [
'dirb {http_scheme}://{addressv6}:{port}/ /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -l -r -S -X ",' + dot_extensions + '" -o "{scandir}/{protocol}_{port}_{http_scheme}_dirb_dirbuster.txt"'
])
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"')
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)
def check(self):
if 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)')
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:
await service.execute('gobuster vhost -k -u {http_scheme}://' + hostname + ':{port}/ -t ' + str(self.get_option('threads')) + ' -w ' + wordlist + ' -r -o "{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.')
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')
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)')
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')
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"')

View File

@ -1,18 +1,5 @@
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}')
class LDAPSearch(ServiceScan):
def __init__(self):

View File

@ -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', [
'lookupsid.py [username]:[password]@{address}'
])

View File

@ -1,201 +0,0 @@
from autorecon.plugins import ServiceScan
from autorecon.io import fformat
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}')
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}')
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}')
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}')
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}')
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}')
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}')
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}')
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}')
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}')
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}')
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}')
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}')
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='<domain>') + ' -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='<domain>') + ' -u <username> -p <password> -x "whoami"'
])
service.add_manual_commands('Evil WinRM (gem install evil-winrm):', [
'evil-winrm -u <user> -p <password> -i {address}',
'evil-winrm -u <user> -H <hash> -i {address}'
])

View File

@ -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 {address} 2>&1', outfile='nbtscan.txt')

View File

@ -1,40 +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}')
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')
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}')

View File

@ -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"')

View File

@ -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}')

View File

@ -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}')

View File

@ -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}')

View File

@ -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}')

View File

@ -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}')

View File

@ -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}')

View File

@ -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}')

View File

@ -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}')

View File

@ -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}')

View File

@ -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}')

View File

@ -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}')

View File

@ -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}')

View File

@ -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}')

View File

@ -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 <username> -P <password> -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}')

View File

@ -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}')

View File

@ -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 <username> -P <password> -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}')

View File

@ -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}')

View File

@ -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}')

View File

@ -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}')

View File

@ -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}')

View File

@ -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}')

View File

@ -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}')

View File

@ -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}')

View File

@ -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}')

View File

@ -12,16 +12,3 @@ class NmapRsync(ServiceScan):
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}')
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')

View File

@ -12,17 +12,3 @@ class NmapSIP(ServiceScan):
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}')
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}')

View File

@ -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}')

View File

@ -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}')

View File

@ -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}')

View File

@ -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}')

View File

@ -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}')

View File

@ -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}')

View File

@ -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}')

View File

@ -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 ' + service.get_option('community-strings') + ' -dd {address} 2>&1', outfile='{protocol}_{port}_snmp_onesixtyone.txt')

View File

@ -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 <sid> --accounts-file accounts/accounts_multiple.txt',
'python odat.py tnspoison -s {address} -p {port} -d <sid> --test-module'
])

View File

@ -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')

View File

@ -0,0 +1,19 @@
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)')
async def run(self, service):
await service.execute('oscanner -v -s {address} -P {port} 2>&1', outfile='{protocol}_{port}_oracle_scanner.txt')

View File

@ -0,0 +1,21 @@
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)')
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')

View File

@ -0,0 +1,41 @@
from autorecon.plugins import PortScan
from autorecon.config import config
import re
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:
services.append(service)
else:
break
await process.wait()
return services

View File

@ -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:
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.')

View File

@ -0,0 +1,26 @@
from autorecon.plugins import PortScan
from autorecon.config import config
class QuickTCPPortScan(PortScan):
def __init__(self):
super().__init__()
self.name = 'Top TCP Ports'
self.description = 'Performs an Nmap scan of the top 1000 TCP ports.'
self.type = 'tcp'
self.tags = ['default', 'default-port-scan']
self.priority = 0
async def run(self, target):
if target.ports: # Don't run this plugin if there are custom ports.
return []
if config['proxychains']:
traceroute_os = ''
else:
traceroute_os = ' -A --osscan-guess'
process, stdout, stderr = await target.execute('nmap {nmap_extra} -sV -sC --version-all' + traceroute_os + ' -oN "{scandir}/_quick_tcp_nmap.txt" -oX "{scandir}/xml/_quick_tcp_nmap.xml" {address}', blocking=False)
services = await target.extract_services(stdout)
await process.wait()
return services

View File

@ -1,19 +1,6 @@
from autorecon.plugins import ServiceScan
from shutil import which
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}')
class RedisCli(ServiceScan):
def __init__(self):

View File

@ -89,75 +89,3 @@ class CherryTree(Report):
output.writelines('</node>\n')
output.writelines('</cherrytree>')
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```')

View File

@ -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```')

View File

@ -1,57 +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}')
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}')
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')
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('getArch.py -target {address}', outfile='{protocol}_{port}_rpc_architecture.txt')

View File

@ -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}')

View File

@ -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')

View File

@ -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')

View File

@ -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')

View File

@ -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}')

View File

@ -0,0 +1,24 @@
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-ms06-025" --script-args="unsafe=1" -oN "{scandir}/{protocol}_{port}_smb_ms06-025.txt" -oX "{scandir}/xml/{protocol}_{port}_smb_ms06-025.xml" {address}')
await service.execute('nmap {nmap_extra} -sV -p {port} --script="smb-vuln-ms07-029" --script-args="unsafe=1" -oN "{scandir}/{protocol}_{port}_smb_ms07-029.txt" -oX "{scandir}/xml/{protocol}_{port}_smb_ms07-029.xml" {address}')
await service.execute('nmap {nmap_extra} -sV -p {port} --script="smb-vuln-ms08-067" --script-args="unsafe=1" -oN "{scandir}/{protocol}_{port}_smb_ms08-067.txt" -oX "{scandir}/xml/{protocol}_{port}_smb_ms08-067.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-ms06-025" --script-args="unsafe=1" -oN "{scandir}/{protocol}_{port}_smb_ms06-025.txt" -oX "{scandir}/xml/{protocol}_{port}_smb_ms06-025.xml" {address}',
'nmap {nmap_extra} -sV -p {port} --script="smb-vuln-ms07-029" --script-args="unsafe=1" -oN "{scandir}/{protocol}_{port}_smb_ms07-029.txt" -oX "{scandir}/xml/{protocol}_{port}_smb_ms07-029.xml" {address}',
'nmap {nmap_extra} -sV -p {port} --script="smb-vuln-ms08-067" --script-args="unsafe=1" -oN "{scandir}/{protocol}_{port}_smb_ms08-067.txt" -oX "{scandir}/xml/{protocol}_{port}_smb_ms08-067.xml" {address}'
])

View File

@ -1,119 +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}')
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-ms06-025" --script-args="unsafe=1" -oN "{scandir}/{protocol}_{port}_smb_ms06-025.txt" -oX "{scandir}/xml/{protocol}_{port}_smb_ms06-025.xml" {address}')
await service.execute('nmap {nmap_extra} -sV -p {port} --script="smb-vuln-ms07-029" --script-args="unsafe=1" -oN "{scandir}/{protocol}_{port}_smb_ms07-029.txt" -oX "{scandir}/xml/{protocol}_{port}_smb_ms07-029.xml" {address}')
await service.execute('nmap {nmap_extra} -sV -p {port} --script="smb-vuln-ms08-067" --script-args="unsafe=1" -oN "{scandir}/{protocol}_{port}_smb_ms08-067.txt" -oX "{scandir}/xml/{protocol}_{port}_smb_ms08-067.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-ms06-025" --script-args="unsafe=1" -oN "{scandir}/{protocol}_{port}_smb_ms06-025.txt" -oX "{scandir}/xml/{protocol}_{port}_smb_ms06-025.xml" {address}',
'nmap {nmap_extra} -sV -p {port} --script="smb-vuln-ms07-029" --script-args="unsafe=1" -oN "{scandir}/{protocol}_{port}_smb_ms07-029.txt" -oX "{scandir}/xml/{protocol}_{port}_smb_ms07-029.xml" {address}',
'nmap {nmap_extra} -sV -p {port} --script="smb-vuln-ms08-067" --script-args="unsafe=1" -oN "{scandir}/{protocol}_{port}_smb_ms08-067.txt" -oX "{scandir}/xml/{protocol}_{port}_smb_ms08-067.xml" {address}'
])
class Enum4Linux(ServiceScan):
def __init__(self):
super().__init__()
self.name = "Enum4Linux"
self.tags = ['default', 'safe', 'active-directory']
def configure(self):
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)
async def run(self, service):
if service.target.ipversion == 'IPv4':
await service.execute('enum4linux -a -M -l -d {address} 2>&1', outfile='enum4linux.txt')
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', [
'lookupsid.py [username]:[password]@{address}'
])
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 {address} 2>&1', outfile='nbtscan.txt')
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')
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')

View File

@ -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')

View File

@ -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')

View File

@ -1,18 +1,5 @@
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}')
class SMTPUserEnum(ServiceScan):
def __init__(self):

View File

@ -1,35 +1,5 @@
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}')
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 ' + service.get_option('community-strings') + ' -dd {address} 2>&1', outfile='{protocol}_{port}_snmp_onesixtyone.txt')
class SNMPWalk(ServiceScan):
def __init__(self):

View File

@ -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.')

View File

@ -0,0 +1,39 @@
from autorecon.plugins import ServiceScan
from shutil import which
import os
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)
def check(self):
if 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)')
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:
await service.execute('gobuster vhost -k -u {http_scheme}://' + hostname + ':{port}/ -t ' + str(self.get_option('threads')) + ' -w ' + wordlist + ' -r -o "{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.')

View File

@ -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')

View File

@ -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='<domain>') + ' -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='<domain>') + ' -u <username> -p <password> -x "whoami"'
])
service.add_manual_commands('Evil WinRM (gem install evil-winrm):', [
'evil-winrm -u <user> -p <password> -i {address}',
'evil-winrm -u <user> -H <hash> -i {address}'
])

View File

@ -0,0 +1,22 @@
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)')
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')

View File

@ -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"')

View File

@ -17,7 +17,7 @@ from autorecon.io import slugify, e, fformat, cprint, debug, info, warn, error,
from autorecon.plugins import Pattern, PortScan, ServiceScan, Report, AutoRecon
from autorecon.targets import Target, Service
VERSION = "2.0.15"
VERSION = "2.0.16"
if not os.path.exists(config['config_dir']):
shutil.rmtree(config['config_dir'], ignore_errors=True, onerror=None)

View File

@ -1,6 +1,6 @@
[tool.poetry]
name = "autorecon"
version = "2.0.15"
version = "2.0.16"
description = "A multi-threaded network reconnaissance tool which performs automated enumeration of services."
authors = ["Tib3rius"]
license = "GNU GPL v3"