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,180 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Deprecation notice: this module will be deprecated by December 2021, please use vmware_nsx module.
|
|
4
|
+
|
|
5
|
+
Module (type "expansion") to submit files and URLs to Lastline for analysis.
|
|
6
|
+
"""
|
|
7
|
+
import base64
|
|
8
|
+
import io
|
|
9
|
+
import json
|
|
10
|
+
import zipfile
|
|
11
|
+
|
|
12
|
+
import lastline_api
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
misperrors = {
|
|
16
|
+
"error": "Error",
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
mispattributes = {
|
|
20
|
+
"input": [
|
|
21
|
+
"attachment",
|
|
22
|
+
"malware-sample",
|
|
23
|
+
"url",
|
|
24
|
+
],
|
|
25
|
+
"output": [
|
|
26
|
+
"link",
|
|
27
|
+
],
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
moduleinfo = {
|
|
31
|
+
'version': '0.1',
|
|
32
|
+
'author': 'Stefano Ortolani',
|
|
33
|
+
'description': 'Deprecation notice: this module will be deprecated by December 2021, please use vmware_nsx module.\n\nModule to submit a file or URL to Lastline.',
|
|
34
|
+
'module-type': ['expansion', 'hover'],
|
|
35
|
+
'name': 'Lastline Submit',
|
|
36
|
+
'logo': 'lastline.png',
|
|
37
|
+
'requirements': [],
|
|
38
|
+
'features': 'The module requires a Lastline Analysis `api_token` and `key`.\nWhen the analysis is completed, it is possible to import the generated report by feeding the analysis link to the [lastline_query](https://github.com/MISP/misp-modules/tree/main/misp_modules/modules/expansion/lastline_query.py) module.',
|
|
39
|
+
'references': ['https://www.lastline.com'],
|
|
40
|
+
'input': 'File or URL to submit to Lastline.',
|
|
41
|
+
'output': 'Link to the report generated by Lastline.',
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
moduleconfig = [
|
|
45
|
+
"url",
|
|
46
|
+
"api_token",
|
|
47
|
+
"key",
|
|
48
|
+
]
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
DEFAULT_ZIP_PASSWORD = b"infected"
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def __unzip(zipped_data, password=None):
|
|
55
|
+
data_file_object = io.BytesIO(zipped_data)
|
|
56
|
+
with zipfile.ZipFile(data_file_object) as zip_file:
|
|
57
|
+
sample_hashname = zip_file.namelist()[0]
|
|
58
|
+
data_zipped = zip_file.read(sample_hashname, password)
|
|
59
|
+
return data_zipped
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def __str_to_bool(x):
|
|
63
|
+
return x in ("True", "true", True)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def introspection():
|
|
67
|
+
return mispattributes
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def version():
|
|
71
|
+
moduleinfo["config"] = moduleconfig
|
|
72
|
+
return moduleinfo
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def handler(q=False):
|
|
76
|
+
if q is False:
|
|
77
|
+
return False
|
|
78
|
+
|
|
79
|
+
request = json.loads(q)
|
|
80
|
+
|
|
81
|
+
# Parse the init parameters
|
|
82
|
+
try:
|
|
83
|
+
config = request.get("config", {})
|
|
84
|
+
auth_data = lastline_api.LastlineAbstractClient.get_login_params_from_dict(config)
|
|
85
|
+
api_url = config.get("url", lastline_api.DEFAULT_LL_ANALYSIS_API_URL)
|
|
86
|
+
except Exception as e:
|
|
87
|
+
misperrors["error"] = "Error parsing configuration: {}".format(e)
|
|
88
|
+
return misperrors
|
|
89
|
+
|
|
90
|
+
# Parse the call parameters
|
|
91
|
+
try:
|
|
92
|
+
call_args = {}
|
|
93
|
+
if "url" in request:
|
|
94
|
+
# URLs are text strings
|
|
95
|
+
api_method = lastline_api.AnalysisClient.submit_url
|
|
96
|
+
call_args["url"] = request.get("url")
|
|
97
|
+
else:
|
|
98
|
+
data = request.get("data")
|
|
99
|
+
# Malware samples are zip-encrypted and then base64 encoded
|
|
100
|
+
if "malware-sample" in request:
|
|
101
|
+
api_method = lastline_api.AnalysisClient.submit_file
|
|
102
|
+
call_args["file_data"] = __unzip(base64.b64decode(data), DEFAULT_ZIP_PASSWORD)
|
|
103
|
+
call_args["file_name"] = request.get("malware-sample").split("|", 1)[0]
|
|
104
|
+
call_args["password"] = DEFAULT_ZIP_PASSWORD
|
|
105
|
+
# Attachments are just base64 encoded
|
|
106
|
+
elif "attachment" in request:
|
|
107
|
+
api_method = lastline_api.AnalysisClient.submit_file
|
|
108
|
+
call_args["file_data"] = base64.b64decode(data)
|
|
109
|
+
call_args["file_name"] = request.get("attachment")
|
|
110
|
+
|
|
111
|
+
else:
|
|
112
|
+
raise ValueError("Input parameters do not specify either an URL or a file")
|
|
113
|
+
|
|
114
|
+
except Exception as e:
|
|
115
|
+
misperrors["error"] = "Error processing input parameters: {}".format(e)
|
|
116
|
+
return misperrors
|
|
117
|
+
|
|
118
|
+
# Make the API call
|
|
119
|
+
try:
|
|
120
|
+
api_client = lastline_api.AnalysisClient(api_url, auth_data)
|
|
121
|
+
response = api_method(api_client, **call_args)
|
|
122
|
+
task_uuid = response.get("task_uuid")
|
|
123
|
+
if not task_uuid:
|
|
124
|
+
raise ValueError("Unable to process returned data")
|
|
125
|
+
if response.get("score") is not None:
|
|
126
|
+
tags = ["workflow:state='complete'"]
|
|
127
|
+
else:
|
|
128
|
+
tags = ["workflow:state='incomplete'"]
|
|
129
|
+
|
|
130
|
+
except Exception as e:
|
|
131
|
+
misperrors["error"] = "Error issuing the API call: {}".format(e)
|
|
132
|
+
return misperrors
|
|
133
|
+
|
|
134
|
+
# Assemble and return
|
|
135
|
+
analysis_link = lastline_api.get_task_link(task_uuid, analysis_url=api_url)
|
|
136
|
+
|
|
137
|
+
return {
|
|
138
|
+
"results": [
|
|
139
|
+
{
|
|
140
|
+
"types": "link",
|
|
141
|
+
"categories": ["External analysis"],
|
|
142
|
+
"values": analysis_link,
|
|
143
|
+
"tags": tags,
|
|
144
|
+
},
|
|
145
|
+
]
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
if __name__ == "__main__":
|
|
150
|
+
"""Test submitting a test subject to the Lastline backend."""
|
|
151
|
+
import argparse
|
|
152
|
+
import configparser
|
|
153
|
+
|
|
154
|
+
parser = argparse.ArgumentParser()
|
|
155
|
+
parser.add_argument("-c", "--config-file", dest="config_file")
|
|
156
|
+
parser.add_argument("-s", "--section-name", dest="section_name")
|
|
157
|
+
args = parser.parse_args()
|
|
158
|
+
c = configparser.ConfigParser()
|
|
159
|
+
c.read(args.config_file)
|
|
160
|
+
a = lastline_api.LastlineAbstractClient.get_login_params_from_conf(c, args.section_name)
|
|
161
|
+
|
|
162
|
+
j = json.dumps(
|
|
163
|
+
{
|
|
164
|
+
"config": a,
|
|
165
|
+
"url": "https://www.google.exe.com",
|
|
166
|
+
}
|
|
167
|
+
)
|
|
168
|
+
print(json.dumps(handler(j), indent=4, sort_keys=True))
|
|
169
|
+
|
|
170
|
+
with open("./tests/test_files/test.docx", "rb") as f:
|
|
171
|
+
data = f.read()
|
|
172
|
+
|
|
173
|
+
j = json.dumps(
|
|
174
|
+
{
|
|
175
|
+
"config": a,
|
|
176
|
+
"data": base64.b64encode(data).decode("utf-8"),
|
|
177
|
+
"attachment": "test.docx",
|
|
178
|
+
}
|
|
179
|
+
)
|
|
180
|
+
print(json.dumps(handler(j), indent=4, sort_keys=True))
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import json
|
|
2
|
+
|
|
3
|
+
from maclookup import ApiClient, exceptions
|
|
4
|
+
|
|
5
|
+
misperrors = {
|
|
6
|
+
'error': 'Error'
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
mispattributes = {
|
|
10
|
+
'input': ['mac-address'],
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
moduleinfo = {
|
|
14
|
+
'version': '1.0',
|
|
15
|
+
'author': 'CodeLine OY - macaddress.io',
|
|
16
|
+
'description': 'MISP hover module for macaddress.io',
|
|
17
|
+
'module-type': ['hover'],
|
|
18
|
+
'name': 'Macaddress.io Lookup',
|
|
19
|
+
'logo': 'macaddress_io.png',
|
|
20
|
+
'requirements': ['maclookup: macaddress.io python library', 'An access to the macaddress.io API (apikey)'],
|
|
21
|
+
'features': 'This module takes a MAC address attribute as input and queries macaddress.io for additional information.\n\nThis information contains data about:\n- MAC address details\n- Vendor details\n- Block details',
|
|
22
|
+
'references': ['https://macaddress.io/', 'https://github.com/CodeLineFi/maclookup-python'],
|
|
23
|
+
'input': 'MAC address MISP attribute.',
|
|
24
|
+
'output': 'Text containing information on the MAC address fetched from a query on macaddress.io.',
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
moduleconfig = ['api_key']
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def handler(q=False):
|
|
31
|
+
if q is False:
|
|
32
|
+
return False
|
|
33
|
+
|
|
34
|
+
request = json.loads(q)
|
|
35
|
+
|
|
36
|
+
if request.get('mac-address'):
|
|
37
|
+
mac_address = request['mac-address']
|
|
38
|
+
else:
|
|
39
|
+
return False
|
|
40
|
+
|
|
41
|
+
if request.get('config') and request['config'].get('api_key'):
|
|
42
|
+
api_key = request['config'].get('api_key')
|
|
43
|
+
else:
|
|
44
|
+
misperrors['error'] = 'Authorization required'
|
|
45
|
+
return misperrors
|
|
46
|
+
|
|
47
|
+
api_client = ApiClient(api_key)
|
|
48
|
+
|
|
49
|
+
try:
|
|
50
|
+
response = api_client.get(mac_address)
|
|
51
|
+
|
|
52
|
+
except exceptions.EmptyResponseException:
|
|
53
|
+
misperrors['error'] = 'Empty response'
|
|
54
|
+
return misperrors
|
|
55
|
+
|
|
56
|
+
except exceptions.UnparsableResponseException:
|
|
57
|
+
misperrors['error'] = 'Unparsable response'
|
|
58
|
+
return misperrors
|
|
59
|
+
|
|
60
|
+
except exceptions.ServerErrorException:
|
|
61
|
+
misperrors['error'] = 'Internal server error'
|
|
62
|
+
return misperrors
|
|
63
|
+
|
|
64
|
+
except exceptions.UnknownOutputFormatException:
|
|
65
|
+
misperrors['error'] = 'Unknown output'
|
|
66
|
+
return misperrors
|
|
67
|
+
|
|
68
|
+
except exceptions.AuthorizationRequiredException:
|
|
69
|
+
misperrors['error'] = 'Authorization required'
|
|
70
|
+
return misperrors
|
|
71
|
+
|
|
72
|
+
except exceptions.AccessDeniedException:
|
|
73
|
+
misperrors['error'] = 'Access denied'
|
|
74
|
+
return misperrors
|
|
75
|
+
|
|
76
|
+
except exceptions.InvalidMacOrOuiException:
|
|
77
|
+
misperrors['error'] = 'Invalid MAC or OUI'
|
|
78
|
+
return misperrors
|
|
79
|
+
|
|
80
|
+
except exceptions.NotEnoughCreditsException:
|
|
81
|
+
misperrors['error'] = 'Not enough credits'
|
|
82
|
+
return misperrors
|
|
83
|
+
|
|
84
|
+
except Exception:
|
|
85
|
+
misperrors['error'] = 'Unknown error'
|
|
86
|
+
return misperrors
|
|
87
|
+
|
|
88
|
+
date_created = \
|
|
89
|
+
response.block_details.date_created.strftime('%d %B %Y') if response.block_details.date_created else None
|
|
90
|
+
|
|
91
|
+
date_updated = \
|
|
92
|
+
response.block_details.date_updated.strftime('%d %B %Y') if response.block_details.date_updated else None
|
|
93
|
+
|
|
94
|
+
results = {
|
|
95
|
+
'results':
|
|
96
|
+
[{'types': ['text'], 'values':
|
|
97
|
+
{
|
|
98
|
+
# Mac address details
|
|
99
|
+
'Valid MAC address': "True" if response.mac_address_details.is_valid else "False",
|
|
100
|
+
'Transmission type': response.mac_address_details.transmission_type,
|
|
101
|
+
'Administration type': response.mac_address_details.administration_type,
|
|
102
|
+
|
|
103
|
+
# Vendor details
|
|
104
|
+
'OUI': response.vendor_details.oui,
|
|
105
|
+
'Vendor details are hidden': "True" if response.vendor_details.is_private else "False",
|
|
106
|
+
'Company name': response.vendor_details.company_name,
|
|
107
|
+
'Company\'s address': response.vendor_details.company_address,
|
|
108
|
+
'County code': response.vendor_details.country_code,
|
|
109
|
+
|
|
110
|
+
# Block details
|
|
111
|
+
'Block found': "True" if response.block_details.block_found else "False",
|
|
112
|
+
'The left border of the range': response.block_details.border_left,
|
|
113
|
+
'The right border of the range': response.block_details.border_right,
|
|
114
|
+
'The total number of MAC addresses in this range': response.block_details.block_size,
|
|
115
|
+
'Assignment block size': response.block_details.assignment_block_size,
|
|
116
|
+
'Date when the range was allocated': date_created,
|
|
117
|
+
'Date when the range was last updated': date_updated
|
|
118
|
+
}}]
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return results
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def introspection():
|
|
125
|
+
return mispattributes
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def version():
|
|
129
|
+
moduleinfo['config'] = moduleconfig
|
|
130
|
+
return moduleinfo
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import requests
|
|
2
|
+
import json
|
|
3
|
+
|
|
4
|
+
misperrors = {'error': 'Error'}
|
|
5
|
+
mispattributes = {'input': ['mac-address'], 'output': ['text']}
|
|
6
|
+
moduleinfo = {
|
|
7
|
+
'version': '0.1',
|
|
8
|
+
'author': 'Aurélien Schwab',
|
|
9
|
+
'description': 'Module to access Macvendors API.',
|
|
10
|
+
'module-type': ['hover'],
|
|
11
|
+
'name': 'Macvendors Lookup',
|
|
12
|
+
'logo': 'macvendors.png',
|
|
13
|
+
'requirements': [],
|
|
14
|
+
'features': 'The module takes a MAC address as input and queries macvendors.com for some information about it. The API returns the name of the vendor related to the address.',
|
|
15
|
+
'references': ['https://macvendors.com/', 'https://macvendors.com/api'],
|
|
16
|
+
'input': 'A MAC address.',
|
|
17
|
+
'output': 'Additional information about the MAC address.',
|
|
18
|
+
}
|
|
19
|
+
moduleconfig = ['user-agent']
|
|
20
|
+
|
|
21
|
+
macvendors_api_url = 'https://api.macvendors.com/'
|
|
22
|
+
default_user_agent = 'MISP-Module'
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def handler(q=False):
|
|
26
|
+
if q is False:
|
|
27
|
+
return False
|
|
28
|
+
request = json.loads(q)
|
|
29
|
+
for input_type in mispattributes['input']:
|
|
30
|
+
if input_type in request:
|
|
31
|
+
mac = request[input_type]
|
|
32
|
+
break
|
|
33
|
+
else:
|
|
34
|
+
misperrors['error'] = "Unsupported attributes type"
|
|
35
|
+
return misperrors
|
|
36
|
+
user_agent = request['config']['user-agent'] if request.get('config') and request['config'].get('user-agent') else default_user_agent
|
|
37
|
+
r = requests.get(macvendors_api_url + mac, headers={'user-agent': user_agent}) # Real request
|
|
38
|
+
if r.status_code == 200: # OK (record found)
|
|
39
|
+
response = r.text
|
|
40
|
+
if response:
|
|
41
|
+
return {'results': [{'types': mispattributes['output'], 'values': response}]}
|
|
42
|
+
elif r.status_code == 404: # Not found (not an error)
|
|
43
|
+
return {'results': [{'types': mispattributes['output'], 'values': 'Not found'}]}
|
|
44
|
+
else: # Real error
|
|
45
|
+
misperrors['error'] = 'MacVendors API not accessible (HTTP ' + str(r.status_code) + ')'
|
|
46
|
+
return misperrors['error']
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def introspection():
|
|
50
|
+
return mispattributes
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def version():
|
|
54
|
+
moduleinfo['config'] = moduleconfig
|
|
55
|
+
return moduleinfo
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import sys
|
|
3
|
+
import base64
|
|
4
|
+
import io
|
|
5
|
+
import zipfile
|
|
6
|
+
import requests
|
|
7
|
+
import hashlib
|
|
8
|
+
import re
|
|
9
|
+
|
|
10
|
+
misperrors = {'error': 'Error'}
|
|
11
|
+
mispattributes = {'input': ['attachment', 'malware-sample'], 'output': ['link']}
|
|
12
|
+
moduleinfo = {
|
|
13
|
+
'version': '1',
|
|
14
|
+
'author': 'Karen Yousefi',
|
|
15
|
+
'description': 'Module to push malware samples to MalShare',
|
|
16
|
+
'module-type': ['expansion'],
|
|
17
|
+
'name': 'MalShare Upload',
|
|
18
|
+
'requirements': ['requests library'],
|
|
19
|
+
'logo': '',
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
moduleconfig = ['malshare_apikey']
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def handler(q=False):
|
|
26
|
+
if q is False:
|
|
27
|
+
return False
|
|
28
|
+
request = json.loads(q)
|
|
29
|
+
|
|
30
|
+
try:
|
|
31
|
+
data = request.get("data")
|
|
32
|
+
if 'malware-sample' in request:
|
|
33
|
+
sample_filename = request.get("malware-sample").split("|", 1)[0]
|
|
34
|
+
data = base64.b64decode(data)
|
|
35
|
+
fl = io.BytesIO(data)
|
|
36
|
+
zf = zipfile.ZipFile(fl)
|
|
37
|
+
sample_hashname = zf.namelist()[0]
|
|
38
|
+
data = zf.read(sample_hashname, b"infected")
|
|
39
|
+
zf.close()
|
|
40
|
+
elif 'attachment' in request:
|
|
41
|
+
sample_filename = request.get("attachment")
|
|
42
|
+
data = base64.b64decode(data)
|
|
43
|
+
else:
|
|
44
|
+
misperrors['error'] = "No malware sample or attachment supplied"
|
|
45
|
+
return misperrors
|
|
46
|
+
except Exception:
|
|
47
|
+
misperrors['error'] = "Unable to process submitted sample data"
|
|
48
|
+
return misperrors
|
|
49
|
+
|
|
50
|
+
if request["config"].get("malshare_apikey") is None:
|
|
51
|
+
misperrors["error"] = "Missing MalShare API key"
|
|
52
|
+
return misperrors
|
|
53
|
+
|
|
54
|
+
malshare_apikey = request["config"].get("malshare_apikey")
|
|
55
|
+
|
|
56
|
+
try:
|
|
57
|
+
url = "https://malshare.com/api.php"
|
|
58
|
+
params = {'api_key': malshare_apikey, 'action': 'upload'}
|
|
59
|
+
files = {"upload": (sample_filename, data)}
|
|
60
|
+
response = requests.post(url, params=params, files=files)
|
|
61
|
+
response.raise_for_status()
|
|
62
|
+
|
|
63
|
+
response_text = response.text.strip()
|
|
64
|
+
|
|
65
|
+
# Calculate SHA256 of the file
|
|
66
|
+
sha256 = hashlib.sha256(data).hexdigest()
|
|
67
|
+
|
|
68
|
+
if response_text.startswith("Success"):
|
|
69
|
+
# If upload was successful or file already exists
|
|
70
|
+
malshare_link = (
|
|
71
|
+
f"https://malshare.com/sample.php?action=detail&hash={sha256}"
|
|
72
|
+
)
|
|
73
|
+
elif "sample already exists" in response_text:
|
|
74
|
+
# If file already exists, extract SHA256 from response
|
|
75
|
+
match = re.search(r'([a-fA-F0-9]{64})', response_text)
|
|
76
|
+
if match:
|
|
77
|
+
sha256 = match.group(1)
|
|
78
|
+
malshare_link = (
|
|
79
|
+
f"https://malshare.com/sample.php?action=detail&hash={sha256}"
|
|
80
|
+
)
|
|
81
|
+
else:
|
|
82
|
+
# If there's any other error
|
|
83
|
+
raise Exception(f"Upload failed: {response_text}")
|
|
84
|
+
|
|
85
|
+
except Exception as e:
|
|
86
|
+
misperrors['error'] = f"Unable to send sample to MalShare: {str(e)}"
|
|
87
|
+
return misperrors
|
|
88
|
+
|
|
89
|
+
r = {
|
|
90
|
+
'results': [
|
|
91
|
+
{
|
|
92
|
+
'types': 'link',
|
|
93
|
+
'values': malshare_link,
|
|
94
|
+
'comment': 'Link to MalShare analysis',
|
|
95
|
+
}
|
|
96
|
+
]
|
|
97
|
+
}
|
|
98
|
+
return r
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def introspection():
|
|
102
|
+
return mispattributes
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def version():
|
|
106
|
+
moduleinfo['config'] = moduleconfig
|
|
107
|
+
return moduleinfo
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import requests
|
|
3
|
+
from . import check_input_attribute, checking_error, standard_error_message
|
|
4
|
+
from pymisp import MISPEvent, MISPObject
|
|
5
|
+
|
|
6
|
+
mispattributes = {'input': ['md5', 'sha1', 'sha256'],
|
|
7
|
+
'format': 'misp_standard'}
|
|
8
|
+
moduleinfo = {
|
|
9
|
+
'version': '0.1',
|
|
10
|
+
'author': 'Christian Studer',
|
|
11
|
+
'description': 'Query Malware Bazaar to get additional information about the input hash.',
|
|
12
|
+
'module-type': ['expansion', 'hover'],
|
|
13
|
+
'name': 'Malware Bazaar Lookup',
|
|
14
|
+
'logo': '',
|
|
15
|
+
'requirements': [],
|
|
16
|
+
'features': "The module takes a hash attribute as input and queries MALWAREbazaar's API to fetch additional data about it. The result, if the payload is known on the databases, is at least one file object describing the file the input hash is related to.\n\nThe module is using the new format of modules able to return object since the result is one or multiple MISP object(s).",
|
|
17
|
+
'references': ['https://bazaar.abuse.ch/'],
|
|
18
|
+
'input': 'A hash attribute (md5, sha1 or sha256).',
|
|
19
|
+
'output': 'File object(s) related to the input attribute found on MALWAREbazaar databases.',
|
|
20
|
+
}
|
|
21
|
+
moduleconfig = []
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def parse_response(response):
|
|
25
|
+
mapping = {'file_name': {'type': 'filename', 'object_relation': 'filename'},
|
|
26
|
+
'file_size': {'type': 'size-in-bytes', 'object_relation': 'size-in-bytes'},
|
|
27
|
+
'file_type_mime': {'type': 'mime-type', 'object_relation': 'mimetype'},
|
|
28
|
+
'md5_hash': {'type': 'md5', 'object_relation': 'md5'},
|
|
29
|
+
'sha1_hash': {'type': 'sha1', 'object_relation': 'sha1'},
|
|
30
|
+
'sha256_hash': {'type': 'sha256', 'object_relation': 'sha256'},
|
|
31
|
+
'ssdeep': {'type': 'ssdeep', 'object_relation': 'ssdeep'}}
|
|
32
|
+
misp_event = MISPEvent()
|
|
33
|
+
for data in response:
|
|
34
|
+
misp_object = MISPObject('file')
|
|
35
|
+
for feature, attribute in mapping.items():
|
|
36
|
+
if feature in data:
|
|
37
|
+
misp_attribute = {'value': data[feature]}
|
|
38
|
+
misp_attribute.update(attribute)
|
|
39
|
+
misp_object.add_attribute(**misp_attribute)
|
|
40
|
+
misp_event.add_object(**misp_object)
|
|
41
|
+
return {'results': {'Object': [json.loads(misp_object.to_json()) for misp_object in misp_event.objects]}}
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def handler(q=False):
|
|
45
|
+
if q is False:
|
|
46
|
+
return False
|
|
47
|
+
request = json.loads(q)
|
|
48
|
+
if not request.get('attribute') or not check_input_attribute(request['attribute'], requirements=('type', 'value')):
|
|
49
|
+
return {'error': f'{standard_error_message}, {checking_error} that is the hash to submit to Malware Bazaar.'}
|
|
50
|
+
attribute = request['attribute']
|
|
51
|
+
if attribute['type'] not in mispattributes['input']:
|
|
52
|
+
return {'error': 'Unsupported attribute type.'}
|
|
53
|
+
url = 'https://mb-api.abuse.ch/api/v1/'
|
|
54
|
+
response = requests.post(url, data={'query': 'get_info', 'hash': attribute['value']}).json()
|
|
55
|
+
query_status = response['query_status']
|
|
56
|
+
if query_status == 'ok':
|
|
57
|
+
return parse_response(response['data'])
|
|
58
|
+
return {'error': 'Hash not found on MALWAREbazzar' if query_status == 'hash_not_found' else f'Problem encountered during the query: {query_status}'}
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def introspection():
|
|
62
|
+
return mispattributes
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def version():
|
|
66
|
+
moduleinfo['config'] = moduleconfig
|
|
67
|
+
return moduleinfo
|