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,150 @@
|
|
|
1
|
+
######################################################
|
|
2
|
+
# #
|
|
3
|
+
# Author: Stanislav Klevtsov, Ukraine; Feb 2019. #
|
|
4
|
+
# #
|
|
5
|
+
# #
|
|
6
|
+
# Script was tested on the following configuration: #
|
|
7
|
+
# MISP v2.4.90 #
|
|
8
|
+
# Cisco Firesight Manager Console v6.2.3 (bld 84) #
|
|
9
|
+
# #
|
|
10
|
+
######################################################
|
|
11
|
+
|
|
12
|
+
import json
|
|
13
|
+
import base64
|
|
14
|
+
from urllib.parse import quote
|
|
15
|
+
|
|
16
|
+
misperrors = {'error': 'Error'}
|
|
17
|
+
|
|
18
|
+
moduleinfo = {
|
|
19
|
+
'version': '1',
|
|
20
|
+
'author': 'Stanislav Klevtsov',
|
|
21
|
+
'description': 'Module to export malicious network activity attributes to Cisco fireSIGHT manager block rules.',
|
|
22
|
+
'module-type': ['export'],
|
|
23
|
+
'name': 'Cisco fireSIGHT blockrule Export',
|
|
24
|
+
'logo': 'cisco.png',
|
|
25
|
+
'requirements': ['Firesight manager console credentials'],
|
|
26
|
+
'features': 'The module goes through the attributes to find all the network activity ones in order to create block rules for the Cisco fireSIGHT manager.',
|
|
27
|
+
'references': [],
|
|
28
|
+
'input': 'Network activity attributes (IPs, URLs).',
|
|
29
|
+
'output': 'Cisco fireSIGHT manager block rules.',
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
moduleconfig = ['fmc_ip_addr', 'fmc_login', 'fmc_pass', 'domain_id', 'acpolicy_id']
|
|
34
|
+
|
|
35
|
+
fsmapping = {"ip-dst": "dst", "url": "request"}
|
|
36
|
+
|
|
37
|
+
mispattributes = {'input': list(fsmapping.keys())}
|
|
38
|
+
|
|
39
|
+
# options: event, attribute, event-collection, attribute-collection
|
|
40
|
+
inputSource = ['event']
|
|
41
|
+
|
|
42
|
+
outputFileExtension = 'sh'
|
|
43
|
+
responseType = 'application/txt'
|
|
44
|
+
|
|
45
|
+
# .sh file templates
|
|
46
|
+
SH_FILE_HEADER = """#!/bin/sh\n\n"""
|
|
47
|
+
|
|
48
|
+
BLOCK_JSON_TMPL = """
|
|
49
|
+
BLOCK_RULE='{{ "action": "BLOCK", "enabled": true, "type": "AccessRule", "name": "{rule_name}", "destinationNetworks": {{ "literals": [ {dst_networks} ] }}, "urls": {{ "literals": [ {urls} ] }}, "newComments": [ "{event_info_comment}" ] }}'\n
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
BLOCK_DST_JSON_TMPL = """{{ "type": "Host", "value": "{ipdst}" }} """
|
|
53
|
+
BLOCK_URL_JSON_TMPL = """{{ "type": "Url", "url": "{url}" }} """
|
|
54
|
+
|
|
55
|
+
CURL_ADD_RULE_TMPL = """
|
|
56
|
+
curl -X POST -v -k -H 'Content-Type: application/json' -H \"Authorization: Basic $LOGINPASS_BASE64\" -H \"X-auth-access-token: $ACC_TOKEN\" -i \"https://$FIRESIGHT_IP_ADDR/api/fmc_config/v1/domain/$DOMAIN_ID/policy/accesspolicies/$ACPOLICY_ID/accessrules\" --data \"$BLOCK_RULE\" """
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def handler(q=False):
|
|
60
|
+
if q is False:
|
|
61
|
+
return False
|
|
62
|
+
|
|
63
|
+
r = {'results': []}
|
|
64
|
+
request = json.loads(q)
|
|
65
|
+
|
|
66
|
+
if "config" in request:
|
|
67
|
+
config = request["config"]
|
|
68
|
+
|
|
69
|
+
# check if config is empty
|
|
70
|
+
if not config['fmc_ip_addr']:
|
|
71
|
+
config['fmc_ip_addr'] = "0.0.0.0"
|
|
72
|
+
if not config['fmc_login']:
|
|
73
|
+
config['fmc_login'] = "login"
|
|
74
|
+
if not config['fmc_pass']:
|
|
75
|
+
config['fmc_pass'] = "password"
|
|
76
|
+
if not config['domain_id']:
|
|
77
|
+
config['domain_id'] = "SET_FIRESIGHT_DOMAIN_ID"
|
|
78
|
+
if not config['acpolicy_id']:
|
|
79
|
+
config['acpolicy_id'] = "SET_FIRESIGHT_ACPOLICY_ID"
|
|
80
|
+
|
|
81
|
+
data = request["data"]
|
|
82
|
+
output = ""
|
|
83
|
+
ipdst = []
|
|
84
|
+
urls = []
|
|
85
|
+
|
|
86
|
+
# populate the ACL rule with attributes
|
|
87
|
+
for ev in data:
|
|
88
|
+
|
|
89
|
+
event = ev["Attribute"]
|
|
90
|
+
event_id = ev["Event"]["id"]
|
|
91
|
+
event_info = ev["Event"]["info"]
|
|
92
|
+
|
|
93
|
+
for index, attr in enumerate(event):
|
|
94
|
+
if attr["to_ids"] is True:
|
|
95
|
+
if attr["type"] in fsmapping:
|
|
96
|
+
if attr["type"] == "ip-dst":
|
|
97
|
+
ipdst.append(BLOCK_DST_JSON_TMPL.format(ipdst=attr["value"]))
|
|
98
|
+
else:
|
|
99
|
+
urls.append(BLOCK_URL_JSON_TMPL.format(url=quote(attr["value"], safe='@/:;?&=-_.,+!*')))
|
|
100
|
+
|
|
101
|
+
# building the .sh file
|
|
102
|
+
output += SH_FILE_HEADER
|
|
103
|
+
output += "FIRESIGHT_IP_ADDR='{}'\n".format(config['fmc_ip_addr'])
|
|
104
|
+
|
|
105
|
+
output += "LOGINPASS_BASE64=`echo -n '{}:{}' | base64`\n".format(config['fmc_login'], config['fmc_pass'])
|
|
106
|
+
output += "DOMAIN_ID='{}'\n".format(config['domain_id'])
|
|
107
|
+
output += "ACPOLICY_ID='{}'\n\n".format(config['acpolicy_id'])
|
|
108
|
+
|
|
109
|
+
output += "ACC_TOKEN=`curl -X POST -v -k -sD - -o /dev/null -H \"Authorization: Basic $LOGINPASS_BASE64\" -i \"https://$FIRESIGHT_IP_ADDR/api/fmc_platform/v1/auth/generatetoken\" | grep -i x-auth-acc | sed 's/.*:\\ //g' | tr -d '[:space:]' | tr -d '\\n'`\n"
|
|
110
|
+
|
|
111
|
+
output += BLOCK_JSON_TMPL.format(rule_name="misp_event_{}".format(event_id),
|
|
112
|
+
dst_networks=', '.join(ipdst),
|
|
113
|
+
urls=', '.join(urls),
|
|
114
|
+
event_info_comment=event_info) + "\n"
|
|
115
|
+
|
|
116
|
+
output += CURL_ADD_RULE_TMPL
|
|
117
|
+
# END building the .sh file
|
|
118
|
+
|
|
119
|
+
r = {"data": base64.b64encode(output.encode('utf-8')).decode('utf-8')}
|
|
120
|
+
return r
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def introspection():
|
|
124
|
+
modulesetup = {}
|
|
125
|
+
try:
|
|
126
|
+
responseType
|
|
127
|
+
modulesetup['responseType'] = responseType
|
|
128
|
+
except NameError:
|
|
129
|
+
pass
|
|
130
|
+
try:
|
|
131
|
+
userConfig
|
|
132
|
+
modulesetup['userConfig'] = userConfig
|
|
133
|
+
except NameError:
|
|
134
|
+
pass
|
|
135
|
+
try:
|
|
136
|
+
outputFileExtension
|
|
137
|
+
modulesetup['outputFileExtension'] = outputFileExtension
|
|
138
|
+
except NameError:
|
|
139
|
+
pass
|
|
140
|
+
try:
|
|
141
|
+
inputSource
|
|
142
|
+
modulesetup['inputSource'] = inputSource
|
|
143
|
+
except NameError:
|
|
144
|
+
pass
|
|
145
|
+
return modulesetup
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def version():
|
|
149
|
+
moduleinfo['config'] = moduleconfig
|
|
150
|
+
return moduleinfo
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Export module for coverting MISP events into Defender for Endpoint KQL queries.
|
|
3
|
+
Config['Period'] : allows to define period over witch to look for IOC from now
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import base64
|
|
7
|
+
import json
|
|
8
|
+
|
|
9
|
+
misperrors = {"error": "Error"}
|
|
10
|
+
|
|
11
|
+
types_to_use = ['sha256', 'sha1', 'md5', 'domain', 'ip-src', 'ip-dst', 'url']
|
|
12
|
+
|
|
13
|
+
userConfig = {
|
|
14
|
+
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
moduleconfig = ["Period"]
|
|
18
|
+
inputSource = ['event']
|
|
19
|
+
|
|
20
|
+
outputFileExtension = 'kql'
|
|
21
|
+
responseType = 'application/txt'
|
|
22
|
+
|
|
23
|
+
moduleinfo = {
|
|
24
|
+
'version': '1.1',
|
|
25
|
+
'author': 'Julien Bachmann, Hacknowledge, Maik Wuerth',
|
|
26
|
+
'description': 'Defender for Endpoint KQL hunting query export module',
|
|
27
|
+
'module-type': ['export'],
|
|
28
|
+
'name': 'Microsoft Defender for Endpoint KQL Export',
|
|
29
|
+
'logo': 'defender_endpoint.png',
|
|
30
|
+
'requirements': [],
|
|
31
|
+
'features': 'This module export an event as Defender for Endpoint KQL queries that can then be used in your own python3 or Powershell tool. If you are using Microsoft Sentinel, you can directly connect your MISP instance to Sentinel and then create queries using the `ThreatIntelligenceIndicator` table to match events against imported IOC.',
|
|
32
|
+
'references': ['https://docs.microsoft.com/en-us/windows/security/threat-protection/microsoft-defender-atp/advanced-hunting-schema-reference'],
|
|
33
|
+
'input': 'MISP Event attributes',
|
|
34
|
+
'output': 'Defender for Endpoint KQL queries',
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def handle_sha256(value, period):
|
|
39
|
+
query = f"""find in (DeviceEvents, DeviceAlertEvents,AlertInfo, AlertEvidence, DeviceFileEvents, DeviceImageLoadEvents, DeviceProcessEvents)
|
|
40
|
+
where (SHA256 == '{value}' or InitiatingProcessSHA1 == '{value}') and
|
|
41
|
+
Timestamp between(ago({period}) .. now())"""
|
|
42
|
+
return query.replace('\n', ' ')
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def handle_sha1(value, period):
|
|
46
|
+
query = f"""find in (DeviceEvents, DeviceAlertEvents, AlertInfo, AlertEvidence, DeviceFileEvents, DeviceImageLoadEvents, DeviceProcessEvents)
|
|
47
|
+
where (SHA1 == '{value}' or InitiatingProcessSHA1 == '{value}') and
|
|
48
|
+
Timestamp between(ago({period}) .. now())"""
|
|
49
|
+
return query.replace('\n', ' ')
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def handle_md5(value, period):
|
|
53
|
+
query = f"""find in (DeviceEvents, DeviceAlertEvents, AlertInfo, AlertEvidence, DeviceFileEvents, DeviceImageLoadEvents, DeviceProcessEvents)
|
|
54
|
+
where (MD5 == '{value}' or InitiatingProcessMD5 == '{value}') and
|
|
55
|
+
Timestamp between(ago({period}) .. now())"""
|
|
56
|
+
return query.replace('\n', ' ')
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def handle_domain(value, period):
|
|
60
|
+
query = f"""find in (DeviceAlertEvents, AlertInfo, AlertEvidence, DeviceNetworkEvents)
|
|
61
|
+
where RemoteUrl contains '{value}' and
|
|
62
|
+
Timestamp between(ago({period}) .. now())"""
|
|
63
|
+
return query.replace('\n', ' ')
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def handle_ip(value, period):
|
|
67
|
+
query = f"""find in (DeviceAlertEvents, AlertInfo, AlertEvidence, DeviceNetworkEvents)
|
|
68
|
+
where RemoteIP == '{value}' and
|
|
69
|
+
Timestamp between(ago({period}) .. now())"""
|
|
70
|
+
return query.replace('\n', ' ')
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def handle_url(value, period):
|
|
74
|
+
query = f"""let url = '{value}';
|
|
75
|
+
search in (EmailUrlInfo,UrlClickEvents,DeviceNetworkEvents,DeviceFileEvents,DeviceEvents,BehaviorEntities, AlertInfo, AlertEvidence, DeviceAlertEvents)
|
|
76
|
+
Timestamp between(ago({period}) .. now()) and
|
|
77
|
+
RemoteUrl has url
|
|
78
|
+
or FileOriginUrl has url
|
|
79
|
+
or FileOriginReferrerUrl has url
|
|
80
|
+
or Url has url"""
|
|
81
|
+
return query.replace('\n', ' ')
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
handlers = {
|
|
85
|
+
'sha256': handle_sha256,
|
|
86
|
+
'sha1': handle_sha1,
|
|
87
|
+
'md5': handle_md5,
|
|
88
|
+
'domain': handle_url,
|
|
89
|
+
'ip-src': handle_ip,
|
|
90
|
+
'ip-dst': handle_ip,
|
|
91
|
+
'url': handle_url
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def handler(q=False):
|
|
96
|
+
if q is False:
|
|
97
|
+
return False
|
|
98
|
+
request = json.loads(q)
|
|
99
|
+
config = request.get("config", {"Period": ""})
|
|
100
|
+
output = ''
|
|
101
|
+
|
|
102
|
+
for event in request["data"]:
|
|
103
|
+
for attribute in event["Attribute"]:
|
|
104
|
+
if attribute['type'] in types_to_use:
|
|
105
|
+
output = output + handlers[attribute['type']](attribute['value'], config['Period']) + '\n'
|
|
106
|
+
for obj in event["Object"]:
|
|
107
|
+
for attribute in obj["Attribute"]:
|
|
108
|
+
if attribute['type'] in types_to_use:
|
|
109
|
+
output = output + handlers[attribute['type']](attribute['value'], config['Period']) + '\n'
|
|
110
|
+
r = {"response": [], "data": str(base64.b64encode(bytes(output, 'utf-8')), 'utf-8')}
|
|
111
|
+
return r
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def introspection():
|
|
115
|
+
modulesetup = {}
|
|
116
|
+
try:
|
|
117
|
+
responseType
|
|
118
|
+
modulesetup['responseType'] = responseType
|
|
119
|
+
except NameError:
|
|
120
|
+
pass
|
|
121
|
+
try:
|
|
122
|
+
userConfig
|
|
123
|
+
modulesetup['userConfig'] = userConfig
|
|
124
|
+
except NameError:
|
|
125
|
+
pass
|
|
126
|
+
try:
|
|
127
|
+
outputFileExtension
|
|
128
|
+
modulesetup['outputFileExtension'] = outputFileExtension
|
|
129
|
+
except NameError:
|
|
130
|
+
pass
|
|
131
|
+
try:
|
|
132
|
+
inputSource
|
|
133
|
+
modulesetup['inputSource'] = inputSource
|
|
134
|
+
except NameError:
|
|
135
|
+
pass
|
|
136
|
+
return modulesetup
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def version():
|
|
140
|
+
moduleinfo['config'] = moduleconfig
|
|
141
|
+
return moduleinfo
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import base64
|
|
3
|
+
from pymisp import MISPEvent
|
|
4
|
+
from collections import defaultdict, Counter
|
|
5
|
+
|
|
6
|
+
misperrors = {'error': 'Error'}
|
|
7
|
+
moduleinfo = {
|
|
8
|
+
'version': '1',
|
|
9
|
+
'author': 'Christian Studer',
|
|
10
|
+
'description': 'This module is used to export MISP events containing transaction objects into GoAML format.',
|
|
11
|
+
'module-type': ['export'],
|
|
12
|
+
'name': 'GoAML Export',
|
|
13
|
+
'require_standard_format': True,
|
|
14
|
+
'logo': 'goAML.jpg',
|
|
15
|
+
'requirements': ['PyMISP', 'MISP objects'],
|
|
16
|
+
'features': "The module works as long as there is at least one transaction object in the Event.\n\nThen in order to have a valid GoAML document, please follow these guidelines:\n- For each transaction object, use either a bank-account, person, or legal-entity object to describe the origin of the transaction, and again one of them to describe the target of the transaction.\n- Create an object reference for both origin and target objects of the transaction.\n- A bank-account object needs a signatory, which is a person object, put as object reference of the bank-account.\n- A person can have an address, which is a geolocation object, put as object reference of the person.\n\nSupported relation types for object references that are recommended for each object are the folowing:\n- transaction:\n\t- 'from', 'from_my_client': Origin of the transaction - at least one of them is required.\n\t- 'to', 'to_my_client': Target of the transaction - at least one of them is required.\n\t- 'address': Location of the transaction - optional.\n- bank-account:\n\t- 'signatory': Signatory of a bank-account - the reference from bank-account to a signatory is required, but the relation-type is optional at the moment since this reference will always describe a signatory.\n\t- 'entity': Entity owning the bank account - optional.\n- person:\n\t- 'address': Address of a person - optional.",
|
|
17
|
+
'references': ['http://goaml.unodc.org/'],
|
|
18
|
+
'input': 'MISP objects (transaction, bank-account, person, legal-entity, geolocation), with references, describing financial transactions and their origin and target.',
|
|
19
|
+
'output': 'GoAML format file, describing financial transactions, with their origin and target (bank accounts, persons or entities).',
|
|
20
|
+
}
|
|
21
|
+
moduleconfig = ['rentity_id']
|
|
22
|
+
mispattributes = {'input': ['MISPEvent'], 'output': ['xml file']}
|
|
23
|
+
outputFileExtension = "xml"
|
|
24
|
+
responseType = "application/xml"
|
|
25
|
+
|
|
26
|
+
objects_to_parse = ['transaction', 'bank-account', 'person', 'entity', 'geolocation']
|
|
27
|
+
|
|
28
|
+
goAMLmapping = {'bank-account': {'bank-account': 't_account', 'institution-name': 'institution_name',
|
|
29
|
+
'institution-code': 'institution_code', 'iban': 'iban', 'swift': 'swift',
|
|
30
|
+
'branch': 'branch', 'non-banking-institution': 'non_bank_institution',
|
|
31
|
+
'account': 'account', 'currency-code': 'currency_code',
|
|
32
|
+
'account-name': 'account_name', 'client-number': 'client_number',
|
|
33
|
+
'personal-account-type': 'personal_account_type', 'opened': 'opened',
|
|
34
|
+
'closed': 'closed', 'balance': 'balance', 'status-code': 'status_code',
|
|
35
|
+
'beneficiary': 'beneficiary', 'beneficiary-comment': 'beneficiary_comment',
|
|
36
|
+
'comments': 'comments'},
|
|
37
|
+
'person': {'person': 't_person', 'text': 'comments', 'first-name': 'first_name',
|
|
38
|
+
'middle-name': 'middle_name', 'last-name': 'last_name', 'title': 'title',
|
|
39
|
+
'mothers-name': 'mothers_name', 'alias': 'alias', 'date-of-birth': 'birthdate',
|
|
40
|
+
'place-of-birth': 'birth_place', 'gender': 'gender', 'nationality': 'nationality1',
|
|
41
|
+
'passport-number': 'passport_number', 'passport-country': 'passport_country',
|
|
42
|
+
'social-security-number': 'ssn', 'identity-card-number': 'id_number'},
|
|
43
|
+
'geolocation': {'geolocation': 'location', 'city': 'city', 'region': 'state',
|
|
44
|
+
'country': 'country_code', 'address': 'address', 'zipcode': 'zip'},
|
|
45
|
+
'transaction': {'transaction': 'transaction', 'transaction-number': 'transactionnumber',
|
|
46
|
+
'date': 'date_transaction', 'location': 'transaction_location',
|
|
47
|
+
'transmode-code': 'transmode_code', 'amount': 'amount_local',
|
|
48
|
+
'transmode-comment': 'transmode_comment', 'date-posting': 'date_posting',
|
|
49
|
+
'teller': 'teller', 'authorized': 'authorized',
|
|
50
|
+
'text': 'transaction_description'},
|
|
51
|
+
'legal-entity': {'legal-entity': 'entity', 'name': 'name', 'business': 'business',
|
|
52
|
+
'commercial-name': 'commercial_name', 'phone-number': 'phone',
|
|
53
|
+
'legal-form': 'incorporation_legal_form',
|
|
54
|
+
'registration-number': 'incorporation_number'}}
|
|
55
|
+
|
|
56
|
+
referencesMapping = {'bank-account': {'aml_type': '{}_account', 'bracket': 't_{}'},
|
|
57
|
+
'person': {'transaction': {'aml_type': '{}_person', 'bracket': 't_{}'}, 'bank-account': {'aml_type': 't_person', 'bracket': 'signatory'}},
|
|
58
|
+
'legal-entity': {'transaction': {'aml_type': '{}_entity', 'bracket': 't_{}'}, 'bank-account': {'aml_type': 't_entity'}},
|
|
59
|
+
'geolocation': {'aml_type': 'address', 'bracket': 'addresses'}}
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class GoAmlGeneration(object):
|
|
63
|
+
def __init__(self, config):
|
|
64
|
+
self.config = config
|
|
65
|
+
self.parsed_uuids = defaultdict(list)
|
|
66
|
+
|
|
67
|
+
def from_event(self, event):
|
|
68
|
+
self.misp_event = MISPEvent()
|
|
69
|
+
self.misp_event.load(event)
|
|
70
|
+
|
|
71
|
+
def parse_objects(self):
|
|
72
|
+
uuids = defaultdict(list)
|
|
73
|
+
report_code = []
|
|
74
|
+
currency_code = []
|
|
75
|
+
for obj in self.misp_event.objects:
|
|
76
|
+
obj_type = obj.name
|
|
77
|
+
uuids[obj_type].append(obj.uuid)
|
|
78
|
+
if obj_type == 'bank-account':
|
|
79
|
+
try:
|
|
80
|
+
report_code.append(obj.get_attributes_by_relation('report-code')[0].value.split(' ')[0])
|
|
81
|
+
currency_code.append(obj.get_attributes_by_relation('currency-code')[0].value)
|
|
82
|
+
except IndexError:
|
|
83
|
+
print('report_code or currency_code error')
|
|
84
|
+
self.uuids, self.report_codes, self.currency_codes = uuids, report_code, currency_code
|
|
85
|
+
|
|
86
|
+
def build_xml(self):
|
|
87
|
+
self.xml = {'header': "<report><rentity_id>{}</rentity_id><submission_code>E</submission_code>".format(self.config),
|
|
88
|
+
'data': ""}
|
|
89
|
+
if "STR" in self.report_codes:
|
|
90
|
+
report_code = "STR"
|
|
91
|
+
else:
|
|
92
|
+
report_code = Counter(self.report_codes).most_common(1)[0][0]
|
|
93
|
+
self.xml['header'] += "<report_code>{}</report_code>".format(report_code)
|
|
94
|
+
submission_date = str(self.misp_event.timestamp).replace(' ', 'T')
|
|
95
|
+
self.xml['header'] += "<submission_date>{}</submission_date>".format(submission_date)
|
|
96
|
+
self.xml['header'] += "<currency_code_local>{}</currency_code_local>".format(Counter(self.currency_codes).most_common(1)[0][0])
|
|
97
|
+
for trans_uuid in self.uuids.get('transaction'):
|
|
98
|
+
self.itterate('transaction', 'transaction', trans_uuid, 'data')
|
|
99
|
+
person_to_parse = [person_uuid for person_uuid in self.uuids.get('person') if person_uuid not in self.parsed_uuids.get('person')]
|
|
100
|
+
if len(person_to_parse) == 1:
|
|
101
|
+
self.itterate('person', 'reporting_person', person_to_parse[0], 'header')
|
|
102
|
+
try:
|
|
103
|
+
location_to_parse = [location_uuid for location_uuid in self.uuids.get('geolocation') if location_uuid not in self.parsed_uuids.get('geolocation')]
|
|
104
|
+
if len(location_to_parse) == 1:
|
|
105
|
+
self.itterate('geolocation', 'location', location_to_parse[0], 'header')
|
|
106
|
+
except TypeError:
|
|
107
|
+
pass
|
|
108
|
+
self.xml['data'] += "</report>"
|
|
109
|
+
|
|
110
|
+
def itterate(self, object_type, aml_type, uuid, xml_part):
|
|
111
|
+
obj = self.misp_event.get_object_by_uuid(uuid)
|
|
112
|
+
if object_type == 'transaction':
|
|
113
|
+
self.xml[xml_part] += "<{}>".format(aml_type)
|
|
114
|
+
self.fill_xml_transaction(object_type, obj.attributes, xml_part)
|
|
115
|
+
self.parsed_uuids[object_type].append(uuid)
|
|
116
|
+
if obj.ObjectReference:
|
|
117
|
+
self.parseObjectReferences(object_type, xml_part, obj.ObjectReference)
|
|
118
|
+
self.xml[xml_part] += "</{}>".format(aml_type)
|
|
119
|
+
else:
|
|
120
|
+
if 'to_' in aml_type or 'from_' in aml_type:
|
|
121
|
+
relation_type = aml_type.split('_')[0]
|
|
122
|
+
self.xml[xml_part] += "<{0}_funds_code>{1}</{0}_funds_code>".format(relation_type, self.from_and_to_fields[relation_type]['funds'].split(' ')[0])
|
|
123
|
+
self.itterate_normal_case(object_type, obj, aml_type, uuid, xml_part)
|
|
124
|
+
self.xml[xml_part] += "<{0}_country>{1}</{0}_country>".format(relation_type, self.from_and_to_fields[relation_type]['country'])
|
|
125
|
+
else:
|
|
126
|
+
self.itterate_normal_case(object_type, obj, aml_type, uuid, xml_part)
|
|
127
|
+
|
|
128
|
+
def itterate_normal_case(self, object_type, obj, aml_type, uuid, xml_part):
|
|
129
|
+
self.xml[xml_part] += "<{}>".format(aml_type)
|
|
130
|
+
self.fill_xml(object_type, obj, xml_part)
|
|
131
|
+
self.parsed_uuids[object_type].append(uuid)
|
|
132
|
+
if obj.ObjectReference:
|
|
133
|
+
self.parseObjectReferences(object_type, xml_part, obj.ObjectReference)
|
|
134
|
+
self.xml[xml_part] += "</{}>".format(aml_type)
|
|
135
|
+
|
|
136
|
+
def parseObjectReferences(self, object_type, xml_part, references):
|
|
137
|
+
for ref in references:
|
|
138
|
+
next_uuid = ref.referenced_uuid
|
|
139
|
+
next_object_type = ref.Object.get('name')
|
|
140
|
+
relationship_type = ref.relationship_type
|
|
141
|
+
self.parse_references(object_type, next_object_type, next_uuid, relationship_type, xml_part)
|
|
142
|
+
|
|
143
|
+
def fill_xml_transaction(self, object_type, attributes, xml_part):
|
|
144
|
+
from_and_to_fields = {'from': {}, 'to': {}}
|
|
145
|
+
for attribute in attributes:
|
|
146
|
+
object_relation = attribute.object_relation
|
|
147
|
+
attribute_value = attribute.value
|
|
148
|
+
if object_relation == 'date-posting':
|
|
149
|
+
self.xml[xml_part] += "<late_deposit>True</late_deposit>"
|
|
150
|
+
elif object_relation in ('from-funds-code', 'to-funds-code'):
|
|
151
|
+
relation_type, field, _ = object_relation.split('-')
|
|
152
|
+
from_and_to_fields[relation_type][field] = attribute_value
|
|
153
|
+
continue
|
|
154
|
+
elif object_relation in ('from-country', 'to-country'):
|
|
155
|
+
relation_type, field = object_relation.split('-')
|
|
156
|
+
from_and_to_fields[relation_type][field] = attribute_value
|
|
157
|
+
continue
|
|
158
|
+
try:
|
|
159
|
+
self.xml[xml_part] += "<{0}>{1}</{0}>".format(goAMLmapping[object_type][object_relation], attribute_value)
|
|
160
|
+
except KeyError:
|
|
161
|
+
pass
|
|
162
|
+
self.from_and_to_fields = from_and_to_fields
|
|
163
|
+
|
|
164
|
+
def fill_xml(self, object_type, obj, xml_part):
|
|
165
|
+
if obj.name == 'bank-account':
|
|
166
|
+
for attribute in obj.attributes:
|
|
167
|
+
if attribute.object_relation in ('personal-account-type', 'status-code'):
|
|
168
|
+
attribute_value = attribute.value.split(' - ')[0]
|
|
169
|
+
else:
|
|
170
|
+
attribute_value = attribute.value
|
|
171
|
+
try:
|
|
172
|
+
self.xml[xml_part] += "<{0}>{1}</{0}>".format(goAMLmapping[object_type][attribute.object_relation], attribute_value)
|
|
173
|
+
except KeyError:
|
|
174
|
+
pass
|
|
175
|
+
else:
|
|
176
|
+
for attribute in obj.attributes:
|
|
177
|
+
try:
|
|
178
|
+
self.xml[xml_part] += "<{0}>{1}</{0}>".format(goAMLmapping[object_type][attribute.object_relation], attribute.value)
|
|
179
|
+
except KeyError:
|
|
180
|
+
pass
|
|
181
|
+
|
|
182
|
+
def parse_references(self, object_type, next_object_type, uuid, relationship_type, xml_part):
|
|
183
|
+
reference = referencesMapping[next_object_type]
|
|
184
|
+
try:
|
|
185
|
+
next_aml_type = reference[object_type].get('aml_type').format(relationship_type.split('_')[0])
|
|
186
|
+
try:
|
|
187
|
+
bracket = reference[object_type].get('bracket').format(relationship_type)
|
|
188
|
+
self.xml[xml_part] += "<{}>".format(bracket)
|
|
189
|
+
self.itterate(next_object_type, next_aml_type, uuid, xml_part)
|
|
190
|
+
self.xml[xml_part] += "</{}>".format(bracket)
|
|
191
|
+
except KeyError:
|
|
192
|
+
self.itterate(next_object_type, next_aml_type, uuid, xml_part)
|
|
193
|
+
except KeyError:
|
|
194
|
+
next_aml_type = reference.get('aml_type').format(relationship_type.split('_')[0])
|
|
195
|
+
bracket = reference.get('bracket').format(relationship_type)
|
|
196
|
+
self.xml[xml_part] += "<{}>".format(bracket)
|
|
197
|
+
self.itterate(next_object_type, next_aml_type, uuid, xml_part)
|
|
198
|
+
self.xml[xml_part] += "</{}>".format(bracket)
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def handler(q=False):
|
|
202
|
+
if q is False:
|
|
203
|
+
return False
|
|
204
|
+
request = json.loads(q)
|
|
205
|
+
if 'data' not in request:
|
|
206
|
+
return False
|
|
207
|
+
if not request.get('config') and not request['config'].get('rentity_id'):
|
|
208
|
+
misperrors['error'] = "Configuration error."
|
|
209
|
+
return misperrors
|
|
210
|
+
config = request['config'].get('rentity_id')
|
|
211
|
+
export_doc = GoAmlGeneration(config)
|
|
212
|
+
export_doc.from_event(request['data'][0])
|
|
213
|
+
if not export_doc.misp_event.Object:
|
|
214
|
+
misperrors['error'] = "There is no object in this event."
|
|
215
|
+
return misperrors
|
|
216
|
+
types = []
|
|
217
|
+
for obj in export_doc.misp_event.Object:
|
|
218
|
+
types.append(obj.name)
|
|
219
|
+
if 'transaction' not in types:
|
|
220
|
+
misperrors['error'] = "There is no transaction object in this event."
|
|
221
|
+
return misperrors
|
|
222
|
+
export_doc.parse_objects()
|
|
223
|
+
export_doc.build_xml()
|
|
224
|
+
exp_doc = "{}{}".format(export_doc.xml.get('header'), export_doc.xml.get('data'))
|
|
225
|
+
return {'response': [], 'data': str(base64.b64encode(bytes(exp_doc, 'utf-8')), 'utf-8')}
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
def introspection():
|
|
229
|
+
modulesetup = {}
|
|
230
|
+
try:
|
|
231
|
+
responseType
|
|
232
|
+
modulesetup['responseType'] = responseType
|
|
233
|
+
except NameError:
|
|
234
|
+
pass
|
|
235
|
+
try:
|
|
236
|
+
userConfig
|
|
237
|
+
modulesetup['userConfig'] = userConfig
|
|
238
|
+
except NameError:
|
|
239
|
+
pass
|
|
240
|
+
try:
|
|
241
|
+
outputFileExtension
|
|
242
|
+
modulesetup['outputFileExtension'] = outputFileExtension
|
|
243
|
+
except NameError:
|
|
244
|
+
pass
|
|
245
|
+
try:
|
|
246
|
+
inputSource
|
|
247
|
+
moduleSetup['inputSource'] = inputSource
|
|
248
|
+
except NameError:
|
|
249
|
+
pass
|
|
250
|
+
return modulesetup
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
def version():
|
|
254
|
+
moduleinfo['config'] = moduleconfig
|
|
255
|
+
return moduleinfo
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import base64
|
|
3
|
+
|
|
4
|
+
misperrors = {'error': 'Error'}
|
|
5
|
+
|
|
6
|
+
moduleinfo = {
|
|
7
|
+
'version': '1',
|
|
8
|
+
'author': 'TM',
|
|
9
|
+
'description': 'Lite export of a MISP event.',
|
|
10
|
+
'module-type': ['export'],
|
|
11
|
+
'name': 'Lite Export',
|
|
12
|
+
'logo': '',
|
|
13
|
+
'requirements': [],
|
|
14
|
+
'features': 'This module is simply producing a json MISP event format file, but exporting only Attributes from the Event. Thus, MISP Events exported with this module should have attributes that are not internal references, otherwise the resulting event would be empty.',
|
|
15
|
+
'references': [],
|
|
16
|
+
'input': 'MISP Event attributes',
|
|
17
|
+
'output': 'Lite MISP Event',
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
moduleconfig = ["indent_json_export"]
|
|
21
|
+
|
|
22
|
+
mispattributes = {}
|
|
23
|
+
outputFileExtension = "json"
|
|
24
|
+
responseType = "application/json"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def handler(q=False):
|
|
28
|
+
if q is False:
|
|
29
|
+
return False
|
|
30
|
+
|
|
31
|
+
request = json.loads(q)
|
|
32
|
+
|
|
33
|
+
config = {}
|
|
34
|
+
if "config" in request:
|
|
35
|
+
config = request["config"]
|
|
36
|
+
else:
|
|
37
|
+
config = {"indent_json_export": None}
|
|
38
|
+
|
|
39
|
+
if config['indent_json_export'] is not None:
|
|
40
|
+
try:
|
|
41
|
+
config['indent_json_export'] = int(config['indent_json_export'])
|
|
42
|
+
except Exception:
|
|
43
|
+
config['indent_json_export'] = None
|
|
44
|
+
|
|
45
|
+
if 'data' not in request:
|
|
46
|
+
return False
|
|
47
|
+
|
|
48
|
+
# ~ Misp json structur
|
|
49
|
+
liteEvent = {'Event': {}}
|
|
50
|
+
|
|
51
|
+
for evt in request['data']:
|
|
52
|
+
rawEvent = evt['Event']
|
|
53
|
+
liteEvent['Event']['info'] = rawEvent['info']
|
|
54
|
+
liteEvent['Event']['Attribute'] = []
|
|
55
|
+
|
|
56
|
+
attrs = evt['Attribute']
|
|
57
|
+
for attr in attrs:
|
|
58
|
+
if 'Internal reference' not in attr['category']:
|
|
59
|
+
liteAttr = {}
|
|
60
|
+
liteAttr['category'] = attr['category']
|
|
61
|
+
liteAttr['type'] = attr['type']
|
|
62
|
+
liteAttr['value'] = attr['value']
|
|
63
|
+
liteEvent['Event']['Attribute'].append(liteAttr)
|
|
64
|
+
|
|
65
|
+
return {'response': [],
|
|
66
|
+
'data': str(base64.b64encode(bytes(
|
|
67
|
+
json.dumps(liteEvent, indent=config['indent_json_export']), 'utf-8')), 'utf-8')}
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def introspection():
|
|
71
|
+
modulesetup = {}
|
|
72
|
+
try:
|
|
73
|
+
responseType
|
|
74
|
+
modulesetup['responseType'] = responseType
|
|
75
|
+
except NameError:
|
|
76
|
+
pass
|
|
77
|
+
try:
|
|
78
|
+
userConfig
|
|
79
|
+
modulesetup['userConfig'] = userConfig
|
|
80
|
+
except NameError:
|
|
81
|
+
pass
|
|
82
|
+
try:
|
|
83
|
+
outputFileExtension
|
|
84
|
+
modulesetup['outputFileExtension'] = outputFileExtension
|
|
85
|
+
except NameError:
|
|
86
|
+
pass
|
|
87
|
+
try:
|
|
88
|
+
inputSource
|
|
89
|
+
modulesetup['inputSource'] = inputSource
|
|
90
|
+
except NameError:
|
|
91
|
+
pass
|
|
92
|
+
return modulesetup
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def version():
|
|
96
|
+
moduleinfo['config'] = moduleconfig
|
|
97
|
+
return moduleinfo
|