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,383 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Import content from a TAXII 2.1 server.
|
|
3
|
+
"""
|
|
4
|
+
import collections
|
|
5
|
+
import itertools
|
|
6
|
+
import json
|
|
7
|
+
import misp_modules.lib.stix2misp
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
import re
|
|
10
|
+
import stix2.v20
|
|
11
|
+
import taxii2client
|
|
12
|
+
import taxii2client.exceptions
|
|
13
|
+
import requests
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class ConfigError(Exception):
|
|
17
|
+
"""
|
|
18
|
+
Represents an error in the config settings for one invocation of this
|
|
19
|
+
module.
|
|
20
|
+
"""
|
|
21
|
+
pass
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
misperrors = {'error': 'Error'}
|
|
25
|
+
|
|
26
|
+
moduleinfo = {
|
|
27
|
+
'version': '0.1',
|
|
28
|
+
'author': 'Abc',
|
|
29
|
+
'description': 'Import content from a TAXII 2.1 server',
|
|
30
|
+
'module-type': ['import'],
|
|
31
|
+
'name': 'TAXII 2.1 Import',
|
|
32
|
+
'logo': '',
|
|
33
|
+
'requirements': [],
|
|
34
|
+
'features': '',
|
|
35
|
+
'references': [],
|
|
36
|
+
'input': '',
|
|
37
|
+
'output': '',
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
mispattributes = {
|
|
41
|
+
'inputSource': [],
|
|
42
|
+
'output': ['MISP objects'],
|
|
43
|
+
'format': 'misp_standard',
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
userConfig = {
|
|
48
|
+
"url": {
|
|
49
|
+
"type": "String",
|
|
50
|
+
"message": "A TAXII 2.1 collection URL",
|
|
51
|
+
},
|
|
52
|
+
"added_after": {
|
|
53
|
+
"type": "String",
|
|
54
|
+
"message": "Lower bound on time the object was uploaded to the TAXII server"
|
|
55
|
+
},
|
|
56
|
+
"stix_id": {
|
|
57
|
+
"type": "String",
|
|
58
|
+
"message": "STIX ID(s) of objects"
|
|
59
|
+
},
|
|
60
|
+
"spec_version": { # TAXII 2.1 specific
|
|
61
|
+
"type": "String",
|
|
62
|
+
"message": "STIX version(s) of objects"
|
|
63
|
+
},
|
|
64
|
+
"type": {
|
|
65
|
+
"type": "String",
|
|
66
|
+
"message": "STIX type(s) of objects"
|
|
67
|
+
},
|
|
68
|
+
"version": {
|
|
69
|
+
"type": "String",
|
|
70
|
+
"message": 'Version timestamp(s), or "first"/"last"/"all"'
|
|
71
|
+
},
|
|
72
|
+
# Should we give some user control over this? It will not be allowed to
|
|
73
|
+
# exceed the admin setting.
|
|
74
|
+
"STIX object limit": {
|
|
75
|
+
"type": "Integer",
|
|
76
|
+
"message": "Maximum number of STIX objects to process"
|
|
77
|
+
},
|
|
78
|
+
"username": {
|
|
79
|
+
"type": "String",
|
|
80
|
+
"message": "Username for TAXII server authentication, if necessary"
|
|
81
|
+
},
|
|
82
|
+
"password": {
|
|
83
|
+
"type": "String",
|
|
84
|
+
"message": "Password for TAXII server authentication, if necessary"
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
# Paging will be handled transparently by this module, so user-defined
|
|
89
|
+
# paging-related filtering parameters will not be supported.
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
# This module will not process more than this number of STIX objects in total
|
|
93
|
+
# from a TAXII server in one module invocation (across all pages), to limit
|
|
94
|
+
# resource consumption.
|
|
95
|
+
moduleconfig = [
|
|
96
|
+
"stix_object_limit"
|
|
97
|
+
]
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
# In case there is neither an admin nor user setting given.
|
|
101
|
+
_DEFAULT_STIX_OBJECT_LIMIT = 1000
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
# Page size to use when paging TAXII results. Trades off the amount of
|
|
105
|
+
# hammering on TAXII servers and overhead of repeated requests, with the
|
|
106
|
+
# resource consumption of a single page. (Should be an admin setting too?)
|
|
107
|
+
_PAGE_SIZE = 100
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
_synonymsToTagNames_path = Path(__file__).parent / "../../lib/synonymsToTagNames.json"
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
# Collects module config information necessary to perform the TAXII query.
|
|
114
|
+
Config = collections.namedtuple("Config", [
|
|
115
|
+
"url",
|
|
116
|
+
"added_after",
|
|
117
|
+
"id",
|
|
118
|
+
"spec_version",
|
|
119
|
+
"type",
|
|
120
|
+
"version",
|
|
121
|
+
"stix_object_limit",
|
|
122
|
+
"username",
|
|
123
|
+
"password"
|
|
124
|
+
])
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def _pymisp_to_json_serializable(obj):
|
|
128
|
+
"""
|
|
129
|
+
Work around a possible bug with PyMISP's
|
|
130
|
+
AbstractMisp.to_dict(json_format=True) method, which doesn't always produce
|
|
131
|
+
a JSON-serializable value (i.e. a value which is serializable with the
|
|
132
|
+
default JSON encoder).
|
|
133
|
+
|
|
134
|
+
:param obj: A PyMISP object
|
|
135
|
+
:return: A JSON-serializable version of the object
|
|
136
|
+
"""
|
|
137
|
+
|
|
138
|
+
# The workaround creates a JSON string and then parses it back to a
|
|
139
|
+
# JSON-serializable value.
|
|
140
|
+
json_ = obj.to_json()
|
|
141
|
+
json_serializable = json.loads(json_)
|
|
142
|
+
|
|
143
|
+
return json_serializable
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def _normalize_multi_values(value):
|
|
147
|
+
"""
|
|
148
|
+
Some TAXII filters may contain multiple values separated by commas,
|
|
149
|
+
without spaces around the commas. Maybe give MISP users a little more
|
|
150
|
+
flexibility? This function normalizes a possible multi-valued value
|
|
151
|
+
(e.g. multiple values delimited by commas or spaces, all in the same
|
|
152
|
+
string) to TAXII-required format.
|
|
153
|
+
|
|
154
|
+
:param value: A MISP config value
|
|
155
|
+
:return: A normalized value
|
|
156
|
+
"""
|
|
157
|
+
|
|
158
|
+
if "," in value:
|
|
159
|
+
value = re.sub(r"\s*,\s*", ",", value)
|
|
160
|
+
else:
|
|
161
|
+
# Assume space delimiting; replace spaces with commas.
|
|
162
|
+
# I don't think we need to worry about spaces embedded in values.
|
|
163
|
+
value = re.sub(r"\s+", ",", value)
|
|
164
|
+
|
|
165
|
+
value = value.strip(",")
|
|
166
|
+
|
|
167
|
+
return value
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def _get_config(config):
|
|
171
|
+
"""
|
|
172
|
+
Combine user, admin, and default config settings to produce a config
|
|
173
|
+
object with all settings together.
|
|
174
|
+
|
|
175
|
+
:param config: The misp-modules request's "config" value.
|
|
176
|
+
:return: A Config object
|
|
177
|
+
:raises ConfigError: if any config errors are detected
|
|
178
|
+
"""
|
|
179
|
+
|
|
180
|
+
# Strip whitespace from all config settings... except for password?
|
|
181
|
+
for key, val in config.items():
|
|
182
|
+
if isinstance(val, str) and key != "password":
|
|
183
|
+
config[key] = val.strip()
|
|
184
|
+
|
|
185
|
+
url = config.get("url")
|
|
186
|
+
added_after = config.get("added_after")
|
|
187
|
+
id_ = config.get("stix_id")
|
|
188
|
+
spec_version = config.get("spec_version")
|
|
189
|
+
type_ = config.get("type")
|
|
190
|
+
version_ = config.get("version")
|
|
191
|
+
username = config.get("username")
|
|
192
|
+
password = config.get("password")
|
|
193
|
+
admin_stix_object_limit = config.get("stix_object_limit")
|
|
194
|
+
user_stix_object_limit = config.get("STIX object limit")
|
|
195
|
+
|
|
196
|
+
if admin_stix_object_limit:
|
|
197
|
+
admin_stix_object_limit = int(admin_stix_object_limit)
|
|
198
|
+
else:
|
|
199
|
+
admin_stix_object_limit = _DEFAULT_STIX_OBJECT_LIMIT
|
|
200
|
+
|
|
201
|
+
if user_stix_object_limit:
|
|
202
|
+
user_stix_object_limit = int(user_stix_object_limit)
|
|
203
|
+
stix_object_limit = min(user_stix_object_limit, admin_stix_object_limit)
|
|
204
|
+
else:
|
|
205
|
+
stix_object_limit = admin_stix_object_limit
|
|
206
|
+
|
|
207
|
+
# How much of this should we sanity-check here before passing it off to the
|
|
208
|
+
# TAXII client (and thence, to the TAXII server)?
|
|
209
|
+
|
|
210
|
+
if not url:
|
|
211
|
+
raise ConfigError("A TAXII 2.1 collection URL is required.")
|
|
212
|
+
|
|
213
|
+
if admin_stix_object_limit < 1:
|
|
214
|
+
raise ConfigError(
|
|
215
|
+
"Invalid admin object limit: must be positive: "
|
|
216
|
+
+ str(admin_stix_object_limit)
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
if stix_object_limit < 1:
|
|
220
|
+
raise ConfigError(
|
|
221
|
+
"Invalid object limit: must be positive: "
|
|
222
|
+
+ str(stix_object_limit)
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
if id_:
|
|
226
|
+
id_ = _normalize_multi_values(id_)
|
|
227
|
+
if spec_version:
|
|
228
|
+
spec_version = _normalize_multi_values(spec_version)
|
|
229
|
+
if type_:
|
|
230
|
+
type_ = _normalize_multi_values(type_)
|
|
231
|
+
if version_:
|
|
232
|
+
version_ = _normalize_multi_values(version_)
|
|
233
|
+
|
|
234
|
+
# STIX->MISP converter currently only supports STIX 2.0, so let's force
|
|
235
|
+
# spec_version="2.0".
|
|
236
|
+
if not spec_version:
|
|
237
|
+
spec_version = "2.0"
|
|
238
|
+
elif spec_version != "2.0":
|
|
239
|
+
raise ConfigError('Only spec_version="2.0" is supported for now.')
|
|
240
|
+
|
|
241
|
+
if (username and not password) or (not username and password):
|
|
242
|
+
raise ConfigError(
|
|
243
|
+
'Both or neither of "username" and "password" are required.'
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
config_obj = Config(
|
|
247
|
+
url, added_after, id_, spec_version, type_, version_, stix_object_limit,
|
|
248
|
+
username, password
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
return config_obj
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
def _query_taxii(config):
|
|
255
|
+
"""
|
|
256
|
+
Query the TAXII server according to the given config, convert the STIX
|
|
257
|
+
results to MISP, and return a standard misp-modules response.
|
|
258
|
+
|
|
259
|
+
:param config: Module config information as a Config object
|
|
260
|
+
:return: A dict containing a misp-modules response
|
|
261
|
+
"""
|
|
262
|
+
|
|
263
|
+
collection = taxii2client.Collection(
|
|
264
|
+
config.url, user=config.username, password=config.password
|
|
265
|
+
)
|
|
266
|
+
|
|
267
|
+
# No point in asking for more than our overall limit.
|
|
268
|
+
page_size = min(_PAGE_SIZE, config.stix_object_limit)
|
|
269
|
+
|
|
270
|
+
kwargs = {
|
|
271
|
+
"per_request": page_size
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
if config.spec_version:
|
|
275
|
+
kwargs["spec_version"] = config.spec_version
|
|
276
|
+
if config.version:
|
|
277
|
+
kwargs["version"] = config.version
|
|
278
|
+
if config.id:
|
|
279
|
+
kwargs["id"] = config.id
|
|
280
|
+
if config.type:
|
|
281
|
+
kwargs["type"] = config.type
|
|
282
|
+
if config.added_after:
|
|
283
|
+
kwargs["added_after"] = config.added_after
|
|
284
|
+
|
|
285
|
+
pages = taxii2client.as_pages(
|
|
286
|
+
collection.get_objects,
|
|
287
|
+
**kwargs
|
|
288
|
+
)
|
|
289
|
+
|
|
290
|
+
# Chain all the objects from all pages together...
|
|
291
|
+
all_stix_objects = itertools.chain.from_iterable(
|
|
292
|
+
taxii_envelope.get("objects", [])
|
|
293
|
+
for taxii_envelope in pages
|
|
294
|
+
)
|
|
295
|
+
|
|
296
|
+
# And only take the first N objects from that.
|
|
297
|
+
limited_stix_objects = itertools.islice(
|
|
298
|
+
all_stix_objects, 0, config.stix_object_limit
|
|
299
|
+
)
|
|
300
|
+
|
|
301
|
+
# Collect into a list. This is... unfortunate, but I don't think the
|
|
302
|
+
# converter will work incrementally (will it?). It expects all objects to
|
|
303
|
+
# be given at once.
|
|
304
|
+
#
|
|
305
|
+
# It may also be desirable to have all objects available at once so that
|
|
306
|
+
# cross-references can be made where possible, but it results in increased
|
|
307
|
+
# memory usage.
|
|
308
|
+
stix_objects = list(limited_stix_objects)
|
|
309
|
+
|
|
310
|
+
# The STIX 2.0 converter wants a 2.0 bundle. (Hope the TAXII server isn't
|
|
311
|
+
# returning 2.1 objects!)
|
|
312
|
+
bundle20 = stix2.v20.Bundle(stix_objects, allow_custom=True)
|
|
313
|
+
|
|
314
|
+
converter = misp_modules.lib.stix2misp.ExternalStixParser()
|
|
315
|
+
converter.handler(
|
|
316
|
+
bundle20, None, [0, "event", str(_synonymsToTagNames_path)]
|
|
317
|
+
)
|
|
318
|
+
|
|
319
|
+
attributes = [
|
|
320
|
+
_pymisp_to_json_serializable(attr)
|
|
321
|
+
for attr in converter.misp_event.attributes
|
|
322
|
+
]
|
|
323
|
+
|
|
324
|
+
objects = [
|
|
325
|
+
_pymisp_to_json_serializable(obj)
|
|
326
|
+
for obj in converter.misp_event.objects
|
|
327
|
+
]
|
|
328
|
+
|
|
329
|
+
tags = [
|
|
330
|
+
_pymisp_to_json_serializable(tag)
|
|
331
|
+
for tag in converter.misp_event.tags
|
|
332
|
+
]
|
|
333
|
+
|
|
334
|
+
result = {
|
|
335
|
+
"results": {
|
|
336
|
+
"Attribute": attributes,
|
|
337
|
+
"Object": objects,
|
|
338
|
+
"Tag": tags
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
return result
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
def handler(q=False):
|
|
346
|
+
if q is False:
|
|
347
|
+
return False
|
|
348
|
+
request = json.loads(q)
|
|
349
|
+
|
|
350
|
+
result = None
|
|
351
|
+
config = None
|
|
352
|
+
|
|
353
|
+
try:
|
|
354
|
+
config = _get_config(request["config"])
|
|
355
|
+
except ConfigError as e:
|
|
356
|
+
result = misperrors
|
|
357
|
+
result["error"] = e.args[0]
|
|
358
|
+
|
|
359
|
+
if not result:
|
|
360
|
+
try:
|
|
361
|
+
result = _query_taxii(config)
|
|
362
|
+
except taxii2client.exceptions.TAXIIServiceException as e:
|
|
363
|
+
result = misperrors
|
|
364
|
+
result["error"] = str(e)
|
|
365
|
+
except requests.HTTPError as e:
|
|
366
|
+
# Let's give a better error message for auth issues.
|
|
367
|
+
if e.response.status_code in (401, 403):
|
|
368
|
+
result = misperrors
|
|
369
|
+
result["error"] = "Access was denied."
|
|
370
|
+
else:
|
|
371
|
+
raise
|
|
372
|
+
|
|
373
|
+
return result
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
def introspection():
|
|
377
|
+
mispattributes["userConfig"] = userConfig
|
|
378
|
+
return mispattributes
|
|
379
|
+
|
|
380
|
+
|
|
381
|
+
def version():
|
|
382
|
+
moduleinfo['config'] = moduleconfig
|
|
383
|
+
return moduleinfo
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import base64
|
|
3
|
+
|
|
4
|
+
misperrors = {'error': 'Error'}
|
|
5
|
+
userConfig = {
|
|
6
|
+
'number1': {
|
|
7
|
+
'type': 'Integer',
|
|
8
|
+
'regex': '/^[0-4]$/i',
|
|
9
|
+
'errorMessage': 'Expected a number in range [0-4]',
|
|
10
|
+
'message': 'Column number used for value'
|
|
11
|
+
},
|
|
12
|
+
'some_string': {
|
|
13
|
+
'type': 'String',
|
|
14
|
+
'message': 'A text field'
|
|
15
|
+
},
|
|
16
|
+
'boolean_field': {
|
|
17
|
+
'type': 'Boolean',
|
|
18
|
+
'message': 'Boolean field test'
|
|
19
|
+
},
|
|
20
|
+
'comment': {
|
|
21
|
+
'type': 'Integer',
|
|
22
|
+
'message': 'Column number used for comment'
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
inputSource = ['file', 'paste']
|
|
27
|
+
|
|
28
|
+
moduleinfo = {
|
|
29
|
+
'version': '0.2',
|
|
30
|
+
'author': 'Andras Iklody',
|
|
31
|
+
'description': 'Simple CSV import tool with mapable columns',
|
|
32
|
+
'module-type': ['import'],
|
|
33
|
+
'name': 'CSV Test Import',
|
|
34
|
+
'logo': '',
|
|
35
|
+
'requirements': [],
|
|
36
|
+
'features': '',
|
|
37
|
+
'references': [],
|
|
38
|
+
'input': '',
|
|
39
|
+
'output': '',
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
moduleconfig = []
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def handler(q=False):
|
|
46
|
+
if q is False:
|
|
47
|
+
return False
|
|
48
|
+
r = {'results': []}
|
|
49
|
+
request = json.loads(q)
|
|
50
|
+
request["data"] = base64.b64decode(request["data"])
|
|
51
|
+
# fields = ["value", "category", "type", "comment"]
|
|
52
|
+
r = {"results": [{"values": ["192.168.56.1"], "types":["ip-src"], "categories": ["Network activity"]}]}
|
|
53
|
+
return r
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def introspection():
|
|
57
|
+
modulesetup = {}
|
|
58
|
+
try:
|
|
59
|
+
userConfig
|
|
60
|
+
modulesetup['userConfig'] = userConfig
|
|
61
|
+
except NameError:
|
|
62
|
+
pass
|
|
63
|
+
try:
|
|
64
|
+
inputSource
|
|
65
|
+
modulesetup['inputSource'] = inputSource
|
|
66
|
+
except NameError:
|
|
67
|
+
pass
|
|
68
|
+
return modulesetup
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def version():
|
|
72
|
+
moduleinfo['config'] = moduleconfig
|
|
73
|
+
return moduleinfo
|