New Features
Added ability to add an additional plugins directory instead of overriding the original. Useful for plugin dev. Also added a new non-default port scan which guesses services based on open ports.
This commit is contained in:
parent
f5415f9f03
commit
0b37730304
25
autorecon.py
25
autorecon.py
|
@ -466,6 +466,7 @@ class AutoRecon(object):
|
|||
'tags',
|
||||
'exclude_tags',
|
||||
'plugins_dir',
|
||||
'add_plugins-dir',
|
||||
'outdir',
|
||||
'single_target',
|
||||
'only_scans_dir',
|
||||
|
@ -491,6 +492,7 @@ class AutoRecon(object):
|
|||
'tags': 'default',
|
||||
'exclude_tags': None,
|
||||
'plugins_dir': os.path.dirname(os.path.abspath(__file__)) + '/plugins',
|
||||
'add_plugins_dir': None,
|
||||
'outdir': 'results',
|
||||
'single_target': False,
|
||||
'only_scans_dir': False,
|
||||
|
@ -1334,6 +1336,7 @@ async def main():
|
|||
parser.add_argument('--tags', action='store', type=str, default='default', help='Tags to determine which plugins should be included. Separate tags by a plus symbol (+) to group tags together. Separate groups with a comma (,) to create multiple groups. For a plugin to be included, it must have all the tags specified in at least one group. Default: %(default)s')
|
||||
parser.add_argument('--exclude-tags', action='store', type=str, default='', help='Tags to determine which plugins should be excluded. Separate tags by a plus symbol (+) to group tags together. Separate groups with a comma (,) to create multiple groups. For a plugin to be excluded, it must have all the tags specified in at least one group. Default: %(default)s')
|
||||
parser.add_argument('--plugins-dir', action='store', type=str, help='The location of the plugins directory. Default: %(default)s')
|
||||
parser.add_argument('--add-plugins-dir', action='store', type=str, help='The location of an additional plugins directory to add to the main one. Default: %(default)s')
|
||||
parser.add_argument('-l', '--list', action='store', nargs='?', const='plugins', help='List all plugins or plugins of a specific type. e.g. --list, --list port, --list service')
|
||||
parser.add_argument('-o', '--output', action='store', dest='outdir', help='The output directory for results. Default: %(default)s')
|
||||
parser.add_argument('--single-target', action='store_true', help='Only scan a single target. A directory named after the target will not be created. Instead, the directory structure will be created within the output directory. Default: %(default)s')
|
||||
|
@ -1370,27 +1373,41 @@ async def main():
|
|||
try:
|
||||
config_toml = toml.load(c)
|
||||
for key, val in config_toml.items():
|
||||
key = slugify(key)
|
||||
if key == 'global-file':
|
||||
autorecon.config['global_file'] = val
|
||||
elif key == 'plugins-dir':
|
||||
autorecon.config['plugins_dir'] = val
|
||||
elif key == 'add-plugins-dir':
|
||||
autorecon.config['add_plugins_dir'] = val
|
||||
except toml.decoder.TomlDecodeError:
|
||||
fail('Error: Couldn\'t parse ' + args.config_file + ' config file. Check syntax.')
|
||||
|
||||
args_dict = vars(args)
|
||||
for key in args_dict:
|
||||
if key == 'global_file' and args_dict['global_file'] is not None:
|
||||
key = slugify(key)
|
||||
if key == 'global-file' and args_dict['global_file'] is not None:
|
||||
autorecon.config['global_file'] = args_dict['global_file']
|
||||
elif key == 'plugins_dir' and args_dict['plugins_dir'] is not None:
|
||||
elif key == 'plugins-dir' and args_dict['plugins_dir'] is not None:
|
||||
autorecon.config['plugins_dir'] = args_dict['plugins_dir']
|
||||
elif key == 'add-plugins-dir' and args_dict['add_plugins_dir'] is not None:
|
||||
autorecon.config['add_plugins_dir'] = args_dict['add_plugins_dir']
|
||||
|
||||
if not os.path.isdir(autorecon.config['plugins_dir']):
|
||||
fail('Error: Specified plugins directory "' + autorecon.config['plugins_dir'] + '" does not exist.')
|
||||
|
||||
for plugin_file in os.listdir(autorecon.config['plugins_dir']):
|
||||
if autorecon.config['add_plugins_dir'] and not os.path.isdir(autorecon.config['add_plugins_dir']):
|
||||
fail('Error: Specified additional plugins directory "' + autorecon.config['add_plugins_dir'] + '" does not exist.')
|
||||
|
||||
plugins_dirs = [autorecon.config['plugins_dir']]
|
||||
if autorecon.config['add_plugins_dir']:
|
||||
plugins_dirs.append(autorecon.config['add_plugins_dir'])
|
||||
|
||||
for plugins_dir in plugins_dirs:
|
||||
for plugin_file in os.listdir(plugins_dir):
|
||||
if not plugin_file.startswith('_') and plugin_file.endswith('.py'):
|
||||
|
||||
dirname, filename = os.path.split(os.path.join(autorecon.config['plugins_dir'], plugin_file))
|
||||
dirname, filename = os.path.split(os.path.join(plugins_dir, plugin_file))
|
||||
dirname = os.path.abspath(dirname)
|
||||
|
||||
# Temporarily insert the plugin directory into the sys.path so importing plugins works.
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
from autorecon import PortScan, Service
|
||||
import re
|
||||
|
||||
class GuesPortScan(PortScan):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.name = 'Guess TCP Ports'
|
||||
self.type = 'tcp'
|
||||
self.description = 'Performs an Nmap scan of the all TCP ports but guesses services based off the port found. Can be quicker. Proper service matching is performed at the end of the scan.'
|
||||
self.tags = ['guess-port-scan', 'long']
|
||||
self.priority = 0
|
||||
|
||||
async def run(self, target):
|
||||
if target.ports:
|
||||
if target.ports['tcp']:
|
||||
process, stdout, stderr = await target.execute('nmap {nmap_extra} -A --osscan-guess --version-all -p ' + target.ports['tcp'] + ' -oN "{scandir}/_custom_ports_tcp_nmap.txt" -oX "{scandir}/xml/_custom_ports_tcp_nmap.xml" {address}', blocking=False)
|
||||
else:
|
||||
return []
|
||||
else:
|
||||
process, stdout, stderr = await target.execute('nmap {nmap_extra} -A --osscan-guess --version-all -p- -oN "{scandir}/_quick_tcp_nmap.txt" -oX "{scandir}/xml/_quick_tcp_nmap.xml" {address}', blocking=False)
|
||||
|
||||
insecure_ports = {
|
||||
'20':'ftp', '21':'ftp', '22':'ssh', '23':'telnet', '25':'smtp', '53':'domain', '69':'tftp', '79':'finger', '80':'http', '88':'kerberos', '109':'pop3', '110':'pop3', '111':'rpcbind', '119':'nntp', '135':'msrpc', '139':'netbios-ssn', '143':'imap', '161':'snmp', '220':'imap', '389':'ldap', '433':'nntp', '445':'smb', '587':'smtp', '631':'ipp', '873':'rsync', '1098':'java-rmi', '1099':'java-rmi', '1433':'mssql', '1521':'oracle', '2049':'nfs', '2483':'oracle', '3020':'smb', '3306':'mysql', '3389':'rdp', '3632':'distccd', '5060':'asterisk', '5500':'vnc', '5900':'vnc', '5985':'wsman', '6379':'redis', '8080':'http-proxy', '27017':'mongod', '27018':'mongod', '27019':'mongod'
|
||||
}
|
||||
secure_ports = {
|
||||
'443':'https', '465':'smtp', '563':'nntp', '585':'imaps', '593':'msrpc', '636':'ldap', '989':'ftp', '990':'ftp', '992':'telnet', '993':'imaps', '995':'pop3s', '2484':'oracle', '5061':'asterisk', '5986':'wsman'
|
||||
}
|
||||
|
||||
services = []
|
||||
while True:
|
||||
line = await stdout.readline()
|
||||
if line is not None:
|
||||
match = re.match('^Discovered open port ([0-9]+)/tcp', line)
|
||||
if match:
|
||||
if match.group(1) in insecure_ports.keys():
|
||||
await target.add_service(Service('tcp', match.group(1), insecure_ports[match.group(1)]))
|
||||
elif match.group(1) in secure_ports.keys():
|
||||
await target.add_service(Service('tcp', match.group(1), secure_ports[match.group(1)], True))
|
||||
service = target.extract_service(line)
|
||||
if service is not None:
|
||||
services.append(service)
|
||||
else:
|
||||
break
|
||||
|
||||
await process.wait()
|
||||
return services
|
Loading…
Reference in New Issue