misp-modules 2.4.196__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- misp_modules/__init__.py +379 -0
- misp_modules/helpers/__init__.py +1 -0
- misp_modules/helpers/cache.py +84 -0
- misp_modules/lib/__init__.py +4 -0
- misp_modules/lib/_vmray/__init__.py +0 -0
- misp_modules/lib/_vmray/parser.py +1417 -0
- misp_modules/lib/_vmray/rest_api.py +148 -0
- misp_modules/lib/cof2misp/LICENSE-2.0.txt +202 -0
- misp_modules/lib/cof2misp/__init__.py +0 -0
- misp_modules/lib/cof2misp/cof.py +165 -0
- misp_modules/lib/joe_mapping.py +114 -0
- misp_modules/lib/joe_parser.py +573 -0
- misp_modules/lib/lastline_api.py +841 -0
- misp_modules/lib/qintel_helper.py +263 -0
- misp_modules/lib/stix2misp.py +2080 -0
- misp_modules/lib/stix2misp_mapping.py +460 -0
- misp_modules/lib/synonymsToTagNames.json +1 -0
- misp_modules/lib/vt_graph_parser/__init__.py +8 -0
- misp_modules/lib/vt_graph_parser/errors.py +20 -0
- misp_modules/lib/vt_graph_parser/helpers/__init__.py +7 -0
- misp_modules/lib/vt_graph_parser/helpers/parsers.py +88 -0
- misp_modules/lib/vt_graph_parser/helpers/rules.py +304 -0
- misp_modules/lib/vt_graph_parser/helpers/wrappers.py +58 -0
- misp_modules/lib/vt_graph_parser/importers/__init__.py +7 -0
- misp_modules/lib/vt_graph_parser/importers/base.py +98 -0
- misp_modules/lib/vt_graph_parser/importers/pymisp_response.py +73 -0
- misp_modules/modules/__init__.py +4 -0
- misp_modules/modules/action_mod/__init__.py +1 -0
- misp_modules/modules/action_mod/_utils/__init__.py +1 -0
- misp_modules/modules/action_mod/_utils/utils.py +70 -0
- misp_modules/modules/action_mod/mattermost.py +113 -0
- misp_modules/modules/action_mod/slack.py +96 -0
- misp_modules/modules/action_mod/testaction.py +68 -0
- misp_modules/modules/expansion/__init__.py +36 -0
- misp_modules/modules/expansion/_dnsdb_query/COPYRIGHT +27 -0
- misp_modules/modules/expansion/_dnsdb_query/LICENSE +202 -0
- misp_modules/modules/expansion/_dnsdb_query/README.md +162 -0
- misp_modules/modules/expansion/_dnsdb_query/__init__.py +0 -0
- misp_modules/modules/expansion/_dnsdb_query/dnsdb_query.py +327 -0
- misp_modules/modules/expansion/_ransomcoindb/__init__.py +0 -0
- misp_modules/modules/expansion/_ransomcoindb/ransomcoindb.py +96 -0
- misp_modules/modules/expansion/_vulnerability_parser/__init__.py +0 -0
- misp_modules/modules/expansion/_vulnerability_parser/vulnerability_parser.py +118 -0
- misp_modules/modules/expansion/abuseipdb.py +146 -0
- misp_modules/modules/expansion/apiosintds.py +365 -0
- misp_modules/modules/expansion/apivoid.py +133 -0
- misp_modules/modules/expansion/assemblyline_query.py +179 -0
- misp_modules/modules/expansion/assemblyline_submit.py +100 -0
- misp_modules/modules/expansion/backscatter_io.py +84 -0
- misp_modules/modules/expansion/btc_scam_check.py +54 -0
- misp_modules/modules/expansion/btc_steroids.py +238 -0
- misp_modules/modules/expansion/censys_enrich.py +287 -0
- misp_modules/modules/expansion/circl_passivedns.py +85 -0
- misp_modules/modules/expansion/circl_passivessl.py +113 -0
- misp_modules/modules/expansion/clamav.py +129 -0
- misp_modules/modules/expansion/cluster25_expand.py +239 -0
- misp_modules/modules/expansion/countrycode.py +69 -0
- misp_modules/modules/expansion/cpe.py +140 -0
- misp_modules/modules/expansion/crowdsec.py +235 -0
- misp_modules/modules/expansion/crowdstrike_falcon.py +148 -0
- misp_modules/modules/expansion/cuckoo_submit.py +161 -0
- misp_modules/modules/expansion/cve.py +57 -0
- misp_modules/modules/expansion/cve_advanced.py +185 -0
- misp_modules/modules/expansion/cytomic_orion.py +196 -0
- misp_modules/modules/expansion/dbl_spamhaus.py +78 -0
- misp_modules/modules/expansion/dns.py +71 -0
- misp_modules/modules/expansion/docx_enrich.py +71 -0
- misp_modules/modules/expansion/domaintools.py +290 -0
- misp_modules/modules/expansion/eql.py +91 -0
- misp_modules/modules/expansion/eupi.py +86 -0
- misp_modules/modules/expansion/extract_url_components.py +83 -0
- misp_modules/modules/expansion/farsight_passivedns.py +243 -0
- misp_modules/modules/expansion/geoip_asn.py +75 -0
- misp_modules/modules/expansion/geoip_city.py +75 -0
- misp_modules/modules/expansion/geoip_country.py +73 -0
- misp_modules/modules/expansion/google_safe_browsing.py +86 -0
- misp_modules/modules/expansion/google_search.py +57 -0
- misp_modules/modules/expansion/google_threat_intelligence.py +453 -0
- misp_modules/modules/expansion/greynoise.py +346 -0
- misp_modules/modules/expansion/hashdd.py +53 -0
- misp_modules/modules/expansion/hashlookup.py +118 -0
- misp_modules/modules/expansion/hibp.py +62 -0
- misp_modules/modules/expansion/html_to_markdown.py +63 -0
- misp_modules/modules/expansion/hyasinsight.py +881 -0
- misp_modules/modules/expansion/intel471.py +73 -0
- misp_modules/modules/expansion/intelmq_eventdb.py.experimental +67 -0
- misp_modules/modules/expansion/ip2locationio.py +90 -0
- misp_modules/modules/expansion/ipasn.py +70 -0
- misp_modules/modules/expansion/ipinfo.py +112 -0
- misp_modules/modules/expansion/ipqs_fraud_and_risk_scoring.py +633 -0
- misp_modules/modules/expansion/iprep.py +98 -0
- misp_modules/modules/expansion/jinja_template_rendering.py +54 -0
- misp_modules/modules/expansion/joesandbox_query.py +91 -0
- misp_modules/modules/expansion/joesandbox_submit.py +147 -0
- misp_modules/modules/expansion/lastline_query.py +148 -0
- misp_modules/modules/expansion/lastline_submit.py +180 -0
- misp_modules/modules/expansion/macaddress_io.py +130 -0
- misp_modules/modules/expansion/macvendors.py +55 -0
- misp_modules/modules/expansion/malshare_upload.py +107 -0
- misp_modules/modules/expansion/malwarebazaar.py +67 -0
- misp_modules/modules/expansion/mcafee_insights_enrich.py +249 -0
- misp_modules/modules/expansion/mmdb_lookup.py +138 -0
- misp_modules/modules/expansion/module.py.skeleton +44 -0
- misp_modules/modules/expansion/mwdb.py +152 -0
- misp_modules/modules/expansion/ocr_enrich.py +74 -0
- misp_modules/modules/expansion/ods_enrich.py +71 -0
- misp_modules/modules/expansion/odt_enrich.py +61 -0
- misp_modules/modules/expansion/onyphe.py +243 -0
- misp_modules/modules/expansion/onyphe_full.py +387 -0
- misp_modules/modules/expansion/otx.py +167 -0
- misp_modules/modules/expansion/passive_ssh.py +150 -0
- misp_modules/modules/expansion/passivetotal.py +358 -0
- misp_modules/modules/expansion/pdf_enrich.py +58 -0
- misp_modules/modules/expansion/pptx_enrich.py +65 -0
- misp_modules/modules/expansion/qintel_qsentry.py +229 -0
- misp_modules/modules/expansion/qrcode.py +99 -0
- misp_modules/modules/expansion/ransomcoindb.py +82 -0
- misp_modules/modules/expansion/rbl.py +126 -0
- misp_modules/modules/expansion/recordedfuture.py +544 -0
- misp_modules/modules/expansion/reversedns.py +77 -0
- misp_modules/modules/expansion/securitytrails.py +571 -0
- misp_modules/modules/expansion/shodan.py +244 -0
- misp_modules/modules/expansion/sigma_queries.py +61 -0
- misp_modules/modules/expansion/sigma_syntax_validator.py +49 -0
- misp_modules/modules/expansion/sigmf_expand.py +303 -0
- misp_modules/modules/expansion/socialscan.py +108 -0
- misp_modules/modules/expansion/sophoslabs_intelix.py +146 -0
- misp_modules/modules/expansion/sourcecache.py +57 -0
- misp_modules/modules/expansion/stairwell.py +156 -0
- misp_modules/modules/expansion/stix2_pattern_syntax_validator.py +56 -0
- misp_modules/modules/expansion/threatcrowd.py +170 -0
- misp_modules/modules/expansion/threatfox.py +75 -0
- misp_modules/modules/expansion/threatminer.py +152 -0
- misp_modules/modules/expansion/triage_submit.py +119 -0
- misp_modules/modules/expansion/trustar_enrich.py +235 -0
- misp_modules/modules/expansion/urlhaus.py +164 -0
- misp_modules/modules/expansion/urlscan.py +269 -0
- misp_modules/modules/expansion/variotdbs.py +133 -0
- misp_modules/modules/expansion/virustotal.py +311 -0
- misp_modules/modules/expansion/virustotal_public.py +272 -0
- misp_modules/modules/expansion/virustotal_upload.py +91 -0
- misp_modules/modules/expansion/vmray_submit.py +161 -0
- misp_modules/modules/expansion/vmware_nsx.py +628 -0
- misp_modules/modules/expansion/vulndb.py +292 -0
- misp_modules/modules/expansion/vulnerability_lookup.py +324 -0
- misp_modules/modules/expansion/vulners.py +81 -0
- misp_modules/modules/expansion/vysion.py +221 -0
- misp_modules/modules/expansion/whois.py +72 -0
- misp_modules/modules/expansion/whoisfreaks.py +232 -0
- misp_modules/modules/expansion/wiki.py +58 -0
- misp_modules/modules/expansion/xforceexchange.py +189 -0
- misp_modules/modules/expansion/xlsx_enrich.py +63 -0
- misp_modules/modules/expansion/yara_query.py +70 -0
- misp_modules/modules/expansion/yara_syntax_validator.py +49 -0
- misp_modules/modules/expansion/yeti.py +196 -0
- misp_modules/modules/export_mod/__init__.py +3 -0
- misp_modules/modules/export_mod/cef_export.py +93 -0
- misp_modules/modules/export_mod/cisco_firesight_manager_ACL_rule_export.py +150 -0
- misp_modules/modules/export_mod/defender_endpoint_export.py +141 -0
- misp_modules/modules/export_mod/goamlexport.py +255 -0
- misp_modules/modules/export_mod/liteexport.py +97 -0
- misp_modules/modules/export_mod/mass_eql_export.py +106 -0
- misp_modules/modules/export_mod/nexthinkexport.py +131 -0
- misp_modules/modules/export_mod/osqueryexport.py +125 -0
- misp_modules/modules/export_mod/pdfexport.py +107 -0
- misp_modules/modules/export_mod/testexport.py +73 -0
- misp_modules/modules/export_mod/threatStream_misp_export.py +114 -0
- misp_modules/modules/export_mod/threat_connect_export.py +125 -0
- misp_modules/modules/export_mod/virustotal_collections.py +141 -0
- misp_modules/modules/export_mod/vt_graph.py +120 -0
- misp_modules/modules/export_mod/yara_export.py +290 -0
- misp_modules/modules/import_mod/__init__.py +22 -0
- misp_modules/modules/import_mod/cof2misp.py +264 -0
- misp_modules/modules/import_mod/csvimport.py +319 -0
- misp_modules/modules/import_mod/cuckooimport.py +749 -0
- misp_modules/modules/import_mod/email_import.py +294 -0
- misp_modules/modules/import_mod/goamlimport.py +188 -0
- misp_modules/modules/import_mod/import_blueprint.py +93 -0
- misp_modules/modules/import_mod/joe_import.py +74 -0
- misp_modules/modules/import_mod/lastline_import.py +160 -0
- misp_modules/modules/import_mod/mispjson.py +73 -0
- misp_modules/modules/import_mod/ocr.py +122 -0
- misp_modules/modules/import_mod/openiocimport.py +99 -0
- misp_modules/modules/import_mod/taxii21.py +383 -0
- misp_modules/modules/import_mod/testimport.py +73 -0
- misp_modules/modules/import_mod/threatanalyzer_import.py +552 -0
- misp_modules/modules/import_mod/url_import.py +97 -0
- misp_modules/modules/import_mod/vmray_import.py +96 -0
- misp_modules/modules/import_mod/vmray_summary_json_import.py +87 -0
- misp_modules-2.4.196.dist-info/LICENSE +661 -0
- misp_modules-2.4.196.dist-info/METADATA +281 -0
- misp_modules-2.4.196.dist-info/RECORD +194 -0
- misp_modules-2.4.196.dist-info/WHEEL +4 -0
- misp_modules-2.4.196.dist-info/entry_points.txt +3 -0
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from pyintel471 import PyIntel471
|
|
3
|
+
|
|
4
|
+
misperrors = {'error': 'Error'}
|
|
5
|
+
mispattributes = {'input': ['hostname', 'domain', 'url', 'ip-src', 'ip-dst', 'email-src',
|
|
6
|
+
'email-dst', 'target-email', 'whois-registrant-email',
|
|
7
|
+
'whois-registrant-name', 'md5', 'sha1', 'sha256'], 'output': ['freetext']}
|
|
8
|
+
moduleinfo = {
|
|
9
|
+
'version': '0.1',
|
|
10
|
+
'author': 'Raphaël Vinot',
|
|
11
|
+
'description': 'Module to access Intel 471',
|
|
12
|
+
'module-type': ['hover', 'expansion'],
|
|
13
|
+
'name': 'Intel471 Lookup',
|
|
14
|
+
'logo': 'intel471.png',
|
|
15
|
+
'requirements': ['The intel471 python library'],
|
|
16
|
+
'features': 'The module uses the Intel471 python library to query the Intel471 API with the value of the input attribute. The result of the query is then returned as freetext so the Freetext import parses it.',
|
|
17
|
+
'references': ['https://public.intel471.com/'],
|
|
18
|
+
'input': 'A MISP attribute whose type is included in the following list:\n- hostname\n- domain\n- url\n- ip-src\n- ip-dst\n- email-src\n- email-dst\n- target-email\n- whois-registrant-email\n- whois-registrant-name\n- md5\n- sha1\n- sha256',
|
|
19
|
+
'output': 'Freetext',
|
|
20
|
+
'descrption': 'An expansion module to query Intel471 in order to get additional information about a domain, ip address, email address, url or hash.',
|
|
21
|
+
}
|
|
22
|
+
moduleconfig = ['email', 'authkey']
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def cleanup(response):
|
|
26
|
+
'''The entries have uids that will be recognised as hashes when they shouldn't'''
|
|
27
|
+
j = response.json()
|
|
28
|
+
if j['iocTotalCount'] == 0:
|
|
29
|
+
return 'Nothing has been found.'
|
|
30
|
+
for ioc in j['iocs']:
|
|
31
|
+
ioc.pop('uid')
|
|
32
|
+
if ioc['links']['actorTotalCount'] > 0:
|
|
33
|
+
for actor in ioc['links']['actors']:
|
|
34
|
+
actor.pop('uid')
|
|
35
|
+
if ioc['links']['reportTotalCount'] > 0:
|
|
36
|
+
for report in ioc['links']['reports']:
|
|
37
|
+
report.pop('uid')
|
|
38
|
+
return json.dumps(j, indent=2)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def handler(q=False):
|
|
42
|
+
if q is False:
|
|
43
|
+
return False
|
|
44
|
+
request = json.loads(q)
|
|
45
|
+
for input_type in mispattributes['input']:
|
|
46
|
+
if input_type in request:
|
|
47
|
+
to_query = request[input_type]
|
|
48
|
+
break
|
|
49
|
+
else:
|
|
50
|
+
misperrors['error'] = "Unsupported attributes type"
|
|
51
|
+
return misperrors
|
|
52
|
+
|
|
53
|
+
if (request.get('config')):
|
|
54
|
+
if (request['config'].get('email') is None) or (request['config'].get('authkey') is None):
|
|
55
|
+
misperrors['error'] = 'Intel 471 authentication is missing'
|
|
56
|
+
return misperrors
|
|
57
|
+
|
|
58
|
+
intel471 = PyIntel471(email=request['config'].get('email'), authkey=request['config'].get('authkey'))
|
|
59
|
+
ioc_filters = intel471.iocs_filters(ioc=to_query)
|
|
60
|
+
res = intel471.iocs(filters=ioc_filters)
|
|
61
|
+
to_return = cleanup(res)
|
|
62
|
+
|
|
63
|
+
r = {'results': [{'types': mispattributes['output'], 'values': to_return}]}
|
|
64
|
+
return r
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def introspection():
|
|
68
|
+
return mispattributes
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def version():
|
|
72
|
+
moduleinfo['config'] = moduleconfig
|
|
73
|
+
return moduleinfo
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import psycopg2
|
|
3
|
+
|
|
4
|
+
misperrors = {'error': 'Error'}
|
|
5
|
+
mispattributes = {'input': ['hostname', 'domain', 'ip-src', 'ip-dst', 'AS'], 'output': ['freetext']}
|
|
6
|
+
moduleinfo = {'version': '0.1', 'author': 'L. Aaron Kaplan <kaplan@cert.at>', 'description': 'Module to access intelmqs eventdb', 'module-type': ['expansion', 'hover']}
|
|
7
|
+
moduleconfig = ['username', 'password', 'hostname', 'database']
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def connect(user, password, host, dbname):
|
|
11
|
+
try:
|
|
12
|
+
conn = psycopg2.connect(database=dbname, user=user, host=host, password=password)
|
|
13
|
+
except Exception as e:
|
|
14
|
+
print("I am unable to connect to the database: %s" %e)
|
|
15
|
+
return conn
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def handler(q=False):
|
|
19
|
+
if q is False:
|
|
20
|
+
return False
|
|
21
|
+
request = json.loads(q)
|
|
22
|
+
#if request.get('hostname'):
|
|
23
|
+
# toquery = request['hostname']
|
|
24
|
+
#elif request.get('domain'):
|
|
25
|
+
# toquery = request['domain']
|
|
26
|
+
if request.get('ip-src'):
|
|
27
|
+
toquery = request['ip-src']
|
|
28
|
+
#elif request.get('ip-dst'):
|
|
29
|
+
# toquery = request['ip-dst']
|
|
30
|
+
#elif request.get('AS'):
|
|
31
|
+
# toquery = request['AS']
|
|
32
|
+
else:
|
|
33
|
+
misperrors['error'] = "Unsupported attributes type"
|
|
34
|
+
return misperrors
|
|
35
|
+
|
|
36
|
+
if (request.get('config')):
|
|
37
|
+
if (request['config'].get('username') is None) or (request['config'].get('password') is None):
|
|
38
|
+
misperrors['error'] = 'intelmq eventdb authentication is missing'
|
|
39
|
+
return misperrors
|
|
40
|
+
|
|
41
|
+
conn = connect(request['config']['username'], request['config']['password'], request['config']['hostname'], request['config']['database'])
|
|
42
|
+
cur = conn.cursor()
|
|
43
|
+
SQL1 = 'SELECT COUNT(*) from events where "source.ip" = \'%s\'' %(toquery)
|
|
44
|
+
try:
|
|
45
|
+
cur.execute(SQL1)
|
|
46
|
+
except Exception as e:
|
|
47
|
+
misperrors['error'] = 'can not query database'
|
|
48
|
+
print(e)
|
|
49
|
+
return misperrors
|
|
50
|
+
|
|
51
|
+
results = cur.fetchone()
|
|
52
|
+
|
|
53
|
+
out = ''
|
|
54
|
+
out = out + "{} ".format(results[0]) + " results found in the DB"
|
|
55
|
+
|
|
56
|
+
r = {'results': [{'types': mispattributes['output'], 'values': out}]}
|
|
57
|
+
conn.close()
|
|
58
|
+
return r
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def introspection():
|
|
62
|
+
return mispattributes
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def version():
|
|
66
|
+
moduleinfo['config'] = moduleconfig
|
|
67
|
+
return moduleinfo
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import requests
|
|
3
|
+
from . import check_input_attribute, standard_error_message
|
|
4
|
+
from pymisp import MISPAttribute, MISPEvent, MISPObject
|
|
5
|
+
|
|
6
|
+
mispattributes = {
|
|
7
|
+
'input': ['ip-src', 'ip-dst'],
|
|
8
|
+
'format': 'misp_standard'
|
|
9
|
+
}
|
|
10
|
+
moduleinfo = {
|
|
11
|
+
'version': 1,
|
|
12
|
+
'author': 'IP2Location.io',
|
|
13
|
+
'description': 'An expansion module to query IP2Location.io to gather more information on a given IP address.',
|
|
14
|
+
'module-type': ['expansion', 'hover'],
|
|
15
|
+
'name': 'IP2Location.io Lookup',
|
|
16
|
+
'logo': 'ip2locationio.png',
|
|
17
|
+
'requirements': ['An IP2Location.io token'],
|
|
18
|
+
'features': 'The module takes an IP address attribute as input and queries the IP2Location.io API. \nFree plan user will get the basic geolocation informaiton, and different subsription plan will get more information on the IP address. \n Refer to [pricing page](https://www.ip2location.io/pricing) for more information on data available for each plan. \n\nMore information on the responses content is available in the [documentation](https://www.ip2location.io/ip2location-documentation).',
|
|
19
|
+
'references': ['https://www.ip2location.io/ip2location-documentation'],
|
|
20
|
+
'input': 'IP address attribute.',
|
|
21
|
+
'output': 'Additional information on the IP address, such as geolocation, proxy and so on. Refer to the Response Format section in https://www.ip2location.io/ip2location-documentation to find out the full format of the data returned.',
|
|
22
|
+
}
|
|
23
|
+
moduleconfig = ['key']
|
|
24
|
+
|
|
25
|
+
_GEOLOCATION_OBJECT_MAPPING = {
|
|
26
|
+
'country_code': 'countrycode',
|
|
27
|
+
'country_name': 'country',
|
|
28
|
+
'region_name': 'region',
|
|
29
|
+
'city_name': 'city',
|
|
30
|
+
'zip_code': 'zipcode',
|
|
31
|
+
'latitude': 'latitude',
|
|
32
|
+
'longitude': 'longitude'
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def handler(q=False):
|
|
37
|
+
# Input checks
|
|
38
|
+
if q is False:
|
|
39
|
+
return False
|
|
40
|
+
request = json.loads(q)
|
|
41
|
+
if not request.get('attribute') or not check_input_attribute(request['attribute']):
|
|
42
|
+
return {'error': f'{standard_error_message}, which should contain at least a type, a value and an uuid.'}
|
|
43
|
+
attribute = request['attribute']
|
|
44
|
+
if attribute.get('type') not in mispattributes['input']:
|
|
45
|
+
return {'error': 'Wrong input attribute type.'}
|
|
46
|
+
if not request.get('config'):
|
|
47
|
+
return {'error': 'Missing ip2locationio config.'}
|
|
48
|
+
if not request['config'].get('key'):
|
|
49
|
+
return {'error': 'Missing ip2locationio API key.'}
|
|
50
|
+
|
|
51
|
+
# Query ip2location.io
|
|
52
|
+
query = requests.get(
|
|
53
|
+
f"https://api.ip2location.io/json?key={request['config']['key']}&ip={attribute['value']}"
|
|
54
|
+
)
|
|
55
|
+
if query.status_code != 200:
|
|
56
|
+
return {'error': f'Error while querying ip2location.io - {query.status_code}: {query.reason}'}
|
|
57
|
+
iplio_result = query.json()
|
|
58
|
+
|
|
59
|
+
# Check if the IP address is not reserved for special use
|
|
60
|
+
# if ipinfo.get('bogon', False):
|
|
61
|
+
if '' in iplio_result and iplio_result[''] == 'RSV':
|
|
62
|
+
return {'error': 'The IP address is reserved for special use'}
|
|
63
|
+
|
|
64
|
+
# Initiate the MISP data structures
|
|
65
|
+
misp_event = MISPEvent()
|
|
66
|
+
input_attribute = MISPAttribute()
|
|
67
|
+
input_attribute.from_dict(**attribute)
|
|
68
|
+
misp_event.add_attribute(**input_attribute)
|
|
69
|
+
|
|
70
|
+
# Parse the geolocation information related to the IP address
|
|
71
|
+
geolocation = MISPObject('geolocation')
|
|
72
|
+
for field, relation in _GEOLOCATION_OBJECT_MAPPING.items():
|
|
73
|
+
geolocation.add_attribute(relation, iplio_result[field])
|
|
74
|
+
geolocation.add_reference(input_attribute.uuid, 'locates')
|
|
75
|
+
misp_event.add_object(geolocation)
|
|
76
|
+
|
|
77
|
+
# Return the results in MISP format
|
|
78
|
+
event = json.loads(misp_event.to_json())
|
|
79
|
+
return {
|
|
80
|
+
'results': {key: event[key] for key in ('Attribute', 'Object')}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def introspection():
|
|
85
|
+
return mispattributes
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def version():
|
|
89
|
+
moduleinfo['config'] = moduleconfig
|
|
90
|
+
return moduleinfo
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
from . import check_input_attribute, standard_error_message
|
|
5
|
+
from pyipasnhistory import IPASNHistory
|
|
6
|
+
from pymisp import MISPAttribute, MISPEvent, MISPObject
|
|
7
|
+
|
|
8
|
+
misperrors = {'error': 'Error'}
|
|
9
|
+
mispattributes = {'input': ['ip-src', 'ip-dst', 'ip'], 'format': 'misp_standard'}
|
|
10
|
+
moduleinfo = {
|
|
11
|
+
'version': '0.3',
|
|
12
|
+
'author': 'Raphaël Vinot',
|
|
13
|
+
'description': 'Module to query an IP ASN history service (https://github.com/D4-project/IPASN-History).',
|
|
14
|
+
'module-type': ['expansion', 'hover'],
|
|
15
|
+
'name': 'IPASN-History Lookup',
|
|
16
|
+
'logo': '',
|
|
17
|
+
'requirements': ['pyipasnhistory: Python library to access IPASN-history instance'],
|
|
18
|
+
'features': 'This module takes an IP address attribute as input and queries the CIRCL IPASN service. The result of the query is the latest asn related to the IP address, that is returned as a MISP object.',
|
|
19
|
+
'references': ['https://github.com/D4-project/IPASN-History'],
|
|
20
|
+
'input': 'An IP address MISP attribute.',
|
|
21
|
+
'output': 'Asn object(s) objects related to the IP address used as input.',
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def parse_result(attribute, values):
|
|
26
|
+
event = MISPEvent()
|
|
27
|
+
initial_attribute = MISPAttribute()
|
|
28
|
+
initial_attribute.from_dict(**attribute)
|
|
29
|
+
event.add_attribute(**initial_attribute)
|
|
30
|
+
mapping = {'asn': ('AS', 'asn'), 'prefix': ('ip-src', 'subnet-announced')}
|
|
31
|
+
for last_seen, response in values['response'].items():
|
|
32
|
+
asn = MISPObject('asn')
|
|
33
|
+
asn.add_attribute('last-seen', **{'type': 'datetime', 'value': last_seen})
|
|
34
|
+
for feature, attribute_fields in mapping.items():
|
|
35
|
+
attribute_type, object_relation = attribute_fields
|
|
36
|
+
asn.add_attribute(object_relation, **{'type': attribute_type, 'value': response[feature]})
|
|
37
|
+
asn.add_reference(initial_attribute.uuid, 'related-to')
|
|
38
|
+
event.add_object(**asn)
|
|
39
|
+
event = json.loads(event.to_json())
|
|
40
|
+
return {key: event[key] for key in ('Attribute', 'Object')}
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def handler(q=False):
|
|
44
|
+
if q is False:
|
|
45
|
+
return False
|
|
46
|
+
request = json.loads(q)
|
|
47
|
+
if not request.get('attribute') or not check_input_attribute(request['attribute']):
|
|
48
|
+
return {'error': f'{standard_error_message}, which should contain at least a type, a value and an uuid.'}
|
|
49
|
+
if request['attribute']['type'] not in mispattributes['input']:
|
|
50
|
+
return {'error': 'Unsupported attribute type.'}
|
|
51
|
+
if request['attribute']['type'] == 'ip':
|
|
52
|
+
request['attribute']['type'] = 'ip-src'
|
|
53
|
+
|
|
54
|
+
toquery = request['attribute']['value']
|
|
55
|
+
|
|
56
|
+
ipasn = IPASNHistory()
|
|
57
|
+
values = ipasn.query(toquery)
|
|
58
|
+
|
|
59
|
+
if not values:
|
|
60
|
+
misperrors['error'] = 'Unable to find the history of this IP'
|
|
61
|
+
return misperrors
|
|
62
|
+
return {'results': parse_result(request['attribute'], values)}
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def introspection():
|
|
66
|
+
return mispattributes
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def version():
|
|
70
|
+
return moduleinfo
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import requests
|
|
3
|
+
from . import check_input_attribute, standard_error_message
|
|
4
|
+
from pymisp import MISPAttribute, MISPEvent, MISPObject
|
|
5
|
+
|
|
6
|
+
mispattributes = {
|
|
7
|
+
'input': ['ip-src', 'ip-dst'],
|
|
8
|
+
'format': 'misp_standard'
|
|
9
|
+
}
|
|
10
|
+
moduleinfo = {
|
|
11
|
+
'version': 1,
|
|
12
|
+
'author': 'Christian Studer',
|
|
13
|
+
'description': 'An expansion module to query ipinfo.io to gather more information on a given IP address.',
|
|
14
|
+
'module-type': ['expansion', 'hover'],
|
|
15
|
+
'name': 'IPInfo.io Lookup',
|
|
16
|
+
'logo': 'ipinfo.png',
|
|
17
|
+
'requirements': ['An ipinfo.io token'],
|
|
18
|
+
'features': 'The module takes an IP address attribute as input and queries the ipinfo.io API. \nThe geolocation information on the IP address is always returned.\n\nDepending on the subscription plan, the API returns different pieces of information then:\n- With a basic plan (free) you get the AS number and the AS organisation name concatenated in the `org` field.\n- With a paid subscription, the AS information is returned in the `asn` field with additional AS information, and depending on which plan the user has, you can also get information on the privacy method used to protect the IP address, the related domains, or the point of contact related to the IP address in case of an abuse.\n\nMore information on the responses content is available in the [documentation](https://ipinfo.io/developers).',
|
|
19
|
+
'references': ['https://ipinfo.io/developers'],
|
|
20
|
+
'input': 'IP address attribute.',
|
|
21
|
+
'output': 'Additional information on the IP address, like its geolocation, the autonomous system it is included in, and the related domain(s).',
|
|
22
|
+
}
|
|
23
|
+
moduleconfig = ['token']
|
|
24
|
+
|
|
25
|
+
_GEOLOCATION_OBJECT_MAPPING = {
|
|
26
|
+
'city': 'city',
|
|
27
|
+
'postal': 'zipcode',
|
|
28
|
+
'region': 'region',
|
|
29
|
+
'country': 'countrycode'
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def handler(q=False):
|
|
34
|
+
# Input checks
|
|
35
|
+
if q is False:
|
|
36
|
+
return False
|
|
37
|
+
request = json.loads(q)
|
|
38
|
+
if not request.get('attribute') or not check_input_attribute(request['attribute']):
|
|
39
|
+
return {'error': f'{standard_error_message}, which should contain at least a type, a value and an uuid.'}
|
|
40
|
+
attribute = request['attribute']
|
|
41
|
+
if attribute.get('type') not in mispattributes['input']:
|
|
42
|
+
return {'error': 'Wrong input attribute type.'}
|
|
43
|
+
if not request.get('config'):
|
|
44
|
+
return {'error': 'Missing ipinfo config.'}
|
|
45
|
+
if not request['config'].get('token'):
|
|
46
|
+
return {'error': 'Missing ipinfo token.'}
|
|
47
|
+
|
|
48
|
+
# Query ipinfo.io
|
|
49
|
+
query = requests.get(
|
|
50
|
+
f"https://ipinfo.io/{attribute['value']}/json?token={request['config']['token']}"
|
|
51
|
+
)
|
|
52
|
+
if query.status_code != 200:
|
|
53
|
+
return {'error': f'Error while querying ipinfo.io - {query.status_code}: {query.reason}'}
|
|
54
|
+
ipinfo = query.json()
|
|
55
|
+
|
|
56
|
+
# Check if the IP address is not reserved for special use
|
|
57
|
+
if ipinfo.get('bogon', False):
|
|
58
|
+
return {'error': 'The IP address is reserved for special use'}
|
|
59
|
+
|
|
60
|
+
# Initiate the MISP data structures
|
|
61
|
+
misp_event = MISPEvent()
|
|
62
|
+
input_attribute = MISPAttribute()
|
|
63
|
+
input_attribute.from_dict(**attribute)
|
|
64
|
+
misp_event.add_attribute(**input_attribute)
|
|
65
|
+
|
|
66
|
+
# Parse the geolocation information related to the IP address
|
|
67
|
+
geolocation = MISPObject('geolocation')
|
|
68
|
+
for field, relation in _GEOLOCATION_OBJECT_MAPPING.items():
|
|
69
|
+
geolocation.add_attribute(relation, ipinfo[field])
|
|
70
|
+
for relation, value in zip(('latitude', 'longitude'), ipinfo['loc'].split(',')):
|
|
71
|
+
geolocation.add_attribute(relation, value)
|
|
72
|
+
geolocation.add_reference(input_attribute.uuid, 'locates')
|
|
73
|
+
misp_event.add_object(geolocation)
|
|
74
|
+
|
|
75
|
+
# Parse the domain information
|
|
76
|
+
domain_ip = misp_event.add_object(name='domain-ip')
|
|
77
|
+
for feature in ('hostname', 'ip'):
|
|
78
|
+
domain_ip.add_attribute(feature, ipinfo[feature])
|
|
79
|
+
domain_ip.add_reference(input_attribute.uuid, 'resolves')
|
|
80
|
+
if ipinfo.get('domain') is not None:
|
|
81
|
+
for domain in ipinfo['domain']['domains']:
|
|
82
|
+
domain_ip.add_attribute('domain', domain)
|
|
83
|
+
|
|
84
|
+
# Parse the AS information
|
|
85
|
+
asn = MISPObject('asn')
|
|
86
|
+
asn.add_reference(input_attribute.uuid, 'includes')
|
|
87
|
+
if ipinfo.get('asn') is not None:
|
|
88
|
+
asn_info = ipinfo['asn']
|
|
89
|
+
asn.add_attribute('asn', asn_info['asn'])
|
|
90
|
+
asn.add_attribute('description', asn_info['name'])
|
|
91
|
+
misp_event.add_object(asn)
|
|
92
|
+
elif ipinfo.get('org'):
|
|
93
|
+
as_value, *description = ipinfo['org'].split(' ')
|
|
94
|
+
asn.add_attribute('asn', as_value)
|
|
95
|
+
asn.add_attribute('description', ' '.join(description))
|
|
96
|
+
misp_event.add_object(asn)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
# Return the results in MISP format
|
|
100
|
+
event = json.loads(misp_event.to_json())
|
|
101
|
+
return {
|
|
102
|
+
'results': {key: event[key] for key in ('Attribute', 'Object')}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def introspection():
|
|
107
|
+
return mispattributes
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def version():
|
|
111
|
+
moduleinfo['config'] = moduleconfig
|
|
112
|
+
return moduleinfo
|