Update autorecon.py
Added feature to collect services which AutoRecon "missed" (i.e. doesn't have plugins for) and report them at the end.
This commit is contained in:
parent
ffa811ddee
commit
0fcadbe1d8
31
autorecon.py
31
autorecon.py
|
@ -164,12 +164,12 @@ class CommandStreamReader(object):
|
||||||
try:
|
try:
|
||||||
line = (await self.stream.readline()).decode('utf8').rstrip()
|
line = (await self.stream.readline()).decode('utf8').rstrip()
|
||||||
except ValueError:
|
except ValueError:
|
||||||
error('{blue}[{bright}' + self.target.address + '/' + self.tag + '{srst}]{crst} A line was longer than 64 KiB and cannot be processed. Ignoring.')
|
error('{bblue}[' + self.target.address + '/' + self.tag + ']{crst} A line was longer than 64 KiB and cannot be processed. Ignoring.')
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if self.target.autorecon.config['verbose'] >= 2:
|
if self.target.autorecon.config['verbose'] >= 2:
|
||||||
if line != '':
|
if line != '':
|
||||||
info('{blue}[{bright}' + self.target.address + '/' + self.tag + '{srst}]{crst} ' + line.replace('{', '{{').replace('}', '}}'))
|
info('{bblue}[' + self.target.address + '/' + self.tag + ']{crst} ' + line.replace('{', '{{').replace('}', '}}'))
|
||||||
for p in self.patterns:
|
for p in self.patterns:
|
||||||
matches = p.pattern.findall(line)
|
matches = p.pattern.findall(line)
|
||||||
for match in matches:
|
for match in matches:
|
||||||
|
@ -177,11 +177,11 @@ class CommandStreamReader(object):
|
||||||
with open(os.path.join(self.target.scandir, '_patterns.log'), 'a') as file:
|
with open(os.path.join(self.target.scandir, '_patterns.log'), 'a') as file:
|
||||||
if p.description:
|
if p.description:
|
||||||
if self.target.autorecon.config['verbose'] >= 1:
|
if self.target.autorecon.config['verbose'] >= 1:
|
||||||
info('{blue}[{bright}' + self.target.address + '/' + self.tag + '{srst}] {crst}{bmagenta}' + p.description.replace('{match}', '{bblue}' + match + '{crst}{bmagenta}') + '{rst}')
|
info('{bblue}[' + self.target.address + '/' + self.tag + ']{crst} {bmagenta}' + p.description.replace('{match}', '{bblue}' + match + '{crst}{bmagenta}') + '{rst}')
|
||||||
file.writelines(p.description.replace('{match}', match) + '\n\n')
|
file.writelines(p.description.replace('{match}', match) + '\n\n')
|
||||||
else:
|
else:
|
||||||
if self.target.autorecon.config['verbose'] >= 1:
|
if self.target.autorecon.config['verbose'] >= 1:
|
||||||
info('{blue}[{bright}' + self.target.address + '/' + self.tag + '{srst}] {crst}{bmagenta}Matched Pattern: {bblue}' + match + '{rst}')
|
info('{bblue}[' + self.target.address + '/' + self.tag + ']{crst} {bmagenta}Matched Pattern: {bblue}' + match + '{rst}')
|
||||||
file.writelines('Matched Pattern: ' + match + '\n\n')
|
file.writelines('Matched Pattern: ' + match + '\n\n')
|
||||||
|
|
||||||
if self.outfile is not None:
|
if self.outfile is not None:
|
||||||
|
@ -367,6 +367,7 @@ class AutoRecon(object):
|
||||||
self.argparse = None
|
self.argparse = None
|
||||||
self.argparse_group = None
|
self.argparse_group = None
|
||||||
self.args = None
|
self.args = None
|
||||||
|
self.missing_services = []
|
||||||
self.tags = []
|
self.tags = []
|
||||||
self.excluded_tags = []
|
self.excluded_tags = []
|
||||||
self.patterns = []
|
self.patterns = []
|
||||||
|
@ -902,6 +903,7 @@ async def scan_target(target):
|
||||||
if protocol == 'udp':
|
if protocol == 'udp':
|
||||||
nmap_extra += ' -sU'
|
nmap_extra += ' -sU'
|
||||||
|
|
||||||
|
service_match = False
|
||||||
matching_plugins = []
|
matching_plugins = []
|
||||||
heading = False
|
heading = False
|
||||||
|
|
||||||
|
@ -910,6 +912,7 @@ async def scan_target(target):
|
||||||
|
|
||||||
for s in plugin.service_names:
|
for s in plugin.service_names:
|
||||||
if re.search(s, service.name):
|
if re.search(s, service.name):
|
||||||
|
service_match = True
|
||||||
plugin_tag_set = set(plugin.tags)
|
plugin_tag_set = set(plugin.tags)
|
||||||
|
|
||||||
matching_tags = False
|
matching_tags = False
|
||||||
|
@ -934,7 +937,7 @@ async def scan_target(target):
|
||||||
if plugin_is_runnable and matching_tags and not excluded_tags:
|
if plugin_is_runnable and matching_tags and not excluded_tags:
|
||||||
# Skip plugin if run_once_boolean and plugin already in target scans
|
# Skip plugin if run_once_boolean and plugin already in target scans
|
||||||
if plugin.run_once_boolean and (plugin.slug,) in target.scans:
|
if plugin.run_once_boolean and (plugin.slug,) in target.scans:
|
||||||
warn('{byellow}[' + plugin_tag + ' against ' + target.address + '{srst}] Plugin should only be run once and it appears to have already been queued. Skipping.{rst}')
|
warn('{byellow}[' + plugin_tag + ' against ' + target.address + ']{srst} Plugin should only be run once and it appears to have already been queued. Skipping.{rst}')
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Skip plugin if require_ssl_boolean and port is not secure
|
# Skip plugin if require_ssl_boolean and port is not secure
|
||||||
|
@ -943,17 +946,17 @@ async def scan_target(target):
|
||||||
|
|
||||||
# Skip plugin if service port is in ignore_ports:
|
# Skip plugin if service port is in ignore_ports:
|
||||||
if port in plugin.ignore_ports[protocol]:
|
if port in plugin.ignore_ports[protocol]:
|
||||||
warn('{byellow}[' + plugin_tag + ' against ' + target.address + '{srst}] Plugin cannot be run against ' + protocol + ' port ' + str(port) + '. Skipping.{rst}')
|
warn('{byellow}[' + plugin_tag + ' against ' + target.address + ']{srst} Plugin cannot be run against ' + protocol + ' port ' + str(port) + '. Skipping.{rst}')
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Skip plugin if plugin has required ports and service port is not in them:
|
# Skip plugin if plugin has required ports and service port is not in them:
|
||||||
if plugin.ports[protocol] and port not in plugin.ports[protocol]:
|
if plugin.ports[protocol] and port not in plugin.ports[protocol]:
|
||||||
warn('{byellow}[' + plugin_tag + ' against ' + target.address + '{srst}] Plugin can only run on specific ports. Skipping.{rst}')
|
warn('{byellow}[' + plugin_tag + ' against ' + target.address + ']{srst} Plugin can only run on specific ports. Skipping.{rst}')
|
||||||
continue
|
continue
|
||||||
|
|
||||||
for i in plugin.ignore_service_names:
|
for i in plugin.ignore_service_names:
|
||||||
if re.search(i, service.name):
|
if re.search(i, service.name):
|
||||||
warn('{byellow}[' + plugin_tag + ' against ' + target.address + '{srst}] Plugin cannot be run against this service. Skipping.{rst}')
|
warn('{byellow}[' + plugin_tag + ' against ' + target.address + ']{srst} Plugin cannot be run against this service. Skipping.{rst}')
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# TODO: check if plugin matches tags, BUT run manual commands anyway!
|
# TODO: check if plugin matches tags, BUT run manual commands anyway!
|
||||||
|
@ -980,12 +983,18 @@ async def scan_target(target):
|
||||||
scan_tuple = (plugin.slug,)
|
scan_tuple = (plugin.slug,)
|
||||||
|
|
||||||
if scan_tuple in target.scans:
|
if scan_tuple in target.scans:
|
||||||
warn('{byellow}[' + plugin_tag + ' against ' + target.address + '{srst}] Plugin appears to have already been queued, but it is not marked as run_once. Possible duplicate service tag? Skipping.{rst}')
|
warn('{byellow}[' + plugin_tag + ' against ' + target.address + ']{srst} Plugin appears to have already been queued, but it is not marked as run_once. Possible duplicate service tag? Skipping.{rst}')
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
target.scans.append(scan_tuple)
|
target.scans.append(scan_tuple)
|
||||||
|
|
||||||
pending.add(asyncio.create_task(service_scan(plugin, service)))
|
pending.add(asyncio.create_task(service_scan(plugin, service)))
|
||||||
|
|
||||||
|
if not service_match:
|
||||||
|
warn('{byellow}[' + target.address + ']{srst} Service ' + service.full_tag() + ' did not match any plugins.{rst}')
|
||||||
|
if service.full_tag() not in target.autorecon.missing_services:
|
||||||
|
target.autorecon.missing_services.append(service.full_tag())
|
||||||
|
|
||||||
heartbeat.cancel()
|
heartbeat.cancel()
|
||||||
elapsed_time = calculate_elapsed_time(start_time)
|
elapsed_time = calculate_elapsed_time(start_time)
|
||||||
|
|
||||||
|
@ -1396,7 +1405,6 @@ async def main():
|
||||||
|
|
||||||
elapsed_time = calculate_elapsed_time(start_time)
|
elapsed_time = calculate_elapsed_time(start_time)
|
||||||
warn('{byellow}AutoRecon took longer than the specified timeout period (' + str(autorecon.config['timeout']) + ' min). Cancelling all scans and exiting.{rst}')
|
warn('{byellow}AutoRecon took longer than the specified timeout period (' + str(autorecon.config['timeout']) + ' min). Cancelling all scans and exiting.{rst}')
|
||||||
sys.exit(0)
|
|
||||||
else:
|
else:
|
||||||
while len(asyncio.all_tasks()) > 1: # this code runs in the main() task so it will be the only task left running
|
while len(asyncio.all_tasks()) > 1: # this code runs in the main() task so it will be the only task left running
|
||||||
await asyncio.sleep(1)
|
await asyncio.sleep(1)
|
||||||
|
@ -1404,6 +1412,9 @@ async def main():
|
||||||
elapsed_time = calculate_elapsed_time(start_time)
|
elapsed_time = calculate_elapsed_time(start_time)
|
||||||
info('{bright}Finished scanning all targets in ' + elapsed_time + '!{rst}')
|
info('{bright}Finished scanning all targets in ' + elapsed_time + '!{rst}')
|
||||||
|
|
||||||
|
if autorecon.missing_services:
|
||||||
|
warn('{byellow}AutoRecon identified the following services, but could not match them to any plugins. Please report these to Tib3rius: ' + ', '.join(autorecon.missing_services) + '{rst}')
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
signal.signal(signal.SIGINT, cancel_all_tasks)
|
signal.signal(signal.SIGINT, cancel_all_tasks)
|
||||||
try:
|
try:
|
||||||
|
|
Loading…
Reference in New Issue