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,229 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import json
|
|
3
|
+
|
|
4
|
+
from pymisp import MISPAttribute, MISPEvent, MISPTag, MISPObject
|
|
5
|
+
from . import check_input_attribute, checking_error, standard_error_message
|
|
6
|
+
|
|
7
|
+
from qintel_helper import search_qsentry
|
|
8
|
+
|
|
9
|
+
logger = logging.getLogger('qintel_qsentry')
|
|
10
|
+
logger.setLevel(logging.DEBUG)
|
|
11
|
+
|
|
12
|
+
moduleinfo = {
|
|
13
|
+
'version': '1.0',
|
|
14
|
+
'author': 'Qintel, LLC',
|
|
15
|
+
'description': 'A hover and expansion module which queries Qintel QSentry for ip reputation data',
|
|
16
|
+
'module-type': ['hover', 'expansion'],
|
|
17
|
+
'name': 'Qintel QSentry Lookup',
|
|
18
|
+
'logo': 'qintel.png',
|
|
19
|
+
'requirements': ['A Qintel API token'],
|
|
20
|
+
'features': 'This module takes an ip-address (ip-src or ip-dst) attribute as input, and queries the Qintel QSentry API to retrieve ip reputation data',
|
|
21
|
+
'references': ['https://www.qintel.com/products/qsentry/'],
|
|
22
|
+
'input': 'ip address attribute',
|
|
23
|
+
'output': '',
|
|
24
|
+
'ouput': 'Objects containing the enriched IP, threat tags, last seen attributes and associated Autonomous System information',
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
moduleconfig = ['token', 'remote']
|
|
28
|
+
|
|
29
|
+
misperrors = {'error': 'Error'}
|
|
30
|
+
|
|
31
|
+
mispattributes = {
|
|
32
|
+
'input': ['ip-src', 'ip-dst'],
|
|
33
|
+
'output': ['ip-src', 'ip-dst', 'AS', 'freetext'],
|
|
34
|
+
'format': 'misp_standard'
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
TAG_COLOR = {
|
|
38
|
+
'benign': '#27ae60',
|
|
39
|
+
'suspicious': '#e6a902',
|
|
40
|
+
'malicious': '#c0392b'
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
CLIENT_HEADERS = {
|
|
44
|
+
'User-Agent': f"MISP/{moduleinfo['version']}",
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _return_error(message):
|
|
49
|
+
misperrors['error'] = message
|
|
50
|
+
return misperrors
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def _make_tags(enriched_attr, result):
|
|
54
|
+
|
|
55
|
+
for tag in result['tags']:
|
|
56
|
+
color = TAG_COLOR['suspicious']
|
|
57
|
+
if tag == 'criminal':
|
|
58
|
+
color = TAG_COLOR['malicious']
|
|
59
|
+
|
|
60
|
+
t = MISPTag()
|
|
61
|
+
t.from_dict(**{
|
|
62
|
+
'name': f'qintel:tag="{tag}"',
|
|
63
|
+
'colour': color
|
|
64
|
+
})
|
|
65
|
+
enriched_attr.add_tag(**t)
|
|
66
|
+
|
|
67
|
+
return enriched_attr
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def _make_enriched_attr(event, result, orig_attr):
|
|
71
|
+
|
|
72
|
+
enriched_object = MISPObject('Qintel Threat Enrichment')
|
|
73
|
+
enriched_object.add_reference(orig_attr.uuid, 'related-to')
|
|
74
|
+
|
|
75
|
+
enriched_attr = MISPAttribute()
|
|
76
|
+
enriched_attr.from_dict(**{
|
|
77
|
+
'value': orig_attr.value,
|
|
78
|
+
'type': orig_attr.type,
|
|
79
|
+
'distribution': 0,
|
|
80
|
+
'object_relation': 'enriched-attr',
|
|
81
|
+
'to_ids': orig_attr.to_ids
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
enriched_attr = _make_tags(enriched_attr, result)
|
|
85
|
+
enriched_object.add_attribute(**enriched_attr)
|
|
86
|
+
|
|
87
|
+
comment_attr = MISPAttribute()
|
|
88
|
+
comment_attr.from_dict(**{
|
|
89
|
+
'value': '\n'.join(result.get('descriptions', [])),
|
|
90
|
+
'type': 'text',
|
|
91
|
+
'object_relation': 'descriptions',
|
|
92
|
+
'distribution': 0
|
|
93
|
+
})
|
|
94
|
+
enriched_object.add_attribute(**comment_attr)
|
|
95
|
+
|
|
96
|
+
last_seen = MISPAttribute()
|
|
97
|
+
last_seen.from_dict(**{
|
|
98
|
+
'value': result.get('last_seen'),
|
|
99
|
+
'type': 'datetime',
|
|
100
|
+
'object_relation': 'last-seen',
|
|
101
|
+
'distribution': 0
|
|
102
|
+
})
|
|
103
|
+
enriched_object.add_attribute(**last_seen)
|
|
104
|
+
|
|
105
|
+
event.add_attribute(**orig_attr)
|
|
106
|
+
event.add_object(**enriched_object)
|
|
107
|
+
|
|
108
|
+
return event
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def _make_asn_attr(event, result, orig_attr):
|
|
112
|
+
|
|
113
|
+
asn_object = MISPObject('asn')
|
|
114
|
+
asn_object.add_reference(orig_attr.uuid, 'related-to')
|
|
115
|
+
|
|
116
|
+
asn_attr = MISPAttribute()
|
|
117
|
+
asn_attr.from_dict(**{
|
|
118
|
+
'type': 'AS',
|
|
119
|
+
'value': result.get('asn'),
|
|
120
|
+
'object_relation': 'asn',
|
|
121
|
+
'distribution': 0
|
|
122
|
+
})
|
|
123
|
+
asn_object.add_attribute(**asn_attr)
|
|
124
|
+
|
|
125
|
+
org_attr = MISPAttribute()
|
|
126
|
+
org_attr.from_dict(**{
|
|
127
|
+
'type': 'text',
|
|
128
|
+
'value': result.get('asn_name', 'unknown').title(),
|
|
129
|
+
'object_relation': 'description',
|
|
130
|
+
'distribution': 0
|
|
131
|
+
})
|
|
132
|
+
asn_object.add_attribute(**org_attr)
|
|
133
|
+
|
|
134
|
+
event.add_object(**asn_object)
|
|
135
|
+
|
|
136
|
+
return event
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def _format_hover(event, result):
|
|
140
|
+
|
|
141
|
+
enriched_object = event.get_objects_by_name('Qintel Threat Enrichment')[0]
|
|
142
|
+
|
|
143
|
+
tags = ', '.join(result.get('tags'))
|
|
144
|
+
enriched_object.add_attribute('Tags', type='text', value=tags)
|
|
145
|
+
|
|
146
|
+
return event
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def _format_result(attribute, result):
|
|
150
|
+
|
|
151
|
+
event = MISPEvent()
|
|
152
|
+
|
|
153
|
+
orig_attr = MISPAttribute()
|
|
154
|
+
orig_attr.from_dict(**attribute)
|
|
155
|
+
|
|
156
|
+
event = _make_enriched_attr(event, result, orig_attr)
|
|
157
|
+
event = _make_asn_attr(event, result, orig_attr)
|
|
158
|
+
|
|
159
|
+
return event
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def _check_config(config):
|
|
163
|
+
if not config:
|
|
164
|
+
return False
|
|
165
|
+
|
|
166
|
+
if not isinstance(config, dict):
|
|
167
|
+
return False
|
|
168
|
+
|
|
169
|
+
if config.get('token', '') == '':
|
|
170
|
+
return False
|
|
171
|
+
|
|
172
|
+
return True
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
def _check_request(request):
|
|
176
|
+
if not request.get('attribute'):
|
|
177
|
+
return f'{standard_error_message}, {checking_error}'
|
|
178
|
+
|
|
179
|
+
check_reqs = ('type', 'value')
|
|
180
|
+
if not check_input_attribute(request['attribute'],
|
|
181
|
+
requirements=check_reqs):
|
|
182
|
+
return f'{standard_error_message}, {checking_error}'
|
|
183
|
+
|
|
184
|
+
if request['attribute']['type'] not in mispattributes['input']:
|
|
185
|
+
return 'Unsupported attribute type'
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def handler(q=False):
|
|
189
|
+
if not q:
|
|
190
|
+
return False
|
|
191
|
+
|
|
192
|
+
request = json.loads(q)
|
|
193
|
+
config = request.get('config')
|
|
194
|
+
|
|
195
|
+
if not _check_config(config):
|
|
196
|
+
return _return_error('Missing Qintel token')
|
|
197
|
+
|
|
198
|
+
check_request_error = _check_request(request)
|
|
199
|
+
if check_request_error:
|
|
200
|
+
return _return_error(check_request_error)
|
|
201
|
+
|
|
202
|
+
search_args = {
|
|
203
|
+
'token': config['token'],
|
|
204
|
+
'remote': config.get('remote')
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
try:
|
|
208
|
+
result = search_qsentry(request['attribute']['value'], **search_args)
|
|
209
|
+
except Exception as e:
|
|
210
|
+
return _return_error(str(e))
|
|
211
|
+
|
|
212
|
+
event = _format_result(request['attribute'], result)
|
|
213
|
+
if not request.get('event_id'):
|
|
214
|
+
event = _format_hover(event, result)
|
|
215
|
+
|
|
216
|
+
event = json.loads(event.to_json())
|
|
217
|
+
|
|
218
|
+
ret_result = {key: event[key] for key in ('Attribute', 'Object') if key
|
|
219
|
+
in event}
|
|
220
|
+
return {'results': ret_result}
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
def introspection():
|
|
224
|
+
return mispattributes
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
def version():
|
|
228
|
+
moduleinfo['config'] = moduleconfig
|
|
229
|
+
return moduleinfo
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from pyzbar import pyzbar
|
|
3
|
+
import cv2
|
|
4
|
+
import re
|
|
5
|
+
import binascii
|
|
6
|
+
import np
|
|
7
|
+
|
|
8
|
+
misperrors = {'error': 'Error'}
|
|
9
|
+
mispattributes = {'input': ['attachment'],
|
|
10
|
+
'output': ['url', 'btc']}
|
|
11
|
+
moduleinfo = {
|
|
12
|
+
'version': '0.1',
|
|
13
|
+
'author': 'Sascha Rommelfangen',
|
|
14
|
+
'description': 'Module to decode QR codes.',
|
|
15
|
+
'module-type': ['expansion', 'hover'],
|
|
16
|
+
'name': 'QR Code Decode',
|
|
17
|
+
'logo': '',
|
|
18
|
+
'requirements': ['cv2: The OpenCV python library.', 'pyzbar: Python library to read QR codes.'],
|
|
19
|
+
'features': 'The module reads the QR code and returns the related address, which can be an URL or a bitcoin address.',
|
|
20
|
+
'references': [],
|
|
21
|
+
'input': 'A QR code stored as attachment attribute.',
|
|
22
|
+
'output': 'The URL or bitcoin address the QR code is pointing to.',
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
debug = True
|
|
26
|
+
debug_prefix = "[DEBUG] QR Code module: "
|
|
27
|
+
# format example: bitcoin:1GXZ6v7FZzYBEnoRaG77SJxhu7QkvQmFuh?amount=0.15424
|
|
28
|
+
# format example: http://example.com
|
|
29
|
+
cryptocurrencies = ['bitcoin']
|
|
30
|
+
schemas = ['http://', 'https://', 'ftp://']
|
|
31
|
+
moduleconfig = []
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def handler(q=False):
|
|
35
|
+
if q is False:
|
|
36
|
+
return False
|
|
37
|
+
q = json.loads(q)
|
|
38
|
+
filename = q['attachment']
|
|
39
|
+
try:
|
|
40
|
+
img_array = np.frombuffer(binascii.a2b_base64(q['data']), np.uint8)
|
|
41
|
+
except Exception as e:
|
|
42
|
+
err = "Couldn't fetch attachment (JSON 'data' is empty). Are you using the 'Query enrichment' action?"
|
|
43
|
+
misperrors['error'] = err
|
|
44
|
+
print(err)
|
|
45
|
+
print(e)
|
|
46
|
+
return misperrors
|
|
47
|
+
image = cv2.imdecode(img_array, cv2.IMREAD_COLOR)
|
|
48
|
+
if q:
|
|
49
|
+
barcodes = pyzbar.decode(image)
|
|
50
|
+
for item in barcodes:
|
|
51
|
+
try:
|
|
52
|
+
result = item.data.decode()
|
|
53
|
+
except Exception as e:
|
|
54
|
+
print(e)
|
|
55
|
+
return
|
|
56
|
+
if debug:
|
|
57
|
+
print(debug_prefix + result)
|
|
58
|
+
for item in cryptocurrencies:
|
|
59
|
+
if item in result:
|
|
60
|
+
try:
|
|
61
|
+
currency, address, extra = re.split(r'\:|\?', result)
|
|
62
|
+
except Exception as e:
|
|
63
|
+
print(e)
|
|
64
|
+
if currency in cryptocurrencies:
|
|
65
|
+
try:
|
|
66
|
+
amount = re.split('=', extra)[1]
|
|
67
|
+
if debug:
|
|
68
|
+
print(debug_prefix + address)
|
|
69
|
+
print(debug_prefix + amount)
|
|
70
|
+
return {'results': [{'types': ['btc'], 'values': address, 'comment': "BTC: " + amount + " from file " + filename}]}
|
|
71
|
+
except Exception as e:
|
|
72
|
+
print(e)
|
|
73
|
+
else:
|
|
74
|
+
print(address)
|
|
75
|
+
for item in schemas:
|
|
76
|
+
if item in result:
|
|
77
|
+
try:
|
|
78
|
+
url = result
|
|
79
|
+
if debug:
|
|
80
|
+
print(debug_prefix + url)
|
|
81
|
+
return {'results': [{'types': ['url'], 'values': url, 'comment': "from QR code of file " + filename}]}
|
|
82
|
+
except Exception as e:
|
|
83
|
+
print(e)
|
|
84
|
+
else:
|
|
85
|
+
try:
|
|
86
|
+
return {'results': [{'types': ['text'], 'values': result, 'comment': "from QR code of file " + filename}]}
|
|
87
|
+
except Exception as e:
|
|
88
|
+
print(e)
|
|
89
|
+
misperrors['error'] = "Couldn't decode QR code in attachment."
|
|
90
|
+
return misperrors
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def introspection():
|
|
94
|
+
return mispattributes
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def version():
|
|
98
|
+
moduleinfo['config'] = moduleconfig
|
|
99
|
+
return moduleinfo
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from . import check_input_attribute, checking_error, standard_error_message
|
|
3
|
+
from ._ransomcoindb import ransomcoindb
|
|
4
|
+
from pymisp import MISPObject
|
|
5
|
+
|
|
6
|
+
copyright = """
|
|
7
|
+
Copyright 2019 (C) by Aaron Kaplan <aaron@lo-res.org>, all rights reserved.
|
|
8
|
+
This file is part of the ransomwarecoindDB project and licensed under the AGPL 3.0 license
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
debug = False
|
|
13
|
+
|
|
14
|
+
misperrors = {'error': 'Error'}
|
|
15
|
+
# mispattributes = {'input': ['sha1', 'sha256', 'md5', 'btc', 'xmr', 'dash' ], 'output': ['btc', 'sha1', 'sha256', 'md5', 'freetext']}
|
|
16
|
+
mispattributes = {'input': ['sha1', 'sha256', 'md5', 'btc'], 'output': ['btc', 'sha1', 'sha256', 'md5', 'freetext'], 'format': 'misp_standard'}
|
|
17
|
+
moduleinfo = {
|
|
18
|
+
'version': '0.1',
|
|
19
|
+
'author': 'Aaron Kaplan',
|
|
20
|
+
'description': 'Module to access the ransomcoinDB (see https://ransomcoindb.concinnity-risks.com)',
|
|
21
|
+
'module-type': ['expansion', 'hover'],
|
|
22
|
+
'name': 'RandomcoinDB Lookup',
|
|
23
|
+
'logo': '',
|
|
24
|
+
'requirements': ['A ransomcoinDB API key.'],
|
|
25
|
+
'features': 'The module takes either a hash attribute or a btc attribute as input to query the ransomcoinDB API for some additional data.\n\nIf the input is a btc address, we will get the associated hashes returned in a file MISP object. If we query ransomcoinDB with a hash, the response contains the associated btc addresses returned as single MISP btc attributes.',
|
|
26
|
+
'references': ['https://ransomcoindb.concinnity-risks.com'],
|
|
27
|
+
'input': 'A hash (md5, sha1 or sha256) or btc attribute.',
|
|
28
|
+
'output': 'Hashes associated to a btc address or btc addresses associated to a hash.',
|
|
29
|
+
'descrption': 'Module to access the ransomcoinDB with a hash or btc address attribute and get the associated btc address of hashes.',
|
|
30
|
+
}
|
|
31
|
+
moduleconfig = ['api-key']
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def handler(q=False):
|
|
35
|
+
""" the main handler function which gets a JSON dict as input and returns a results dict """
|
|
36
|
+
|
|
37
|
+
if q is False:
|
|
38
|
+
return False
|
|
39
|
+
|
|
40
|
+
q = json.loads(q)
|
|
41
|
+
if "config" not in q or "api-key" not in q["config"]:
|
|
42
|
+
return {"error": "Ransomcoindb API key is missing"}
|
|
43
|
+
if not q.get('attribute') or not check_input_attribute(q['attribute'], requirements=('type', 'value')):
|
|
44
|
+
return {'error': f'{standard_error_message}, {checking_error}.'}
|
|
45
|
+
if q['attribute']['type'] not in mispattributes['input']:
|
|
46
|
+
return {'error': 'Unsupported attribute type.'}
|
|
47
|
+
api_key = q["config"]["api-key"]
|
|
48
|
+
r = {"results": []}
|
|
49
|
+
|
|
50
|
+
""" the "q" query coming in should look something like this:
|
|
51
|
+
{'config': {'api-key': '<api key here>'},
|
|
52
|
+
'md5': 'md5 or sha1 or sha256 or btc',
|
|
53
|
+
'module': 'ransomcoindb',
|
|
54
|
+
'persistent': 1}
|
|
55
|
+
"""
|
|
56
|
+
attribute = q['attribute']
|
|
57
|
+
answer = ransomcoindb.get_data_by('BTC', attribute['type'], attribute['value'], api_key)
|
|
58
|
+
""" The results data type should be:
|
|
59
|
+
r = { 'results': [ {'types': 'md5', 'values': [ a list of all md5s or all binaries related to this btc address ] } ] }
|
|
60
|
+
"""
|
|
61
|
+
if attribute['type'] in ['md5', 'sha1', 'sha256']:
|
|
62
|
+
r['results'].append({'types': 'btc', 'values': [a['btc'] for a in answer]})
|
|
63
|
+
elif attribute['type'] == 'btc':
|
|
64
|
+
# better: create a MISP object
|
|
65
|
+
files = []
|
|
66
|
+
for a in answer:
|
|
67
|
+
obj = MISPObject('file')
|
|
68
|
+
obj.add_attribute('md5', a['md5'])
|
|
69
|
+
obj.add_attribute('sha1', a['sha1'])
|
|
70
|
+
obj.add_attribute('sha256', a['sha256'])
|
|
71
|
+
files.append(obj)
|
|
72
|
+
r['results'] = {'Object': [json.loads(f.to_json()) for f in files]}
|
|
73
|
+
return r
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def introspection():
|
|
77
|
+
return mispattributes
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def version():
|
|
81
|
+
moduleinfo['config'] = moduleconfig
|
|
82
|
+
return moduleinfo
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import sys
|
|
3
|
+
|
|
4
|
+
try:
|
|
5
|
+
import dns.resolver
|
|
6
|
+
except ImportError:
|
|
7
|
+
print("dnspython3 is missing, use 'pip install dnspython3' to install it.")
|
|
8
|
+
sys.exit(0)
|
|
9
|
+
|
|
10
|
+
misperrors = {'error': 'Error'}
|
|
11
|
+
mispattributes = {'input': ['ip-src', 'ip-dst'], 'output': ['text']}
|
|
12
|
+
moduleinfo = {
|
|
13
|
+
'version': '0.2',
|
|
14
|
+
'author': 'Christian Studer',
|
|
15
|
+
'description': 'Module to check an IPv4 address against known RBLs.',
|
|
16
|
+
'module-type': ['expansion', 'hover'],
|
|
17
|
+
'name': 'Real-time Blackhost Lists Lookup',
|
|
18
|
+
'logo': '',
|
|
19
|
+
'requirements': ['dnspython3: DNS python3 library'],
|
|
20
|
+
'features': 'This module takes an IP address attribute as input and queries multiple know Real-time Blackhost Lists to check if they have already seen this IP address.\n\nWe display then all the information we get from those different sources.',
|
|
21
|
+
'references': ['[RBLs list](https://github.com/MISP/misp-modules/blob/8817de476572a10a9c9d03258ec81ca70f3d926d/misp_modules/modules/expansion/rbl.py#L20)'],
|
|
22
|
+
'input': 'IP address attribute.',
|
|
23
|
+
'output': 'Text with additional data from Real-time Blackhost Lists about the IP address.',
|
|
24
|
+
}
|
|
25
|
+
moduleconfig = ['timeout']
|
|
26
|
+
|
|
27
|
+
rbls = (
|
|
28
|
+
"spam.spamrats.com",
|
|
29
|
+
"spamguard.leadmon.net",
|
|
30
|
+
"rbl-plus.mail-abuse.org",
|
|
31
|
+
"web.dnsbl.sorbs.net",
|
|
32
|
+
"ix.dnsbl.manitu.net",
|
|
33
|
+
"virus.rbl.jp",
|
|
34
|
+
"dul.dnsbl.sorbs.net",
|
|
35
|
+
"bogons.cymru.com",
|
|
36
|
+
"psbl.surriel.com",
|
|
37
|
+
"misc.dnsbl.sorbs.net",
|
|
38
|
+
"httpbl.abuse.ch",
|
|
39
|
+
"combined.njabl.org",
|
|
40
|
+
"smtp.dnsbl.sorbs.net",
|
|
41
|
+
"korea.services.net",
|
|
42
|
+
"drone.abuse.ch",
|
|
43
|
+
"rbl.efnetrbl.org",
|
|
44
|
+
"cbl.anti-spam.org.cn",
|
|
45
|
+
"b.barracudacentral.org",
|
|
46
|
+
"bl.spamcannibal.org",
|
|
47
|
+
"xbl.spamhaus.org",
|
|
48
|
+
"zen.spamhaus.org",
|
|
49
|
+
"rbl.suresupport.com",
|
|
50
|
+
"db.wpbl.info",
|
|
51
|
+
"sbl.spamhaus.org",
|
|
52
|
+
"http.dnsbl.sorbs.net",
|
|
53
|
+
"csi.cloudmark.com",
|
|
54
|
+
"rbl.interserver.net",
|
|
55
|
+
"ubl.unsubscore.com",
|
|
56
|
+
"dnsbl.sorbs.net",
|
|
57
|
+
"virbl.bit.nl",
|
|
58
|
+
"pbl.spamhaus.org",
|
|
59
|
+
"socks.dnsbl.sorbs.net",
|
|
60
|
+
"short.rbl.jp",
|
|
61
|
+
"dnsbl.dronebl.org",
|
|
62
|
+
"blackholes.mail-abuse.org",
|
|
63
|
+
"truncate.gbudb.net",
|
|
64
|
+
"dyna.spamrats.com",
|
|
65
|
+
"spamrbl.imp.ch",
|
|
66
|
+
"spam.dnsbl.sorbs.net",
|
|
67
|
+
"wormrbl.imp.ch",
|
|
68
|
+
"query.senderbase.org",
|
|
69
|
+
"opm.tornevall.org",
|
|
70
|
+
"netblock.pedantic.org",
|
|
71
|
+
"access.redhawk.org",
|
|
72
|
+
"cdl.anti-spam.org.cn",
|
|
73
|
+
"multi.surbl.org",
|
|
74
|
+
"noptr.spamrats.com",
|
|
75
|
+
"dnsbl.inps.de",
|
|
76
|
+
"bl.spamcop.net",
|
|
77
|
+
"cbl.abuseat.org",
|
|
78
|
+
"dsn.rfc-ignorant.org",
|
|
79
|
+
"zombie.dnsbl.sorbs.net",
|
|
80
|
+
"dnsbl.njabl.org",
|
|
81
|
+
"relays.mail-abuse.org",
|
|
82
|
+
"rbl.spamlab.com",
|
|
83
|
+
"all.bl.blocklist.de"
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def handler(q=False):
|
|
88
|
+
if q is False:
|
|
89
|
+
return False
|
|
90
|
+
request = json.loads(q)
|
|
91
|
+
if request.get('ip-src'):
|
|
92
|
+
ip = request['ip-src']
|
|
93
|
+
elif request.get('ip-dst'):
|
|
94
|
+
ip = request['ip-dst']
|
|
95
|
+
else:
|
|
96
|
+
misperrors['error'] = "Unsupported attributes type"
|
|
97
|
+
return misperrors
|
|
98
|
+
resolver = dns.resolver.Resolver()
|
|
99
|
+
try:
|
|
100
|
+
timeout = float(request['config']['timeout'])
|
|
101
|
+
except (KeyError, ValueError):
|
|
102
|
+
timeout = 0.4
|
|
103
|
+
resolver.timeout = timeout
|
|
104
|
+
resolver.lifetime = timeout
|
|
105
|
+
infos = {}
|
|
106
|
+
ipRev = '.'.join(ip.split('.')[::-1])
|
|
107
|
+
for rbl in rbls:
|
|
108
|
+
query = '{}.{}'.format(ipRev, rbl)
|
|
109
|
+
try:
|
|
110
|
+
txt = resolver.query(query, 'TXT')
|
|
111
|
+
infos[query] = [str(t) for t in txt]
|
|
112
|
+
except Exception:
|
|
113
|
+
continue
|
|
114
|
+
result = "\n".join([f"{rbl}: {' - '.join(info)}" for rbl, info in infos.items()])
|
|
115
|
+
if not result:
|
|
116
|
+
return {'error': 'No data found by querying known RBLs'}
|
|
117
|
+
return {'results': [{'types': mispattributes.get('output'), 'values': result}]}
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def introspection():
|
|
121
|
+
return mispattributes
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def version():
|
|
125
|
+
moduleinfo['config'] = moduleconfig
|
|
126
|
+
return moduleinfo
|