def create_share_comment_link(text, action): """Parse indicators from the text and create links for ThreatConnect share comments.""" response = str() error = False # map the keys from the ioc finder to the indicator types expected by threatconnect (respectively) ioc_finder_to_threatconnect_mappings = { 'domain': 'host', 'email': 'emailaddress', 'ipv4': 'address', 'md5': 'file', 'sha1': 'file', 'sha256': 'file', 'url': 'url' } indicators = ioc_finder.find_iocs(text) for indicator_type in indicators: if indicator_type in ioc_finder_to_threatconnect_mappings: tc_ind_type = ioc_finder_to_threatconnect_mappings[indicator_type] else: continue for indicator in indicators[indicator_type]: response += "\n[[{}:{}]]".format(tc_ind_type, indicator) return response, False
def test_asn_parsing(): s = 'NWD2HUBCAS8.ad.analog.com' iocs = find_iocs(s) assert iocs['asns'] == [] s = 'here is an asn: "AS8"' iocs = find_iocs(s) assert iocs['asns'] == ['ASN8'] s = 'here is an asn: AS8foobar' iocs = find_iocs(s) assert iocs['asns'] == [] s = 'as8' iocs = find_iocs(s) assert iocs['asns'] == ['ASN8']
def test_not_parsing_authentihash(): s = 'authentihash 3f1b149d07e7e8636636b8b7f7043c40ed64a10b28986181fb046c498432c2d4' iocs = find_iocs(s, parse_authentihashes=False) assert 'authentihashes' not in iocs assert iocs['sha256s'] == [ '3f1b149d07e7e8636636b8b7f7043c40ed64a10b28986181fb046c498432c2d4' ]
def test_file_hash_parsing(): s = "{} {} {} {} {}".format('A'*32, 'a'*32, 'b'*40, 'c'*64, 'd'*128) iocs = find_iocs(s) assert len(iocs['md5s']) == 1 assert len(iocs['sha1s']) == 1 assert len(iocs['sha256s']) == 1 assert len(iocs['sha512s']) == 1
def test_registry_key_parsing(): s = "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows HKLM\Software\Microsoft\Windows HKCC\Software\Microsoft\Windows" iocs = find_iocs(s) assert len(iocs['registry_key_paths']) == 3 assert 'HKEY_LOCAL_MACHINE\Software\Microsoft\Windows' in iocs['registry_key_paths'] assert 'HKLM\Software\Microsoft\Windows' in iocs['registry_key_paths'] assert 'HKCC\Software\Microsoft\Windows' in iocs['registry_key_paths']
def test_certificate_serial_number_issue_96(): # see https://github.com/fhightower/ioc-finder/issues/96 s = '''SolarWinds.Orion.Core.BusinessLayer.dll is signed by SolarWinds, using the certificate with serial number 0f:e9:73:75:20:22:a6:06:ad:f2:a3:6e:34:5d:c0:ed. The file was signed on March 24, 2020.''' observables = find_iocs(s) print(observables) assert observables['ipv6s'] == [] assert observables['mac_addresses'] == []
def test_url_parsing(): invalid_urls = [ 'foo@{}.com'.format('a' * 64), '[email protected]', 'foo@abc', '@@@@-hi-.com', '@_hi_.com', 'me@*hi*.com', 'foo{}.com'.format('a' * 64), '.com', 'abc', '-hi-.com', '_hi_.com', '*hi*.com', ] valid_urls = [ 'https://a.com', 'https://en.wikipedia.com', 'https://{}.com'.format('a' * 63), 'https://{}.{}.com'.format('a' * 63, 'a' * 63), 'https://test-ing.com', 'https://2600.com', 'https://example.com', 'http://example.com', 'ftp://example.com', 'http://"John..Doe"@example.com', 'http://[email protected]', 'http://[email protected]', 'http://foo@{}.com'.format('a' * 63), ] iocs = find_iocs(' '.join(valid_urls)) assert len(iocs['urls']) == 13 # make sure domains are being parsed from the valid urls as well assert len(iocs['domains']) == 7 iocs = find_iocs(' '.join(invalid_urls)) assert len(iocs['urls']) == 0 s = 'http://8pretgdl.r.us-east-1.awstrack.me/L0/http:%2F%2Fwww.excelgoodies.com%2Fexcel-vba-training-in-virginia%23course-content/1/0100016ed23f4bef-b14931bd-26f6-4130-9c37-c4f9902a771d-000000/mHJBuJ8D1RcIDE3jrWkdw4I9im4=138' iocs = find_iocs(s) assert iocs['urls'] == [ 'http://8pretgdl.r.us-east-1.awstrack.me/L0/http:%2F%2Fwww.excelgoodies.com%2Fexcel-vba-training-in-virginia%23course-content/1/0100016ed23f4bef-b14931bd-26f6-4130-9c37-c4f9902a771d-000000/mHJBuJ8D1RcIDE3jrWkdw4I9im4=138' ]
def test_url_parsing(): for url in VALID_URLS: iocs = find_iocs(url) try: assert len(iocs['urls']) == 1 assert iocs['urls'][0] == url except AssertionError as e: print('failed on url: {}'.format(url)) raise e
def test_file_hash_parsing(): s = 'this is a test{}'.format('a' * 32) iocs = find_iocs(s) assert iocs['md5s'] == [] s = 'this is a test {}'.format('a' * 32) iocs = find_iocs(s) assert iocs['md5s'] == ['a' * 32] s = 'this is a test "{}"'.format('a' * 32) iocs = find_iocs(s) assert iocs['md5s'] == ['a' * 32] s = 'this is a test {}.'.format('a' * 32) iocs = find_iocs(s) assert iocs['md5s'] == ['a' * 32] s = '0x1a1db93766e31994507511c9c70a1dd94465cf6d' iocs = find_iocs(s) assert iocs['sha1s'] == ['1a1db93766e31994507511c9c70a1dd94465cf6d']
def mainReporter(ioc): engine_responses = [] ioc_allowed = ['urls', 'domains', 'ipv4s', 'sha256s', 'sha1s', 'md5s'] validate = find_iocs(ioc) analyze = {k: v for k, v in validate.items() if v and k in ioc_allowed} if analyze: for key, value in analyze.items(): if key == ioc_allowed[0]: vtUrl = VTUrlReporter(value) urlHaus = UrlHausUrlReporter(value) capeUrl = CapeReporter(value) scanUrl = UrlScanReporter(value) engine_responses = vtUrl + urlHaus + capeUrl + scanUrl if key == ioc_allowed[1]: vtDom = VTUrlReporter(value) urlHausDom = UrlHausUrlReporter(value) capeDom = CapeReporter(value) scanDom = UrlScanReporter(value, True) engine_responses = engine_responses + vtDom + urlHausDom + capeDom + scanDom if key == ioc_allowed[2]: abuse = AbuseReporter(value) vtIp = VTIpReporter(value) capeIp = CapeReporter(value) scanIp = UrlScanReporter(value) engine_responses = engine_responses + abuse + vtIp + capeIp + scanIp if key == ioc_allowed[3]: malshare256 = malshareReporter(value) vt256 = VTHashReporter(value) urlHaus256 = UrlHausHashReporter(value, 'sha256_hash') valhalla256 = ValhallaReporter(value) hybrid256 = HybridReporter(value) cape256 = CapeReporter(value) engine_responses = engine_responses + malshare256 + vt256 + urlHaus256 + valhalla256 + hybrid256 + cape256 if key == ioc_allowed[4]: malshare1 = malshareReporter(value) vt1 = VTHashReporter(value) hybrid1 = HybridReporter(value) cape1 = CapeReporter(value) engine_responses = engine_responses + malshare1 + vt1 + hybrid1 + cape1 if key == ioc_allowed[5]: malshare5 = malshareReporter(value) vt5 = VTHashReporter(value) urlHaus5 = UrlHausHashReporter(value, 'md5_hash') hybrid5 = HybridReporter(value) cape5 = CapeReporter(value) engine_responses = engine_responses + malshare5 + vt5 + urlHaus5 + hybrid5 + cape5 return engine_responses