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,160 @@
|
|
|
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 "import") to import a Lastline report from an analysis link.
|
|
6
|
+
"""
|
|
7
|
+
import json
|
|
8
|
+
|
|
9
|
+
import lastline_api
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
misperrors = {
|
|
13
|
+
"error": "Error",
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
userConfig = {
|
|
17
|
+
"analysis_link": {
|
|
18
|
+
"type": "String",
|
|
19
|
+
"errorMessage": "Expected analysis link",
|
|
20
|
+
"message": "The link to a Lastline analysis"
|
|
21
|
+
},
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
inputSource = []
|
|
25
|
+
|
|
26
|
+
moduleinfo = {
|
|
27
|
+
'version': '0.1',
|
|
28
|
+
'author': 'Stefano Ortolani',
|
|
29
|
+
'description': 'Deprecation notice: this module will be deprecated by December 2021, please use vmware_nsx module.\n\nModule to import and parse reports from Lastline analysis links.',
|
|
30
|
+
'module-type': ['import'],
|
|
31
|
+
'name': 'Lastline Import',
|
|
32
|
+
'logo': 'lastline.png',
|
|
33
|
+
'requirements': [],
|
|
34
|
+
'features': 'The module requires a Lastline Portal `username` and `password`.\nThe module uses the new format and it is able to return MISP attributes and objects.\nThe module returns the same results as the [lastline_query](https://github.com/MISP/misp-modules/tree/main/misp_modules/modules/expansion/lastline_query.py) expansion module.',
|
|
35
|
+
'references': ['https://www.lastline.com'],
|
|
36
|
+
'input': 'Link to a Lastline analysis.',
|
|
37
|
+
'output': 'MISP attributes and objects parsed from the analysis report.',
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
moduleconfig = [
|
|
41
|
+
"username",
|
|
42
|
+
"password",
|
|
43
|
+
"verify_ssl",
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def introspection():
|
|
48
|
+
modulesetup = {}
|
|
49
|
+
try:
|
|
50
|
+
userConfig
|
|
51
|
+
modulesetup["userConfig"] = userConfig
|
|
52
|
+
except NameError:
|
|
53
|
+
pass
|
|
54
|
+
try:
|
|
55
|
+
inputSource
|
|
56
|
+
modulesetup["inputSource"] = inputSource
|
|
57
|
+
except NameError:
|
|
58
|
+
pass
|
|
59
|
+
modulesetup["format"] = "misp_standard"
|
|
60
|
+
return modulesetup
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def version():
|
|
64
|
+
moduleinfo["config"] = moduleconfig
|
|
65
|
+
return moduleinfo
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def handler(q=False):
|
|
69
|
+
if q is False:
|
|
70
|
+
return False
|
|
71
|
+
|
|
72
|
+
request = json.loads(q)
|
|
73
|
+
|
|
74
|
+
# Parse the init parameters
|
|
75
|
+
try:
|
|
76
|
+
config = request["config"]
|
|
77
|
+
auth_data = lastline_api.LastlineAbstractClient.get_login_params_from_dict(config)
|
|
78
|
+
analysis_link = request["config"]["analysis_link"]
|
|
79
|
+
# The API url changes based on the analysis link host name
|
|
80
|
+
api_url = lastline_api.get_portal_url_from_task_link(analysis_link)
|
|
81
|
+
except Exception as e:
|
|
82
|
+
misperrors["error"] = "Error parsing configuration: {}".format(e)
|
|
83
|
+
return misperrors
|
|
84
|
+
|
|
85
|
+
# Parse the call parameters
|
|
86
|
+
try:
|
|
87
|
+
task_uuid = lastline_api.get_uuid_from_task_link(analysis_link)
|
|
88
|
+
except (KeyError, ValueError) as e:
|
|
89
|
+
misperrors["error"] = "Error processing input parameters: {}".format(e)
|
|
90
|
+
return misperrors
|
|
91
|
+
|
|
92
|
+
# Make the API calls
|
|
93
|
+
try:
|
|
94
|
+
api_client = lastline_api.PortalClient(api_url, auth_data, verify_ssl=config.get('verify_ssl', True).lower() in ("true"))
|
|
95
|
+
response = api_client.get_progress(task_uuid)
|
|
96
|
+
if response.get("completed") != 1:
|
|
97
|
+
raise ValueError("Analysis is not finished yet.")
|
|
98
|
+
|
|
99
|
+
response = api_client.get_result(task_uuid)
|
|
100
|
+
if not response:
|
|
101
|
+
raise ValueError("Analysis report is empty.")
|
|
102
|
+
|
|
103
|
+
except Exception as e:
|
|
104
|
+
misperrors["error"] = "Error issuing the API call: {}".format(e)
|
|
105
|
+
return misperrors
|
|
106
|
+
|
|
107
|
+
# Parse and return
|
|
108
|
+
result_parser = lastline_api.LastlineResultBaseParser()
|
|
109
|
+
result_parser.parse(analysis_link, response)
|
|
110
|
+
|
|
111
|
+
event = result_parser.misp_event
|
|
112
|
+
event_dictionary = json.loads(event.to_json())
|
|
113
|
+
|
|
114
|
+
return {
|
|
115
|
+
"results": {
|
|
116
|
+
key: event_dictionary[key]
|
|
117
|
+
for key in ("Attribute", "Object", "Tag")
|
|
118
|
+
if (key in event and event[key])
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
if __name__ == "__main__":
|
|
124
|
+
"""Test importing information from a Lastline analysis link."""
|
|
125
|
+
import argparse
|
|
126
|
+
import configparser
|
|
127
|
+
|
|
128
|
+
parser = argparse.ArgumentParser()
|
|
129
|
+
parser.add_argument("-c", "--config-file", dest="config_file")
|
|
130
|
+
parser.add_argument("-s", "--section-name", dest="section_name")
|
|
131
|
+
args = parser.parse_args()
|
|
132
|
+
c = configparser.ConfigParser()
|
|
133
|
+
c.read(args.config_file)
|
|
134
|
+
a = lastline_api.LastlineAbstractClient.get_login_params_from_conf(c, args.section_name)
|
|
135
|
+
|
|
136
|
+
j = json.dumps(
|
|
137
|
+
{
|
|
138
|
+
"config": {
|
|
139
|
+
**a,
|
|
140
|
+
"analysis_link": (
|
|
141
|
+
"https://user.lastline.com/portal#/analyst/task/"
|
|
142
|
+
"1fcbcb8f7fb400100772d6a7b62f501b/overview"
|
|
143
|
+
)
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
)
|
|
147
|
+
print(json.dumps(handler(j), indent=4, sort_keys=True))
|
|
148
|
+
|
|
149
|
+
j = json.dumps(
|
|
150
|
+
{
|
|
151
|
+
"config": {
|
|
152
|
+
**a,
|
|
153
|
+
"analysis_link": (
|
|
154
|
+
"https://user.lastline.com/portal#/analyst/task/"
|
|
155
|
+
"f3c0ae115d51001017ff8da768fa6049/overview"
|
|
156
|
+
)
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
)
|
|
160
|
+
print(json.dumps(handler(j), indent=4, sort_keys=True))
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import base64
|
|
3
|
+
|
|
4
|
+
misperrors = {'error': 'Error'}
|
|
5
|
+
userConfig = {}
|
|
6
|
+
|
|
7
|
+
inputSource = ['file']
|
|
8
|
+
|
|
9
|
+
moduleinfo = {
|
|
10
|
+
'version': '0.1',
|
|
11
|
+
'author': 'Richard van den Berg',
|
|
12
|
+
'description': 'Module to import MISP JSON format for merging MISP events.',
|
|
13
|
+
'module-type': ['import'],
|
|
14
|
+
'name': 'MISP JSON Import',
|
|
15
|
+
'logo': '',
|
|
16
|
+
'requirements': [],
|
|
17
|
+
'features': 'The module simply imports MISP Attributes from an other MISP Event in order to merge events together. There is thus no special feature to make it work.',
|
|
18
|
+
'references': [],
|
|
19
|
+
'input': 'MISP Event',
|
|
20
|
+
'output': 'MISP Event attributes',
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
moduleconfig = []
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def handler(q=False):
|
|
27
|
+
if q is False:
|
|
28
|
+
return False
|
|
29
|
+
r = {'results': []}
|
|
30
|
+
request = json.loads(q)
|
|
31
|
+
try:
|
|
32
|
+
mfile = base64.b64decode(request["data"]).decode('utf-8')
|
|
33
|
+
misp = json.loads(mfile)
|
|
34
|
+
event = misp['response'][0]['Event']
|
|
35
|
+
for a in event["Attribute"]:
|
|
36
|
+
tmp = {}
|
|
37
|
+
tmp["values"] = a["value"]
|
|
38
|
+
tmp["categories"] = a["category"]
|
|
39
|
+
tmp["types"] = a["type"]
|
|
40
|
+
tmp["to_ids"] = a["to_ids"]
|
|
41
|
+
tmp["comment"] = a["comment"]
|
|
42
|
+
if a.get("data"):
|
|
43
|
+
tmp["data"] = a["data"]
|
|
44
|
+
r['results'].append(tmp)
|
|
45
|
+
except Exception:
|
|
46
|
+
pass
|
|
47
|
+
return r
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def introspection():
|
|
51
|
+
modulesetup = {}
|
|
52
|
+
try:
|
|
53
|
+
userConfig
|
|
54
|
+
modulesetup['userConfig'] = userConfig
|
|
55
|
+
except NameError:
|
|
56
|
+
pass
|
|
57
|
+
try:
|
|
58
|
+
inputSource
|
|
59
|
+
modulesetup['inputSource'] = inputSource
|
|
60
|
+
except NameError:
|
|
61
|
+
pass
|
|
62
|
+
return modulesetup
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def version():
|
|
66
|
+
moduleinfo['config'] = moduleconfig
|
|
67
|
+
return moduleinfo
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
if __name__ == '__main__':
|
|
71
|
+
x = open('test.json', 'r')
|
|
72
|
+
r = handler(q=x.read())
|
|
73
|
+
print(json.dumps(r))
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import json
|
|
3
|
+
import base64
|
|
4
|
+
from io import BytesIO
|
|
5
|
+
|
|
6
|
+
import logging
|
|
7
|
+
|
|
8
|
+
log = logging.getLogger('ocr')
|
|
9
|
+
log.setLevel(logging.DEBUG)
|
|
10
|
+
ch = logging.StreamHandler(sys.stdout)
|
|
11
|
+
ch.setLevel(logging.DEBUG)
|
|
12
|
+
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
|
13
|
+
ch.setFormatter(formatter)
|
|
14
|
+
log.addHandler(ch)
|
|
15
|
+
|
|
16
|
+
misperrors = {'error': 'Error'}
|
|
17
|
+
userConfig = {}
|
|
18
|
+
|
|
19
|
+
inputSource = ['file']
|
|
20
|
+
|
|
21
|
+
moduleinfo = {
|
|
22
|
+
'version': '0.2',
|
|
23
|
+
'author': 'Alexandre Dulaunoy',
|
|
24
|
+
'description': 'Optical Character Recognition (OCR) module for MISP.',
|
|
25
|
+
'module-type': ['import'],
|
|
26
|
+
'name': 'OCR Import',
|
|
27
|
+
'logo': '',
|
|
28
|
+
'requirements': [],
|
|
29
|
+
'features': 'The module tries to recognize some text from an image and import the result as a freetext attribute, there is then no special feature asked to users to make it work.',
|
|
30
|
+
'references': [],
|
|
31
|
+
'input': 'Image',
|
|
32
|
+
'output': 'freetext MISP attribute',
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
moduleconfig = []
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def handler(q=False):
|
|
39
|
+
# try to import modules and return errors if module not found
|
|
40
|
+
try:
|
|
41
|
+
from PIL import Image
|
|
42
|
+
except ImportError:
|
|
43
|
+
misperrors['error'] = "Please pip(3) install pillow"
|
|
44
|
+
return misperrors
|
|
45
|
+
|
|
46
|
+
try:
|
|
47
|
+
# Official ImageMagick module
|
|
48
|
+
from wand.image import Image as WImage
|
|
49
|
+
except ImportError:
|
|
50
|
+
misperrors['error'] = "Please pip(3) install wand"
|
|
51
|
+
return misperrors
|
|
52
|
+
|
|
53
|
+
try:
|
|
54
|
+
from pytesseract import image_to_string
|
|
55
|
+
except ImportError:
|
|
56
|
+
misperrors['error'] = "Please pip(3) install pytesseract"
|
|
57
|
+
return misperrors
|
|
58
|
+
|
|
59
|
+
if q is False:
|
|
60
|
+
return False
|
|
61
|
+
r = {'results': []}
|
|
62
|
+
request = json.loads(q)
|
|
63
|
+
document = base64.b64decode(request["data"])
|
|
64
|
+
document = WImage(blob=document)
|
|
65
|
+
if document.format == 'PDF':
|
|
66
|
+
with document as pdf:
|
|
67
|
+
# Get number of pages
|
|
68
|
+
pages = len(pdf.sequence)
|
|
69
|
+
log.debug("PDF with {} page(s) detected".format(pages))
|
|
70
|
+
# Create new image object where the height will be the number of pages. With huge PDFs this will overflow, break, consume silly memory etc…
|
|
71
|
+
img = WImage(width=pdf.width, height=pdf.height * pages)
|
|
72
|
+
# Cycle through pages and stitch it together to one big file
|
|
73
|
+
for p in range(pages):
|
|
74
|
+
log.debug("Stitching page {}".format(p + 1))
|
|
75
|
+
image = img.composite(pdf.sequence[p], top=pdf.height * p, left=0)
|
|
76
|
+
# Create a png blob
|
|
77
|
+
image = img.make_blob('png')
|
|
78
|
+
log.debug("Final image size is {}x{}".format(pdf.width, pdf.height * (p + 1)))
|
|
79
|
+
else:
|
|
80
|
+
image = base64.b64decode(request["data"])
|
|
81
|
+
|
|
82
|
+
image_file = BytesIO(image)
|
|
83
|
+
image_file.seek(0)
|
|
84
|
+
|
|
85
|
+
try:
|
|
86
|
+
im = Image.open(image_file)
|
|
87
|
+
except IOError:
|
|
88
|
+
misperrors['error'] = "Corrupt or not an image file."
|
|
89
|
+
return misperrors
|
|
90
|
+
|
|
91
|
+
ocrized = image_to_string(im)
|
|
92
|
+
|
|
93
|
+
freetext = {}
|
|
94
|
+
freetext['values'] = ocrized
|
|
95
|
+
freetext['types'] = ['freetext']
|
|
96
|
+
r['results'].append(freetext)
|
|
97
|
+
return r
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def introspection():
|
|
101
|
+
modulesetup = {}
|
|
102
|
+
try:
|
|
103
|
+
userConfig
|
|
104
|
+
modulesetup['userConfig'] = userConfig
|
|
105
|
+
except NameError:
|
|
106
|
+
pass
|
|
107
|
+
try:
|
|
108
|
+
inputSource
|
|
109
|
+
modulesetup['inputSource'] = inputSource
|
|
110
|
+
except NameError:
|
|
111
|
+
pass
|
|
112
|
+
return modulesetup
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def version():
|
|
116
|
+
moduleinfo['config'] = moduleconfig
|
|
117
|
+
return moduleinfo
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
if __name__ == '__main__':
|
|
121
|
+
x = open('test.json', 'r')
|
|
122
|
+
handler(q=x.read())
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import base64
|
|
3
|
+
|
|
4
|
+
from pymisp.tools import openioc
|
|
5
|
+
|
|
6
|
+
misperrors = {'error': 'Error'}
|
|
7
|
+
userConfig = {'not save ioc': {'type': 'Boolean',
|
|
8
|
+
'message': 'If you check this box, IOC file will not save as an attachment in MISP'
|
|
9
|
+
},
|
|
10
|
+
'default tag': {
|
|
11
|
+
'type': 'String',
|
|
12
|
+
'message': 'Add tags spaced by a comma (tlp:white,misp:threat-level="no-risk")',
|
|
13
|
+
'validation': '0'}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
inputSource = ['file']
|
|
17
|
+
|
|
18
|
+
moduleinfo = {
|
|
19
|
+
'version': '0.1',
|
|
20
|
+
'author': 'Raphaël Vinot',
|
|
21
|
+
'description': 'Module to import OpenIOC packages.',
|
|
22
|
+
'module-type': ['import'],
|
|
23
|
+
'name': 'OpenIOC Import',
|
|
24
|
+
'logo': '',
|
|
25
|
+
'requirements': ['PyMISP'],
|
|
26
|
+
'features': 'The module imports MISP Attributes from OpenIOC packages, there is then no special feature for users to make it work.',
|
|
27
|
+
'references': ['https://www.fireeye.com/blog/threat-research/2013/10/openioc-basics.html'],
|
|
28
|
+
'input': 'OpenIOC packages',
|
|
29
|
+
'output': 'MISP Event attributes',
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
moduleconfig = []
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def handler(q=False):
|
|
36
|
+
# Just in case we have no data
|
|
37
|
+
if q is False:
|
|
38
|
+
return False
|
|
39
|
+
|
|
40
|
+
# The return value
|
|
41
|
+
r = {'results': []}
|
|
42
|
+
|
|
43
|
+
# Load up that JSON
|
|
44
|
+
q = json.loads(q)
|
|
45
|
+
|
|
46
|
+
# It's b64 encoded, so decode that stuff
|
|
47
|
+
package = base64.b64decode(q.get("data")).decode('utf-8')
|
|
48
|
+
|
|
49
|
+
# If something really weird happened
|
|
50
|
+
if not package:
|
|
51
|
+
return json.dumps({"success": 0})
|
|
52
|
+
|
|
53
|
+
pkg = openioc.load_openioc(package)
|
|
54
|
+
|
|
55
|
+
if q.get('config'):
|
|
56
|
+
if q['config'].get('not save ioc') == "0":
|
|
57
|
+
addFile = {"values": [q.get('filename')],
|
|
58
|
+
"types": ['attachment'],
|
|
59
|
+
"categories": ['Support Tool'],
|
|
60
|
+
"data": q.get('data')}
|
|
61
|
+
# add tag
|
|
62
|
+
if q['config'].get('default tag') is not None:
|
|
63
|
+
addFile["tags"] = q['config']['default tag'].split(",")
|
|
64
|
+
# add file as attachment
|
|
65
|
+
r["results"].append(addFile)
|
|
66
|
+
|
|
67
|
+
# return all attributes
|
|
68
|
+
for attrib in pkg.attributes:
|
|
69
|
+
toAppend = {
|
|
70
|
+
"values": [attrib.value],
|
|
71
|
+
"types": [attrib.type],
|
|
72
|
+
"categories": [attrib.category],
|
|
73
|
+
"comment": getattr(attrib, 'comment', '')}
|
|
74
|
+
# add tag
|
|
75
|
+
if q.get('config') and q['config'].get('default tag') is not None:
|
|
76
|
+
toAppend["tags"] = q['config']['default tag'].split(",")
|
|
77
|
+
|
|
78
|
+
r["results"].append(toAppend)
|
|
79
|
+
return r
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def introspection():
|
|
83
|
+
modulesetup = {}
|
|
84
|
+
try:
|
|
85
|
+
userConfig
|
|
86
|
+
modulesetup['userConfig'] = userConfig
|
|
87
|
+
except NameError:
|
|
88
|
+
pass
|
|
89
|
+
try:
|
|
90
|
+
inputSource
|
|
91
|
+
modulesetup['inputSource'] = inputSource
|
|
92
|
+
except NameError:
|
|
93
|
+
pass
|
|
94
|
+
return modulesetup
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def version():
|
|
98
|
+
moduleinfo['config'] = moduleconfig
|
|
99
|
+
return moduleinfo
|