def main(): parser = argparse.ArgumentParser( description= 'Verify SSL certificate validation for one or more tested application') parser.add_argument('app_or_capture', metavar='appname', nargs='?', help='Application name or network capture file') args = parser.parse_args() app = args.app_or_capture if args.app_or_capture: check_app(app) else: for entry in os.listdir('results'): if os.path.isdir(os.path.join('results', entry)): app = entry check_app(app) eprint('') eprint(color.bright('SSL test summary:')) eprint(color.bright(color.red(('Failed:')))) for app in ssl_failed: eprint(app) if ssl_notest: eprint(color.bright('Not tested:')) for app in ssl_notest: eprint(app) eprint(color.bright(color.green(('Passed:')))) for app in ssl_passed: eprint(app)
def get_search_results(pkt): ''' Parse through packets that match tshark filter for search ''' global found, foundunenc, searchterm # Searches are case insensitive pcre = re.compile('(?i)' + searchterm) print( color.green( color.bright('Found match in %s packet [%d] (%s):' % (pcapfile, int(pkt.number), pkt.highest_layer)))) found = True foundunenc = True for layer in pkt.layers: for field_line in layer._get_all_field_lines(): if pcre.search(field_line): print('%s: %s' % (layer.layer_name, field_line.rstrip())) print( color.bright( color.red('%s found in unencrypted %s traffic!' % (searchterm, pkt.highest_layer)))) if args.verbose: print('----- Full packet dump begin -----') print(pkt) print('----- Full packet dump end -------')
def check_app(app): failedssltest = False badrequests = [] # Get mitmproxy log file location if app.endswith('.log'): flowfile = app jsonfile = '%s.%s' % (flowfile, json_output) if os.path.exists(flowfile): sys.stdout = Logger('%s.%s' % (flowfile, report_output)) else: flowfile = os.path.join('results', app, 'ssltest.log') jsonfile = os.path.join(os.path.dirname(flowfile), json_output) if os.path.exists(flowfile): sys.stdout = Logger(os.path.join('results', app, report_output)) if os.path.exists(flowfile): badsslmsgs = [] with open(flowfile, "rb") as logfile: freader = io.FlowReader(logfile) pp = pprint.PrettyPrinter(indent=4) try: for msg in freader.stream(): scheme = msg.request.scheme if scheme == 'https': failedssltest = True badsslmsgs.append(msg) if failedssltest: ssl_failed.append(app) print( color.bright( '%s fails to validate SSL certificates properly' % app)) print('Offending URIs accessed:') for msg in badsslmsgs: method = msg.request.method uri = msg.request.pretty_url request = '%s %s' % (method, uri) badrequests.append(request) request = color.bright(color.red((request))) print(request) else: print('No HTTPS traffic detected for app %s' % app) ssl_passed.append(app) except FlowReadException as e: print("Flow file corrupted: {}".format(e)) report = {} report['app'] = app report['testtime'] = os.path.getmtime(flowfile) report['failedtest'] = failedssltest report['ssl_failed'] = badrequests with open(jsonfile, 'w') as fp: json.dump(report, fp) else: ssl_notest.append(app)
def run_all(app, analyzers): for analyzer in analyzers: print( color.bright('----- Begin %s report for %s -----' % (analyzer, color.cyan(app)))) subprocess.call(['./%s' % analyzer, app]) print( color.bright('----- End %s report for %s -------' % (analyzer, color.cyan(app)))) print('')
def main(): global args, searchterm parser = argparse.ArgumentParser( description='Search captured traffic for a pattern') parser.add_argument('app_or_capture', metavar='appname', help='Application name or network capture file') parser.add_argument('searchterm', type=str, help='String to search for') parser.add_argument('-v', '--verbose', dest='verbose', action='store_true', help='display packet contents') parser.add_argument('-m', '--multi', dest='multi', action='store_true', help='search multiple encodings') args = parser.parse_args() app = args.app_or_capture searchterm = args.searchterm appdir = os.path.join('results', app) search_output = get_search_outname(searchterm) if os.path.isdir(appdir): sys.stdout = Logger(os.path.join(appdir, search_output)) if args.app_or_capture: # Check only one app # Option to use full packets perhaps specified if args.multi: check_multi(app, searchterm) else: check_app(app, searchterm) else: # Check all apps tested for entry in os.listdir('results'): if os.path.isdir(os.path.join('results', entry)): app = entry if args.multi: check_multi(app, searchterm) else: check_app(app, searchterm) elif os.path.isdir(os.path.join('results', entry.lower())): app = entry if args.multi: check_multi(app, searchterm) else: check_app(app, searchterm) print('') # Flush stdout log file sys.stdout = sys.__stdout__ # Copy log file to universally-named one copy2(os.path.join(appdir, search_output), os.path.join(appdir, report_output)) eprint(color.bright('Done!'))
def generate_report(app, fullpacket=False, pcapfile=''): ''' Print report based on collected data ''' report = {} report['app'] = app report['testtime'] = os.path.getmtime(pcapfile) # This is an un-failable test report['failedtest'] = False report['targets'] = net.targets report['dnsreqs'] = net.dnsreqs if app.endswith('.pcap'): app_or_pcap = 'pcap' jsonfile = '%s.%s' % (app, json_output) else: app_or_pcap = 'application' jsonfile = os.path.join(os.path.dirname(pcapfile), 'net.json') print('') print('Summary for %s: %s' % (app_or_pcap, color.bright(color.cyan(app)))) print('') print(color.bright('Hosts contacted:')) # For each target (unsorted) for target in net.targets: # Get protocols used if fullpacket: protos = get_protos_full(net.targets[target]) else: protos = get_protos(net.targets[target]) # Get host name host = net.get_hostname(target) protolist = ', '.join(protos) print('%s : %s : %s' % (color.bright('CONNECT'), host, protolist)) print('') print(color.bright('DNS queries made:')) for dnsreq in net.dnsreqs: print('%s : %s' % (color.bright('LOOKUP'), dnsreq)) with open(jsonfile, 'w') as fp: json.dump(report, fp)
def print_header(logfile): global pcapfile, fullmitmfile, ssltestfile traffictype = '' logfile = os.path.basename(logfile) if logfile == pcapfile: traffictype = 'unencrypted' elif logfile == fullmitmfile: traffictype = 'protected HTTPS' elif logfile == ssltestfile: traffictype = 'UNPROTECTED HTTPS' print( color.bright('===== Search hits in %s traffic below =====' % traffictype))
def main(): parser = argparse.ArgumentParser( description='Run all reports for one or more tested application') parser.add_argument('app_or_capture', metavar='appname', nargs='?', help='Application name or network capture file') args = parser.parse_args() app = args.app_or_capture if args.app_or_capture: # Check only one app runreports(app) else: # Check all apps tested for app in getapps(): runreports(app) eprint(color.bright('Done!'))
def generate_report(app, pcapfile=''): ''' Print report based on collected data ''' global sslpacketcount if app.endswith('.pcap'): app_or_pcap = 'pcap' jsonfile = '%s.%s' % (pcapfile, json_output) else: app_or_pcap = 'application' jsonfile = os.path.join(os.path.dirname(pcapfile), json_output) report = {} report['app'] = app report['testtime'] = os.path.getmtime(pcapfile) report['sslversions'] = net.sslversions report['requestedciphers'] = net.requestedciphers report['negotiatedciphers'] = net.negotiatedciphers report['dtlsversions'] = net.dtlsversions report['negotiateddtlsciphers'] = net.negotiateddtlsciphers seen_mandatory_ciphers = [] seen_optional_ciphers = [] seen_other_ciphers = [] failedtest = False failedreasons = [] print('') print('Summary for application: %s' % color.bright(color.cyan(app))) print('') if net.sslpacketcount > 0: print(color.bright('TLS/SSL protocols used:')) # For each target (unsorted) for sslversion in net.sslversions: if sslversion == 'TLS 1.2': sslversion = color.bright(color.green(sslversion)) else: failedtest = True failedreasons.append('%s is used, rather than TLS 1.2' % sslversion) sslversion = color.bright(color.red(sslversion)) print(sslversion) print( color.bright('Hosts using %s:' % color.decolorize(sslversion))) for host in net.sslversions[color.decolorize(sslversion)]: print(host) print('') for ciphersuite in net.requestedciphers: if ciphersuite in net.mandatory_ciphers: #ciphersuite = color.bright(color.green(ciphersuite)) seen_mandatory_ciphers.append(ciphersuite) elif ciphersuite in net.optional_ciphers: #ciphersuite = color.bright(ciphersuite) seen_optional_ciphers.append(ciphersuite) else: #ciphersuite = color.dim(ciphersuite) seen_other_ciphers.append(ciphersuite) if len(seen_mandatory_ciphers) == 0: failedtest = True failedreasons.append('%s is not supported by client' % net.mandatory_ciphers[0]) print( color.bright( 'Observed mandatory ciphers in TLS/SSL client requests:')) for cipher in seen_mandatory_ciphers: print(color.bright(color.green(cipher))) report['seen_mandatory_ciphers'] = seen_mandatory_ciphers print('') print( color.bright( 'Observed optional ciphers in TLS/SSL client requests:')) for cipher in seen_optional_ciphers: print(cipher) report['seen_optional_ciphers'] = seen_optional_ciphers print('') print( color.bright('Observed other ciphers in TLS/SSL client requests:')) for cipher in seen_other_ciphers: print(color.dim(cipher)) report['seen_other_ciphers'] = seen_other_ciphers print('') print(color.bright('Negotiated TLS/SSL ciphers:')) for ciphersuite in net.negotiatedciphers: if ciphersuite in net.mandatory_ciphers: ciphersuite = color.bright(color.green(ciphersuite)) elif ciphersuite in net.optional_ciphers: pass #ciphersuite = color.bright(ciphersuite) else: ciphersuite = color.dim(ciphersuite) print(ciphersuite) print( color.bright('Hosts using %s:' % color.decolorize(ciphersuite))) for host in net.negotiatedciphers[color.decolorize(ciphersuite)]: print(host) print('') print('') else: print(color.bright(color.green('No TLS/SSL traffic seen'))) print('') if net.dtlspacketcount > 0: print(color.bright('DTLS protocols used:')) # For each target (unsorted) for dtlsversion in net.dtlsversions: if dtlsversion == 'DTLS 1.2': dtlsversion = color.bright(color.green(dtlsversion)) else: failedtest = True failedreasons.append('%s is used, rather than DTLS 1.2' % dtlsversion) dtlsversion = color.bright(color.red(dtlsversion)) print(dtlsversion) print( color.bright('Hosts using %s:' % color.decolorize(dtlsversion))) for host in net.dtlsversions[color.decolorize(dtlsversion)]: print(host) print('') report['dtlsciphers'] = net.requesteddtlsciphers for ciphersuite in net.requesteddtlsciphers: if ciphersuite in net.mandatory_ciphers: #ciphersuite = color.bright(color.green(ciphersuite)) seen_mandatory_ciphers.append(ciphersuite) elif ciphersuite in net.optional_ciphers: #ciphersuite = color.bright(ciphersuite) seen_optional_ciphers.append(ciphersuite) else: #ciphersuite = color.dim(ciphersuite) seen_other_ciphers.append(ciphersuite) if len(seen_mandatory_ciphers) == 0: failedtest = True failedreasons.append('%s is not supported by client' % net.mandatory_ciphers[0]) print( color.bright( 'Observed mandatory ciphers in DTLS client requests:')) for cipher in seen_mandatory_ciphers: print(color.bright(color.green(cipher))) print('') report['seen_mandatory_dtls_ciphers'] = seen_mandatory_ciphers print( color.bright('Observed optional ciphers in DTLS client requests:')) for cipher in seen_optional_ciphers: print(cipher) print('') report['seen_optional_dtls_ciphers'] = seen_optional_ciphers print(color.bright('Observed other ciphers in DTLS client requests:')) for cipher in seen_other_ciphers: print(color.dim(cipher)) print('') report['seen_other_dtls_ciphers'] = seen_other_ciphers print(color.bright('Negotiated DTLS ciphers:')) for ciphersuite in net.negotiateddtlsciphers: if ciphersuite in net.mandatory_ciphers: ciphersuite = color.bright(color.green(ciphersuite)) elif ciphersuite in net.optional_ciphers: pass #ciphersuite = color.bright(ciphersuite) else: ciphersuite = color.dim(ciphersuite) print(ciphersuite) print( color.bright('Hosts using %s:' % color.decolorize(ciphersuite))) for host in net.negotiateddtlsciphers[color.decolorize( ciphersuite)]: print(host) print('') print('') else: print(color.bright(color.green('No DTLS traffic seen'))) report['failedtest'] = failedtest report['failedreasons'] = failedreasons if failedtest: print( color.bright( color.red('App %s failed crypto checking because:' % app))) for reason in failedreasons: print(color.bright(color.red(reason))) else: print(color.bright(color.green('App %s passed crypto checking' % app))) # print(report) with open(jsonfile, 'w') as fp: json.dump(report, fp)
def check_app(app, force=False): ''' Check application based on app name in Tapioca results ''' dnscacheloaded = False largewarned = False # Get pcap file location if app.endswith('.pcap'): pcapfile = app if os.path.exists(pcapfile): sys.stdout = Logger('%s.%s' % (pcapfile, report_output)) else: pcapfile = os.path.join('results', app, 'tcpdump.pcap') if os.path.exists(pcapfile): sys.stdout = Logger(os.path.join('results', app, report_output)) if os.path.exists(pcapfile): pcapdir = os.path.dirname(pcapfile) dnspkl = os.path.join(pcapdir, '.dnsmap.pkl') eprint(color.bright('Checking app %s...' % color.cyan(app))) if os.path.exists(dnspkl) and not force: eprint('Loading cached DNS info...') with open(dnspkl, 'rb') as pklhandle: try: net.dnsmap = pickle.load(pklhandle) dnscacheloaded = True except: pass if not dnscacheloaded: if os.path.getsize(pcapfile) > 100000000: # Over 100MB eprint( color.bright( color.yellow( 'Warning: capture size is large. Please be patient.' ))) largewarned = True # Get captured DNS info for IP addresses eprint('Getting DNS info...') dnspackets = pyshark.FileCapture(pcapfile, keep_packets=False, display_filter='dns') dnspackets.apply_on_packets(net.get_dns_info, timeout=1000) with open(dnspkl, 'wb') as pklhandle: pickle.dump(net.dnsmap, pklhandle, protocol=pickle.HIGHEST_PROTOCOL) if os.path.getsize(pcapfile) > 100000000 and not largewarned: # Over 100MB eprint( color.bright( color.yellow( 'Warning: capture size is large. Please be patient.'))) largewarned = True sslpackets = pyshark.FileCapture(pcapfile, keep_packets=False, display_filter='ssl') eprint('Getting SSL info from capture...') # get_indexed_ssl_info(cap) sslpackets.apply_on_packets(net.get_ssl_info, timeout=1000) dtlspackets = pyshark.FileCapture(pcapfile, keep_packets=False, display_filter='dtls') eprint('Getting DTLS info from capture...') dtlspackets.apply_on_packets(net.get_dtls_info, timeout=1000) # Print report generate_report(app, pcapfile=pcapfile) # Reset globals net.clear()
def check_app(app, fullpacket=False, force=False): ''' Check application based on app name in Tapioca results ''' dnscacheloaded = False targetscacheloaded = False largewarned = False # load local network from config net.set_local() # Get pcap file location if app.endswith('.pcap'): pcapfile = app if os.path.exists(pcapfile): sys.stdout = Logger('%s.%s' % (pcapfile, report_output)) else: pcapfile = os.path.join('results', app, 'tcpdump.pcap') if os.path.exists(pcapfile): sys.stdout = Logger(os.path.join('results', app, report_output)) if os.path.exists(pcapfile): pcapdir = os.path.dirname(pcapfile) dnspkl = os.path.join(pcapdir, '.dnsmap.pkl') targetspkl = os.path.join(pcapdir, '.targets.pkl') eprint(color.bright('Checking app %s...' % color.cyan(app))) if os.path.exists(dnspkl) and not force: eprint('Loading cached DNS info...') with open(dnspkl, 'rb') as pklhandle: try: net.dnsmap = pickle.load(pklhandle) net.dnsreqs = pickle.load(pklhandle) dnscacheloaded = True except: pass if not dnscacheloaded: if os.path.getsize(pcapfile) > 100000000: # Over 100MB eprint( color.bright( color.yellow( 'Warning: capture size is large. Please be patient.' ))) largewarned = True # Get captured DNS info for IP addresses eprint('Getting DNS info...') dnspackets = pyshark.FileCapture(pcapfile, keep_packets=False, display_filter='dns') dnspackets.apply_on_packets(net.get_dns_info, timeout=1000) with open(dnspkl, 'wb') as pklhandle: pickle.dump(net.dnsmap, pklhandle, protocol=pickle.HIGHEST_PROTOCOL) pickle.dump(net.dnsreqs, pklhandle, protocol=pickle.HIGHEST_PROTOCOL) # if os.path.exists(targetspkl) and not force: # eprint('Loading cached targets...') # with open(targetspkl, 'rb') as pklhandle: # try: # net.targets = pickle.load(pklhandle) # targetscacheloaded = True # except: # pass if not targetscacheloaded: if fullpacket: packets = pyshark.FileCapture(pcapfile, keep_packets=False) # Get hosts contacted eprint('Getting hosts contacted...') packets.apply_on_packets(net.get_hosts_contacted_fullpacket, timeout=1000) else: packets = pyshark.FileCapture(pcapfile, keep_packets=False, only_summaries=True) # Get hosts contacted eprint('Getting hosts contacted...') packets.apply_on_packets(net.get_hosts_contacted, timeout=1000) # with open(targetspkl, 'wb') as pklhandle: # pickle.dump( # net.targets, pklhandle, protocol=pickle.HIGHEST_PROTOCOL) # Print report generate_report(app, fullpacket=fullpacket, pcapfile=pcapfile) # Reset globals net.clear()
def get_dtls_info(pkt): global dtlspacketcount, dtlsversions, negotiateddtlsciphers try: dtlspkt = pkt.dtls dtlspacketcount = dtlspacketcount + 1 handshake = dtlspkt.handshake if handshake == 'Handshake Protocol: Client Hello': dtlshost = get_host_contacted(pkt) # print(pkt) maxdtlsversion = 0 ciphersuitelist = [] destination_host = get_host_contacted(pkt) for field_line in dtlspkt._get_all_field_lines(): if field_line.startswith('\tVersion: '): intdtlsversion = extract_intval(field_line) if intdtlsversion > maxdtlsversion: # Newer DTLS version than we've seen so far maxdtlsversion = intdtlsversion dtlsversion = extract_property( field_line, 'Version') if field_line.startswith('\tCipher Suite: '): ciphersuite = extract_property( field_line, 'Cipher Suite') if ciphersuite not in requesteddtlsciphers: requesteddtlsciphers.append(ciphersuite) if ciphersuite in mandatory_ciphers: ciphersuite = color.bright( color.green(ciphersuite)) elif ciphersuite in optional_ciphers: ciphersuite = color.bright(ciphersuite) ciphersuitelist.append(ciphersuite) # print('%s: %s' % # (color.bright('Cipher suite'), ciphersuite)) # Add host to list of hosts contacted per DTLS version dtlsversions = addonlynew( dtlsversions, dtlsversion, dtlshost) if str(dtlsversion) == 'DTLS 1.2': dtlsversion = color.green(dtlsversion) else: dtlsversion = color.red(dtlsversion) if args.verbose: print('Client request handshake with %s: %s' % (destination_host, color.bright(dtlsversion))) for ciphersuite in ciphersuitelist: if args.verbose: print('%s: %s' % ('Client-supported cipher suite', ciphersuite)) elif handshake == 'Handshake Protocol: Server Hello': dtlshost = get_source_host(pkt) #print('Server hello!') negotiated_ciphersuite = pkt.dtls.handshake_ciphersuite.showname negotiated_ciphersuite = extract_notab_property( negotiated_ciphersuite, 'Cipher Suite') # print('*** Negotiated DTLS ciphersuite: %s' % # negotiated_ciphersuite) # if negotiated_ciphersuite not in negotiateddtlsciphers: # negotiateddtlsciphers.append(negotiated_ciphersuite) negotiateddtlsciphers = addonlynew( negotiateddtlsciphers, negotiated_ciphersuite, dtlshost) if args.verbose: print('Negotiated ciphersuite with %s: %s' % (dtlshost, color.bright(negotiated_ciphersuite))) print('***********') except AttributeError: pass
def get_ssl_info(pkt): global sslpacketcount, sslversions, negotiatedciphers try: # Assume SSLv3 or TLS sslpkt = pkt.ssl sslpacketcount = sslpacketcount + 1 handshake = sslpkt.handshake if handshake == 'Handshake Protocol: Client Hello': # print(pkt) maxsslversion = 0 ciphersuitelist = [] sslhost = get_host_contacted(pkt) for field_line in sslpkt._get_all_field_lines(): if field_line.startswith('\tVersion: '): intsslversion = extract_intval(field_line) if intsslversion > maxsslversion: # Newer SSL/TLS version than we've seen so far maxsslversion = intsslversion sslversion = extract_property( field_line, 'Version') if field_line.startswith('\tCipher Suite: '): ciphersuite = extract_property( field_line, 'Cipher Suite') if ciphersuite not in requestedciphers: requestedciphers.append(ciphersuite) if ciphersuite in mandatory_ciphers: ciphersuite = color.bright( color.green(ciphersuite)) elif ciphersuite in optional_ciphers: ciphersuite = color.bright(ciphersuite) ciphersuitelist.append(ciphersuite) # print('%s: %s' % # (color.bright('Cipher suite'), ciphersuite)) # Add host to list of hosts contacted per SSL version sslversions = addonlynew( sslversions, sslversion, sslhost) if str(sslversion) == 'TLS 1.2': sslversion = color.green(sslversion) else: sslversion = color.red(sslversion) if args.verbose: print('Client request handshake with %s: %s' % (sslhost, color.bright(sslversion))) for ciphersuite in ciphersuitelist: if args.verbose: print('%s: %s' % ('Client-supported cipher suite', ciphersuite)) elif handshake == 'Handshake Protocol: Server Hello': sslhost = get_source_host(pkt) #print('Server hello!') negotiated_ciphersuite = pkt.ssl.handshake_ciphersuite.showname negotiated_ciphersuite = extract_notab_property( negotiated_ciphersuite, 'Cipher Suite') # print('*** Negotiated SSL/TLS ciphersuite: %s' % # negotiated_ciphersuite) # if negotiated_ciphersuite not in negotiatedciphers: # negotiatedciphers.append(negotiated_ciphersuite) negotiatedciphers = addonlynew( negotiatedciphers, negotiated_ciphersuite, sslhost) if args.verbose: print('Negotiated ciphersuite with %s: %s' % (sslhost, color.bright(negotiated_ciphersuite))) print('***********') except AttributeError: # SSLv2 doesn't have "handshake" structure try: sslpkt = pkt.ssl sslhost = get_host_contacted(pkt) if sslpkt.record == 'SSLv2 Record Layer: Client Hello': sslversion = 'SSLv2' if sslversion not in sslversions: sslversions.append(str(sslversion)) destination_host = get_host_contacted(pkt) if args.verbose: print('Client request handshake with %s: %s' % (destination_host, color.bright(color.red('SSLv2')))) for field_line in sslpkt._get_all_field_lines(): if field_line.startswith('\tCipher Spec: '): ciphersuite = extract_property( field_line, 'Cipher Spec') if ciphersuite not in requestedciphers: requestedciphers.append(ciphersuite) if ciphersuite in mandatory_ciphers: ciphersuite = color.bright( color.green(ciphersuite)) elif ciphersuite in optional_ciphers: ciphersuite = color.bright(ciphersuite) if args.verbose: print('%s: %s' % ('Client-supported cipher spec', ciphersuite)) elif sslpkt.record == 'SSLv2 Record Layer: Server Hello': negotiated_cipherspec = pkt.ssl.handshake_cipherspec.showname negotiated_cipherspec = extract_notab_property( negotiated_cipherspec, 'Cipher Spec') if negotiated_cipherspec not in negotiatedciphers: negotiatedciphers.append(negotiated_cipherspec) if negotiated_cipherspec not in optional_ciphers and negotiated_cipherspec not in mandatory_ciphers: negotiated_cipherspec = color.red( negotiated_cipherspec) destination_host = get_source_host(pkt) if args.verbose: print('Negotiated cipherspec with %s: %s' % (destination_host, color.bright(negotiated_cipherspec))) print('***********') except AttributeError: pass
def check_app(app, searchterm, encoding='string'): ''' Check application based on app name in Tapioca results ''' global pcapfile, ssltestfile, fullmitmfile global found, foundunprot, foundprot, foundunenc ssltesttime = None fullmitmtime = None pcaptime = None appbase = os.path.basename(app) # Get pcap file location if appbase == ssltestfile or app == fullmitmfile: # Check mitmproxy log logfile = app jsonfile = '%s.%s' % (app, json_output) if os.path.exists(logfile): if appbase == ssltestfile: ssltesttime = os.path.getmtime(app) elif appbase == fullmitmfile: fullmitmtime = os.path.getmtime(app) print_header(logfile) print( color.bright('searching %s for %s (%s)') % (color.cyan(logfile), searchterm, encoding)) searchmitmflow(logfile, searchterm) print('') elif appbase.endswith('.pcap'): # Check tcpdump pcap logfile = app jsonfile = '%s.%s' % (app, json_output) if os.path.exists(logfile): pcaptime = os.path.getmtime(app) print_header(logfile) print( color.bright('searching %s for %s (%s)') % (color.cyan(logfile), searchterm, encoding)) searchtcpdump(logfile, searchterm) print('') else: # check app (all captures availabale) appdir = os.path.join('results', app) jsonfile = os.path.join(appdir, json_output) # app name, so check all three logfile = os.path.join('results', app, pcapfile) if os.path.exists(logfile): pcaptime = os.path.getmtime(logfile) print_header(logfile) print( color.bright('searching %s for %s (%s)') % (color.cyan(logfile), searchterm, encoding)) searchtcpdump(logfile, searchterm) print('') logfile = os.path.join('results', app, ssltestfile) if os.path.exists(logfile): ssltesttime = os.path.getmtime(logfile) print_header(logfile) print( color.bright('searching %s for %s (%s)') % (color.cyan(logfile), searchterm, encoding)) searchmitmflow(logfile, searchterm) print('') logfile = os.path.join('results', app, fullmitmfile) if os.path.exists(logfile): fullmitmtime = os.path.getmtime(logfile) print_header(logfile) print( color.bright('searching %s for %s (%s)') % (color.cyan(logfile), searchterm, encoding)) searchmitmflow(logfile, searchterm) print('') report = {} report['app'] = app report['pcaptime'] = pcaptime report['ssltesttime'] = ssltesttime report['fullmitmtime'] = fullmitmtime report['searchterm'] = searchterm report['found'] = found report['foundunenc'] = foundunenc report['foundunprot'] = foundunprot report['foundprot'] = foundprot with open(jsonfile, 'w') as fp: json.dump(report, fp)
def searchmitmflow(flowfile, searchterm): global found, foundunprot, foundprot # Searches are case insensitive pcre = re.compile('(?i)' + searchterm) # Create a dictionary of all of the messages in the flow with open(flowfile, 'rb') as logfile: fr = io.FlowReader(logfile) msgnum = 0 flowdict = {} messages = [] for msg in fr.stream(): messagedict = {} responsedict = {} requestdict = {} messagedict['msgnum'] = msgnum requestdict['uri'] = msg.request.pretty_url requestdict['method'] = msg.request.method requestdict['scheme'] = msg.request.scheme requestdict['headers'] = msg.request.headers requestcontent = msg.request.content decodedcontent = decodecontent(requestcontent) if decodedcontent: # mitmproxy found a way to decode the content requestdict['content'] = decodedcontent else: # just take the raw bytes requestdict['content'] = requestcontent try: responsedict['headers'] = msg.response.headers except AttributeError: responsedict['headers'] = '' try: responsecontent = msg.response.content except AttributeError: responsecontent = '' try: decodedcontent = decodecontent(responsecontent) if decodedcontent: # mitmproxy found a way to decode the content responsedict['content'] = decodecontent(responsecontent) else: # just take the raw bytes responsedict['content'] = responsecontent except AttributeError: responsedict['content'] = '' messagedict['request'] = requestdict messagedict['response'] = responsedict # print(messagedict) messages.append(messagedict) msgnum = msgnum + 1 flowdict['messages'] = messages # Check for matches in the flow dictionary for message in flowdict['messages']: msgnum = message['msgnum'] for key in message: if key == 'msgnum': continue else: for value in message[key].values(): if pcre.search(str(value)): found = True print( color.bright( color.green( 'Found match for %s in %s message [%s] field [%s]:' % (searchterm, flowfile, msgnum + 1, key)))) if message['request']['scheme'] == 'https': if flowfile.endswith('ssltest.log'): foundunprot = True print( color.bright( color.red( '%s found in non-validated HTTPS traffic!' % searchterm))) elif flowfile.endswith('flows.log'): foundprot = True color.bright( '%s found in validated HTTPS traffic' % searchterm) elif message['request']['scheme'] == 'http': foundunenc = True print( color.bright( color.red( '%s found in unencrypted HTTP traffic!' % searchterm))) print(str(value))