From 7db7f136226dee71cab5508ae4164523f4043b7f Mon Sep 17 00:00:00 2001 From: Tib3rius <48113936+Tib3rius@users.noreply.github.com> Date: Tue, 26 Mar 2019 15:14:03 -0400 Subject: [PATCH] Added service-specific pattern matching. Updated pattern matching output. --- autorecon.py | 53 ++++++++++++++++++++++++++++++++++------------ patterns.toml | 6 +++--- service-scans.toml | 4 ++++ 3 files changed, 47 insertions(+), 16 deletions(-) diff --git a/autorecon.py b/autorecon.py index fc09a72..bef3a04 100644 --- a/autorecon.py +++ b/autorecon.py @@ -52,11 +52,13 @@ def cprint(*args, color=Fore.RESET, char='*', sep=' ', end='\n', frame_index=1, 'bred': Fore.RED + Style.BRIGHT, 'bblue': Fore.BLUE + Style.BRIGHT, 'byellow': Fore.YELLOW + Style.BRIGHT, + 'bmagenta': Fore.MAGENTA + Style.BRIGHT, 'green': Fore.GREEN, 'red': Fore.RED, 'blue': Fore.BLUE, 'yellow': Fore.YELLOW, + 'magenta': Fore.MAGENTA, 'bright': Style.BRIGHT, 'srst': Style.NORMAL, @@ -137,7 +139,7 @@ if 'password_wordlist' in service_scans_config: if isinstance(service_scans_config['password_wordlist'], str): password_wordlist = service_scans_config['password_wordlist'] -async def read_stream(stream, address, tag='?', color=Fore.BLUE): +async def read_stream(stream, address, tag='?', patterns=None, color=Fore.BLUE): while True: line = await stream.readline() if line: @@ -146,12 +148,25 @@ async def read_stream(stream, address, tag='?', color=Fore.BLUE): if verbose >= 1: for p in global_patterns: matches = re.findall(p['pattern'], line) - for match in matches: - info('{bgreen}{tag}{rst} on {byellow}{address}{rst} - ' + p['description']) + if 'description' in p: + for match in matches: + info('Task {bgreen}{tag}{rst} on {byellow}{address}{rst} - {bmagenta}' + p['description'].replace('{match}', '{bblue}{match}{crst}{bmagenta}') + '{rst}') + else: + for match in matches: + info('Task {bgreen}{tag}{rst} on {byellow}{address}{rst} - {bmagenta}Matched Pattern: {bblue}{match}{rst}') + + for p in patterns: + matches = re.findall(p['pattern'], line) + if 'description' in p: + for match in matches: + info('Task {bgreen}{tag}{rst} on {byellow}{address}{rst} - {bmagenta}' + p['description'].replace('{match}', '{bblue}{match}{crst}{bmagenta}') + '{rst}') + else: + for match in matches: + info('Task {bgreen}{tag}{rst} on {byellow}{address}{rst} - {bmagenta}Matched Pattern: {bblue}{match}{rst}') else: break -async def run_cmd(semaphore, cmd, target, tag='?'): +async def run_cmd(semaphore, cmd, target, tag='?', patterns=None): async with semaphore: address = target.address scandir = target.scandir @@ -164,8 +179,8 @@ async def run_cmd(semaphore, cmd, target, tag='?'): process = await asyncio.create_subprocess_shell(cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE) await asyncio.wait([ - read_stream(process.stdout, address, tag), - read_stream(process.stderr, address, tag, Fore.RED) + read_stream(process.stdout, address, tag=tag, patterns=patterns), + read_stream(process.stderr, address, tag=tag, patterns=patterns, color=Fore.RED) ]) await process.wait() @@ -195,8 +210,12 @@ async def parse_port_scan(stream, tag, address, pattern): if verbose >= 1: for p in global_patterns: matches = re.findall(p['pattern'], line) - for match in matches: - info('{bgreen}{tag}{rst} on {byellow}{address}{rst} - ' + p['description']) + if 'description' in p: + for match in matches: + info('Task {bgreen}{tag}{rst} on {byellow}{address}{rst} - {bmagenta}' + p['description'].replace('{match}', '{bblue}{match}{crst}{bmagenta}') + '{rst}') + else: + for match in matches: + info('Task {bgreen}{tag}{rst} on {byellow}{address}{rst} - {bmagenta}Matched Pattern: {bblue}{match}{rst}') else: break @@ -218,8 +237,12 @@ async def parse_service_detection(stream, tag, address, pattern): if verbose >= 1: for p in global_patterns: matches = re.findall(p['pattern'], line) - for match in matches: - info('{bgreen}{tag}{rst} on {byellow}{address}{rst} - ' + p['description']) + if 'description' in p: + for match in matches: + info('Task {bgreen}{tag}{rst} on {byellow}{address}{rst} - {bmagenta}' + p['description'].replace('{match}', '{bblue}{match}{crst}{bmagenta}') + '{rst}') + else: + for match in matches: + info('Task {bgreen}{tag}{rst} on {byellow}{address}{rst} - {bmagenta}Matched Pattern: {bblue}{match}{rst}') else: break @@ -246,7 +269,7 @@ async def run_portscan(semaphore, tag, target, service_detection, port_scan=None output = [ parse_port_scan(process.stdout, tag, address, pattern), - read_stream(process.stderr, address, tag, Fore.RED) + read_stream(process.stderr, address, tag=tag, color=Fore.RED) ] results = await asyncio.gather(*output) @@ -279,7 +302,7 @@ async def run_portscan(semaphore, tag, target, service_detection, port_scan=None output = [ parse_service_detection(process.stdout, tag, address, pattern), - read_stream(process.stderr, address, tag, Fore.RED) + read_stream(process.stderr, address, tag=tag, color=Fore.RED) ] results = await asyncio.gather(*output) @@ -444,7 +467,11 @@ async def scan_services(loop, semaphore, target): else: target.scans.append(scan_tuple) - pending.add(asyncio.ensure_future(run_cmd(semaphore, e(command), target, tag))) + patterns = [] + if 'pattern' in scan: + patterns = scan['pattern'] + + pending.add(asyncio.ensure_future(run_cmd(semaphore, e(command), target, tag=tag, patterns=patterns))) def scan_host(target, concurrent_scans): info('Scanning target {byellow}{target.address}{rst}') diff --git a/patterns.toml b/patterns.toml index 7ceaff8..d6bd0ac 100644 --- a/patterns.toml +++ b/patterns.toml @@ -1,7 +1,7 @@ [[pattern]] -description = 'Nmap script found a potential vulnerability. ({bblue}{match}{rst})' -pattern = 'State: (?:LIKELY|VULNERABLE)' +description = 'Nmap script found a potential vulnerability. ({match})' +pattern = 'State: (?:(?:LIKELY\_?)?VULNERABLE)' [[pattern]] -description = 'HTTP Server: {bblue}{match}{rst}' +description = 'Identified HTTP Server: {match}' pattern = 'Server: ([^\n]+)' diff --git a/service-scans.toml b/service-scans.toml index f87f733..269a9e1 100644 --- a/service-scans.toml +++ b/service-scans.toml @@ -43,6 +43,10 @@ service-names = [ name = 'nmap-ftp' command = 'nmap {nmap_extra} -sV -p {port} --script="(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}' + [[ftp.scan.pattern]] + description = 'Anonymous FTP Enabled!' + pattern = 'Anonymous FTP login allowed' + [[ftp.manual]] description = 'Bruteforce logins:' commands = [