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.
Files changed (194) hide show
  1. misp_modules/__init__.py +379 -0
  2. misp_modules/helpers/__init__.py +1 -0
  3. misp_modules/helpers/cache.py +84 -0
  4. misp_modules/lib/__init__.py +4 -0
  5. misp_modules/lib/_vmray/__init__.py +0 -0
  6. misp_modules/lib/_vmray/parser.py +1417 -0
  7. misp_modules/lib/_vmray/rest_api.py +148 -0
  8. misp_modules/lib/cof2misp/LICENSE-2.0.txt +202 -0
  9. misp_modules/lib/cof2misp/__init__.py +0 -0
  10. misp_modules/lib/cof2misp/cof.py +165 -0
  11. misp_modules/lib/joe_mapping.py +114 -0
  12. misp_modules/lib/joe_parser.py +573 -0
  13. misp_modules/lib/lastline_api.py +841 -0
  14. misp_modules/lib/qintel_helper.py +263 -0
  15. misp_modules/lib/stix2misp.py +2080 -0
  16. misp_modules/lib/stix2misp_mapping.py +460 -0
  17. misp_modules/lib/synonymsToTagNames.json +1 -0
  18. misp_modules/lib/vt_graph_parser/__init__.py +8 -0
  19. misp_modules/lib/vt_graph_parser/errors.py +20 -0
  20. misp_modules/lib/vt_graph_parser/helpers/__init__.py +7 -0
  21. misp_modules/lib/vt_graph_parser/helpers/parsers.py +88 -0
  22. misp_modules/lib/vt_graph_parser/helpers/rules.py +304 -0
  23. misp_modules/lib/vt_graph_parser/helpers/wrappers.py +58 -0
  24. misp_modules/lib/vt_graph_parser/importers/__init__.py +7 -0
  25. misp_modules/lib/vt_graph_parser/importers/base.py +98 -0
  26. misp_modules/lib/vt_graph_parser/importers/pymisp_response.py +73 -0
  27. misp_modules/modules/__init__.py +4 -0
  28. misp_modules/modules/action_mod/__init__.py +1 -0
  29. misp_modules/modules/action_mod/_utils/__init__.py +1 -0
  30. misp_modules/modules/action_mod/_utils/utils.py +70 -0
  31. misp_modules/modules/action_mod/mattermost.py +113 -0
  32. misp_modules/modules/action_mod/slack.py +96 -0
  33. misp_modules/modules/action_mod/testaction.py +68 -0
  34. misp_modules/modules/expansion/__init__.py +36 -0
  35. misp_modules/modules/expansion/_dnsdb_query/COPYRIGHT +27 -0
  36. misp_modules/modules/expansion/_dnsdb_query/LICENSE +202 -0
  37. misp_modules/modules/expansion/_dnsdb_query/README.md +162 -0
  38. misp_modules/modules/expansion/_dnsdb_query/__init__.py +0 -0
  39. misp_modules/modules/expansion/_dnsdb_query/dnsdb_query.py +327 -0
  40. misp_modules/modules/expansion/_ransomcoindb/__init__.py +0 -0
  41. misp_modules/modules/expansion/_ransomcoindb/ransomcoindb.py +96 -0
  42. misp_modules/modules/expansion/_vulnerability_parser/__init__.py +0 -0
  43. misp_modules/modules/expansion/_vulnerability_parser/vulnerability_parser.py +118 -0
  44. misp_modules/modules/expansion/abuseipdb.py +146 -0
  45. misp_modules/modules/expansion/apiosintds.py +365 -0
  46. misp_modules/modules/expansion/apivoid.py +133 -0
  47. misp_modules/modules/expansion/assemblyline_query.py +179 -0
  48. misp_modules/modules/expansion/assemblyline_submit.py +100 -0
  49. misp_modules/modules/expansion/backscatter_io.py +84 -0
  50. misp_modules/modules/expansion/btc_scam_check.py +54 -0
  51. misp_modules/modules/expansion/btc_steroids.py +238 -0
  52. misp_modules/modules/expansion/censys_enrich.py +287 -0
  53. misp_modules/modules/expansion/circl_passivedns.py +85 -0
  54. misp_modules/modules/expansion/circl_passivessl.py +113 -0
  55. misp_modules/modules/expansion/clamav.py +129 -0
  56. misp_modules/modules/expansion/cluster25_expand.py +239 -0
  57. misp_modules/modules/expansion/countrycode.py +69 -0
  58. misp_modules/modules/expansion/cpe.py +140 -0
  59. misp_modules/modules/expansion/crowdsec.py +235 -0
  60. misp_modules/modules/expansion/crowdstrike_falcon.py +148 -0
  61. misp_modules/modules/expansion/cuckoo_submit.py +161 -0
  62. misp_modules/modules/expansion/cve.py +57 -0
  63. misp_modules/modules/expansion/cve_advanced.py +185 -0
  64. misp_modules/modules/expansion/cytomic_orion.py +196 -0
  65. misp_modules/modules/expansion/dbl_spamhaus.py +78 -0
  66. misp_modules/modules/expansion/dns.py +71 -0
  67. misp_modules/modules/expansion/docx_enrich.py +71 -0
  68. misp_modules/modules/expansion/domaintools.py +290 -0
  69. misp_modules/modules/expansion/eql.py +91 -0
  70. misp_modules/modules/expansion/eupi.py +86 -0
  71. misp_modules/modules/expansion/extract_url_components.py +83 -0
  72. misp_modules/modules/expansion/farsight_passivedns.py +243 -0
  73. misp_modules/modules/expansion/geoip_asn.py +75 -0
  74. misp_modules/modules/expansion/geoip_city.py +75 -0
  75. misp_modules/modules/expansion/geoip_country.py +73 -0
  76. misp_modules/modules/expansion/google_safe_browsing.py +86 -0
  77. misp_modules/modules/expansion/google_search.py +57 -0
  78. misp_modules/modules/expansion/google_threat_intelligence.py +453 -0
  79. misp_modules/modules/expansion/greynoise.py +346 -0
  80. misp_modules/modules/expansion/hashdd.py +53 -0
  81. misp_modules/modules/expansion/hashlookup.py +118 -0
  82. misp_modules/modules/expansion/hibp.py +62 -0
  83. misp_modules/modules/expansion/html_to_markdown.py +63 -0
  84. misp_modules/modules/expansion/hyasinsight.py +881 -0
  85. misp_modules/modules/expansion/intel471.py +73 -0
  86. misp_modules/modules/expansion/intelmq_eventdb.py.experimental +67 -0
  87. misp_modules/modules/expansion/ip2locationio.py +90 -0
  88. misp_modules/modules/expansion/ipasn.py +70 -0
  89. misp_modules/modules/expansion/ipinfo.py +112 -0
  90. misp_modules/modules/expansion/ipqs_fraud_and_risk_scoring.py +633 -0
  91. misp_modules/modules/expansion/iprep.py +98 -0
  92. misp_modules/modules/expansion/jinja_template_rendering.py +54 -0
  93. misp_modules/modules/expansion/joesandbox_query.py +91 -0
  94. misp_modules/modules/expansion/joesandbox_submit.py +147 -0
  95. misp_modules/modules/expansion/lastline_query.py +148 -0
  96. misp_modules/modules/expansion/lastline_submit.py +180 -0
  97. misp_modules/modules/expansion/macaddress_io.py +130 -0
  98. misp_modules/modules/expansion/macvendors.py +55 -0
  99. misp_modules/modules/expansion/malshare_upload.py +107 -0
  100. misp_modules/modules/expansion/malwarebazaar.py +67 -0
  101. misp_modules/modules/expansion/mcafee_insights_enrich.py +249 -0
  102. misp_modules/modules/expansion/mmdb_lookup.py +138 -0
  103. misp_modules/modules/expansion/module.py.skeleton +44 -0
  104. misp_modules/modules/expansion/mwdb.py +152 -0
  105. misp_modules/modules/expansion/ocr_enrich.py +74 -0
  106. misp_modules/modules/expansion/ods_enrich.py +71 -0
  107. misp_modules/modules/expansion/odt_enrich.py +61 -0
  108. misp_modules/modules/expansion/onyphe.py +243 -0
  109. misp_modules/modules/expansion/onyphe_full.py +387 -0
  110. misp_modules/modules/expansion/otx.py +167 -0
  111. misp_modules/modules/expansion/passive_ssh.py +150 -0
  112. misp_modules/modules/expansion/passivetotal.py +358 -0
  113. misp_modules/modules/expansion/pdf_enrich.py +58 -0
  114. misp_modules/modules/expansion/pptx_enrich.py +65 -0
  115. misp_modules/modules/expansion/qintel_qsentry.py +229 -0
  116. misp_modules/modules/expansion/qrcode.py +99 -0
  117. misp_modules/modules/expansion/ransomcoindb.py +82 -0
  118. misp_modules/modules/expansion/rbl.py +126 -0
  119. misp_modules/modules/expansion/recordedfuture.py +544 -0
  120. misp_modules/modules/expansion/reversedns.py +77 -0
  121. misp_modules/modules/expansion/securitytrails.py +571 -0
  122. misp_modules/modules/expansion/shodan.py +244 -0
  123. misp_modules/modules/expansion/sigma_queries.py +61 -0
  124. misp_modules/modules/expansion/sigma_syntax_validator.py +49 -0
  125. misp_modules/modules/expansion/sigmf_expand.py +303 -0
  126. misp_modules/modules/expansion/socialscan.py +108 -0
  127. misp_modules/modules/expansion/sophoslabs_intelix.py +146 -0
  128. misp_modules/modules/expansion/sourcecache.py +57 -0
  129. misp_modules/modules/expansion/stairwell.py +156 -0
  130. misp_modules/modules/expansion/stix2_pattern_syntax_validator.py +56 -0
  131. misp_modules/modules/expansion/threatcrowd.py +170 -0
  132. misp_modules/modules/expansion/threatfox.py +75 -0
  133. misp_modules/modules/expansion/threatminer.py +152 -0
  134. misp_modules/modules/expansion/triage_submit.py +119 -0
  135. misp_modules/modules/expansion/trustar_enrich.py +235 -0
  136. misp_modules/modules/expansion/urlhaus.py +164 -0
  137. misp_modules/modules/expansion/urlscan.py +269 -0
  138. misp_modules/modules/expansion/variotdbs.py +133 -0
  139. misp_modules/modules/expansion/virustotal.py +311 -0
  140. misp_modules/modules/expansion/virustotal_public.py +272 -0
  141. misp_modules/modules/expansion/virustotal_upload.py +91 -0
  142. misp_modules/modules/expansion/vmray_submit.py +161 -0
  143. misp_modules/modules/expansion/vmware_nsx.py +628 -0
  144. misp_modules/modules/expansion/vulndb.py +292 -0
  145. misp_modules/modules/expansion/vulnerability_lookup.py +324 -0
  146. misp_modules/modules/expansion/vulners.py +81 -0
  147. misp_modules/modules/expansion/vysion.py +221 -0
  148. misp_modules/modules/expansion/whois.py +72 -0
  149. misp_modules/modules/expansion/whoisfreaks.py +232 -0
  150. misp_modules/modules/expansion/wiki.py +58 -0
  151. misp_modules/modules/expansion/xforceexchange.py +189 -0
  152. misp_modules/modules/expansion/xlsx_enrich.py +63 -0
  153. misp_modules/modules/expansion/yara_query.py +70 -0
  154. misp_modules/modules/expansion/yara_syntax_validator.py +49 -0
  155. misp_modules/modules/expansion/yeti.py +196 -0
  156. misp_modules/modules/export_mod/__init__.py +3 -0
  157. misp_modules/modules/export_mod/cef_export.py +93 -0
  158. misp_modules/modules/export_mod/cisco_firesight_manager_ACL_rule_export.py +150 -0
  159. misp_modules/modules/export_mod/defender_endpoint_export.py +141 -0
  160. misp_modules/modules/export_mod/goamlexport.py +255 -0
  161. misp_modules/modules/export_mod/liteexport.py +97 -0
  162. misp_modules/modules/export_mod/mass_eql_export.py +106 -0
  163. misp_modules/modules/export_mod/nexthinkexport.py +131 -0
  164. misp_modules/modules/export_mod/osqueryexport.py +125 -0
  165. misp_modules/modules/export_mod/pdfexport.py +107 -0
  166. misp_modules/modules/export_mod/testexport.py +73 -0
  167. misp_modules/modules/export_mod/threatStream_misp_export.py +114 -0
  168. misp_modules/modules/export_mod/threat_connect_export.py +125 -0
  169. misp_modules/modules/export_mod/virustotal_collections.py +141 -0
  170. misp_modules/modules/export_mod/vt_graph.py +120 -0
  171. misp_modules/modules/export_mod/yara_export.py +290 -0
  172. misp_modules/modules/import_mod/__init__.py +22 -0
  173. misp_modules/modules/import_mod/cof2misp.py +264 -0
  174. misp_modules/modules/import_mod/csvimport.py +319 -0
  175. misp_modules/modules/import_mod/cuckooimport.py +749 -0
  176. misp_modules/modules/import_mod/email_import.py +294 -0
  177. misp_modules/modules/import_mod/goamlimport.py +188 -0
  178. misp_modules/modules/import_mod/import_blueprint.py +93 -0
  179. misp_modules/modules/import_mod/joe_import.py +74 -0
  180. misp_modules/modules/import_mod/lastline_import.py +160 -0
  181. misp_modules/modules/import_mod/mispjson.py +73 -0
  182. misp_modules/modules/import_mod/ocr.py +122 -0
  183. misp_modules/modules/import_mod/openiocimport.py +99 -0
  184. misp_modules/modules/import_mod/taxii21.py +383 -0
  185. misp_modules/modules/import_mod/testimport.py +73 -0
  186. misp_modules/modules/import_mod/threatanalyzer_import.py +552 -0
  187. misp_modules/modules/import_mod/url_import.py +97 -0
  188. misp_modules/modules/import_mod/vmray_import.py +96 -0
  189. misp_modules/modules/import_mod/vmray_summary_json_import.py +87 -0
  190. misp_modules-2.4.196.dist-info/LICENSE +661 -0
  191. misp_modules-2.4.196.dist-info/METADATA +281 -0
  192. misp_modules-2.4.196.dist-info/RECORD +194 -0
  193. misp_modules-2.4.196.dist-info/WHEEL +4 -0
  194. misp_modules-2.4.196.dist-info/entry_points.txt +3 -0
@@ -0,0 +1,98 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ import json
4
+ import requests
5
+
6
+
7
+ misperrors = {'error': 'Error'}
8
+ mispattributes = {'input': ['ip-src', 'ip-dst'], 'output': ['text']}
9
+ moduleinfo = {
10
+ 'version': '1.0',
11
+ 'author': 'Keith Faber',
12
+ 'description': 'Module to query IPRep data for IP addresses.',
13
+ 'module-type': ['expansion'],
14
+ 'name': 'IPRep Lookup',
15
+ 'logo': '',
16
+ 'requirements': ['An access to the packetmail API (apikey)'],
17
+ 'features': 'This module takes an IP address attribute as input and queries the database from packetmail.net to get some information about the reputation of the IP.',
18
+ 'references': ['https://github.com/mahesh557/packetmail'],
19
+ 'input': 'An IP address MISP attribute.',
20
+ 'output': 'Text describing additional information about the input after a query on the IPRep API.',
21
+ }
22
+
23
+ moduleconfig = ['apikey']
24
+
25
+
26
+ def handler(q=False):
27
+ if q is False:
28
+ return False
29
+ request = json.loads(q)
30
+ if request.get('ip-src'):
31
+ toquery = request['ip-src']
32
+ elif request.get('ip-dst'):
33
+ toquery = request['ip-dst']
34
+ else:
35
+ misperrors['error'] = "Unsupported attributes type"
36
+ return misperrors
37
+
38
+ if not request.get('config') and not request['config'].get('apikey'):
39
+ misperrors['error'] = 'IPRep api key is missing'
40
+ return misperrors
41
+
42
+ err, rep = parse_iprep(toquery, request['config'].get('apikey'))
43
+ if len(err) > 0:
44
+ misperrors['error'] = ','.join(err)
45
+ return misperrors
46
+ return {'results': rep}
47
+
48
+
49
+ def parse_iprep(ip, api):
50
+ meta_fields = ['origin', 'Query_Time', 'created_on', 'IP_Lookup_History', 'IPs_in_collection', '_id', 'disclaimer',
51
+ 'MaxMind_Free_GeoIP', 'Unique_Lookups', 'query_result']
52
+ rep = []
53
+ err = []
54
+ full_text = ''
55
+ url = 'https://www.packetmail.net/iprep.php/%s' % ip
56
+ try:
57
+ data = requests.get(url, params={'apikey': api}).json()
58
+ except Exception:
59
+ return ['Error pulling data'], rep
60
+ # print '%s' % data
61
+ for name, val in data.items():
62
+ if name not in meta_fields:
63
+ try:
64
+ context = val['context']
65
+ if type(context) is list:
66
+ if context[0].get('alert'):
67
+ context = ','.join([hit['alert']['signature'] for hit in context])
68
+ elif context[0].get('signature'):
69
+ context = ','.join([hit['signature'] for hit in context])
70
+ elif context[0].get('target_port') and context[0].get('protocol'):
71
+ context = ','.join(
72
+ ['Port Attacked: %s %s' % (hit['target_port'], hit['protocol']) for hit in context])
73
+ elif context[0].get('phishing_kit') and context[0].get('url'):
74
+ context = ','.join(['%s (%s)' % (hit['phishing_kit'], hit['url']) for hit in context])
75
+ else:
76
+ context = ';'.join(['%s: %s' % (k, v) for k, v in context[0].items()])
77
+
78
+ if val.get('special_note'):
79
+ context += '; ' + val['special_note']
80
+
81
+ misp_val = context
82
+ full_text += '\n%s' % context
83
+ misp_comment = 'IPRep Source %s: %s' % (name, val['last_seen'])
84
+ rep.append({'types': mispattributes['output'], 'categories': ['External analysis'], 'values': misp_val, 'comment': misp_comment})
85
+ except Exception:
86
+ err.append('Error parsing source: %s' % name)
87
+
88
+ rep.append({'types': ['freetext'], 'values': full_text, 'comment': 'Free text import of IPRep'})
89
+ return err, rep
90
+
91
+
92
+ def introspection():
93
+ return mispattributes
94
+
95
+
96
+ def version():
97
+ moduleinfo['config'] = moduleconfig
98
+ return moduleinfo
@@ -0,0 +1,54 @@
1
+ #!/usr/bin/env python\
2
+
3
+ import json
4
+ from jinja2.sandbox import SandboxedEnvironment
5
+
6
+ misperrors = {'error': 'Error'}
7
+ mispattributes = {'input': ['text'], 'output': ['text']}
8
+ moduleinfo = {
9
+ 'version': '0.1',
10
+ 'author': 'Sami Mokaddem',
11
+ 'description': 'Render the template with the data passed',
12
+ 'module-type': ['expansion'],
13
+ 'name': 'Ninja Template Rendering',
14
+ 'logo': '',
15
+ 'requirements': [],
16
+ 'features': '',
17
+ 'references': [],
18
+ 'input': '',
19
+ 'output': '',
20
+ }
21
+
22
+ default_template = '- Default template -'
23
+
24
+ def renderTemplate(data, template=default_template):
25
+ env = SandboxedEnvironment()
26
+ return env.from_string(template).render(data)
27
+
28
+ def handler(q=False):
29
+ if q is False:
30
+ return False
31
+ request = json.loads(q)
32
+ if request.get('text'):
33
+ data = request['text']
34
+ else:
35
+ return False
36
+ data = json.loads(data)
37
+ template = data.get('template', default_template)
38
+ templateData = data.get('data', {})
39
+ try:
40
+ rendered = renderTemplate(templateData, template)
41
+ except TypeError:
42
+ rendered = ''
43
+
44
+ r = {'results': [{'types': mispattributes['output'],
45
+ 'values':[rendered]}]}
46
+ return r
47
+
48
+
49
+ def introspection():
50
+ return mispattributes
51
+
52
+
53
+ def version():
54
+ return moduleinfo
@@ -0,0 +1,91 @@
1
+ # -*- coding: utf-8 -*-
2
+ import jbxapi
3
+ import json
4
+ from . import check_input_attribute, checking_error, standard_error_message
5
+ from joe_parser import JoeParser
6
+
7
+ misperrors = {'error': 'Error'}
8
+
9
+ inputSource = ['link']
10
+
11
+ moduleinfo = {
12
+ 'version': '0.2',
13
+ 'author': 'Christian Studer',
14
+ 'description': 'Query Joe Sandbox API with a submission url to get the json report and extract its data that is parsed and converted into MISP attributes and objects.',
15
+ 'module-type': ['expansion'],
16
+ 'name': 'Joe Sandbox Import',
17
+ 'logo': 'joesandbox.png',
18
+ 'requirements': ['jbxapi: Joe Sandbox API python3 library'],
19
+ 'features': "Module using the new format of modules able to return attributes and objects.\n\nThe module returns the same results as the import module [joe_import](https://github.com/MISP/misp-modules/tree/main/misp_modules/modules/import_mod/joe_import.py) taking directly the json report as input.\n\nEven if the introspection will allow all kinds of links to call this module, obviously only the ones presenting a sample or url submission in the Joe Sandbox API will return results.\n\nTo make it work you will need to fill the 'apikey' configuration with your Joe Sandbox API key and provide a valid link as input.",
20
+ 'references': ['https://www.joesecurity.org', 'https://www.joesandbox.com/'],
21
+ 'input': 'Link of a Joe Sandbox sample or url submission.',
22
+ 'output': 'MISP attributes & objects parsed from the analysis report.',
23
+ }
24
+ moduleconfig = ['apiurl', 'apikey', 'import_executable', 'import_mitre_attack']
25
+
26
+
27
+ def handler(q=False):
28
+ if q is False:
29
+ return False
30
+ request = json.loads(q)
31
+ apiurl = request['config'].get('apiurl') or 'https://jbxcloud.joesecurity.org/api'
32
+ apikey = request['config'].get('apikey')
33
+ parser_config = {
34
+ "import_executable": request["config"].get('import_executable', "false") == "true",
35
+ "mitre_attack": request["config"].get('import_mitre_attack', "false") == "true",
36
+ }
37
+
38
+ if not apikey:
39
+ return {'error': 'No API key provided'}
40
+
41
+ if not request.get('attribute') or not check_input_attribute(request['attribute'], requirements=('type', 'value')):
42
+ return {'error': f'{standard_error_message}, {checking_error} that is the link to the Joe Sandbox report.'}
43
+ if request['attribute']['type'] != 'link':
44
+ return {'error': 'Unsupported attribute type.'}
45
+ url = request['attribute']['value']
46
+ if "/submissions/" not in url:
47
+ return {'error': "The URL does not point to a Joe Sandbox analysis."}
48
+
49
+ submission_id = url.split('/')[-1] # The URL has the format https://example.net/submissions/12345
50
+ joe = jbxapi.JoeSandbox(apiurl=apiurl, apikey=apikey, user_agent='MISP joesandbox_query')
51
+
52
+ try:
53
+ joe_info = joe.submission_info(submission_id)
54
+ except jbxapi.ApiError as e:
55
+ return {'error': str(e)}
56
+
57
+ if joe_info["status"] != "finished":
58
+ return {'error': "The analysis has not finished yet."}
59
+
60
+ if joe_info['most_relevant_analysis'] is None:
61
+ return {'error': "No analysis belongs to this submission."}
62
+
63
+ analysis_webid = joe_info['most_relevant_analysis']['webid']
64
+
65
+ joe_parser = JoeParser(parser_config)
66
+ joe_data = json.loads(joe.analysis_download(analysis_webid, 'jsonfixed')[1])
67
+ joe_parser.parse_data(joe_data['analysis'])
68
+ joe_parser.finalize_results()
69
+
70
+ return {'results': joe_parser.results}
71
+
72
+
73
+ def introspection():
74
+ modulesetup = {}
75
+ try:
76
+ userConfig
77
+ modulesetup['userConfig'] = userConfig
78
+ except NameError:
79
+ pass
80
+ try:
81
+ inputSource
82
+ modulesetup['input'] = inputSource
83
+ except NameError:
84
+ pass
85
+ modulesetup['format'] = 'misp_standard'
86
+ return modulesetup
87
+
88
+
89
+ def version():
90
+ moduleinfo['config'] = moduleconfig
91
+ return moduleinfo
@@ -0,0 +1,147 @@
1
+ import jbxapi
2
+ import base64
3
+ import io
4
+ import json
5
+ import logging
6
+ import sys
7
+ import zipfile
8
+ import re
9
+
10
+ from urllib.parse import urljoin
11
+
12
+
13
+ log = logging.getLogger(__name__)
14
+ log.setLevel(logging.DEBUG)
15
+ sh = logging.StreamHandler(sys.stdout)
16
+ sh.setLevel(logging.DEBUG)
17
+ fmt = logging.Formatter(
18
+ "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
19
+ )
20
+ sh.setFormatter(fmt)
21
+ log.addHandler(sh)
22
+
23
+ moduleinfo = {
24
+ 'version': '1.0',
25
+ 'author': 'Joe Security LLC',
26
+ 'description': 'A module to submit files or URLs to Joe Sandbox for an advanced analysis, and return the link of the submission.',
27
+ 'module-type': ['expansion', 'hover'],
28
+ 'name': 'Joe Sandbox Submit',
29
+ 'logo': 'joesandbox.png',
30
+ 'requirements': ['jbxapi: Joe Sandbox API python3 library'],
31
+ 'features': 'The module requires a Joe Sandbox API key to submit files or URL, and returns the link of the submitted analysis.\n\nIt is then possible, when the analysis is completed, to query the Joe Sandbox API to get the data related to the analysis, using the [joesandbox_query module](https://github.com/MISP/misp-modules/tree/main/misp_modules/modules/expansion/joesandbox_query.py) directly on this submission link.',
32
+ 'references': ['https://www.joesecurity.org', 'https://www.joesandbox.com/'],
33
+ 'input': 'Sample, url (or domain) to submit to Joe Sandbox for an advanced analysis.',
34
+ 'output': 'Link of the report generated in Joe Sandbox.',
35
+ }
36
+ moduleconfig = [
37
+ "apiurl",
38
+ "apikey",
39
+ "accept-tac",
40
+ "report-cache",
41
+ "systems",
42
+ ]
43
+
44
+ mispattributes = {
45
+ "input": ["attachment", "malware-sample", "url", "domain"],
46
+ "output": ["link"],
47
+ }
48
+
49
+
50
+ def handler(q=False):
51
+ if q is False:
52
+ return False
53
+
54
+ request = json.loads(q)
55
+
56
+ apiurl = request["config"].get("apiurl") or "https://jbxcloud.joesecurity.org/api"
57
+ apikey = request["config"].get("apikey")
58
+
59
+ # systems
60
+ systems = request["config"].get("systems") or ""
61
+ systems = [s.strip() for s in re.split(r"[\s,;]", systems) if s.strip()]
62
+
63
+ try:
64
+ accept_tac = _parse_bool(request["config"].get("accept-tac"), "accept-tac")
65
+ report_cache = _parse_bool(request["config"].get("report-cache"), "report-cache")
66
+ except _ParseError as e:
67
+ return {"error": str(e)}
68
+
69
+ params = {
70
+ "report-cache": report_cache,
71
+ "systems": systems,
72
+ }
73
+
74
+ if not apikey:
75
+ return {"error": "No API key provided"}
76
+
77
+ joe = jbxapi.JoeSandbox(apiurl=apiurl, apikey=apikey, user_agent="MISP joesandbox_submit", accept_tac=accept_tac)
78
+
79
+ try:
80
+ is_url_submission = "url" in request or "domain" in request
81
+
82
+ if is_url_submission:
83
+ url = request.get("url") or request.get("domain")
84
+
85
+ log.info("Submitting URL: %s", url)
86
+ result = joe.submit_url(url, params=params)
87
+ else:
88
+ if "malware-sample" in request:
89
+ filename = request.get("malware-sample").split("|", 1)[0]
90
+ data = _decode_malware(request["data"], True)
91
+ elif "attachment" in request:
92
+ filename = request["attachment"]
93
+ data = _decode_malware(request["data"], False)
94
+
95
+ data_fp = io.BytesIO(data)
96
+ log.info("Submitting sample: %s", filename)
97
+ result = joe.submit_sample((filename, data_fp), params=params)
98
+
99
+ assert "submission_id" in result
100
+ except jbxapi.JoeException as e:
101
+ return {"error": str(e)}
102
+
103
+ link_to_analysis = urljoin(apiurl, "../submissions/{}".format(result["submission_id"]))
104
+
105
+ return {
106
+ "results": [{
107
+ "types": "link",
108
+ "categories": "External analysis",
109
+ "values": link_to_analysis,
110
+ }]
111
+ }
112
+
113
+
114
+ def introspection():
115
+ return mispattributes
116
+
117
+
118
+ def version():
119
+ moduleinfo["config"] = moduleconfig
120
+ return moduleinfo
121
+
122
+
123
+ def _decode_malware(data, is_encrypted):
124
+ data = base64.b64decode(data)
125
+
126
+ if is_encrypted:
127
+ with zipfile.ZipFile(io.BytesIO(data)) as zipf:
128
+ data = zipf.read(zipf.namelist()[0], pwd=b"infected")
129
+
130
+ return data
131
+
132
+
133
+ class _ParseError(Exception):
134
+ pass
135
+
136
+
137
+ def _parse_bool(value, name="bool"):
138
+ if value is None or value == "":
139
+ return None
140
+
141
+ if value == "true":
142
+ return True
143
+
144
+ if value == "false":
145
+ return False
146
+
147
+ raise _ParseError("Cannot parse {}. Must be 'true' or 'false'".format(name))
@@ -0,0 +1,148 @@
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 query a Lastline report from an analysis link.
6
+ """
7
+ import json
8
+ import lastline_api
9
+ from . import check_input_attribute, checking_error, standard_error_message
10
+
11
+
12
+ misperrors = {
13
+ "error": "Error",
14
+ }
15
+
16
+ mispattributes = {
17
+ "input": [
18
+ "link",
19
+ ],
20
+ "output": ["text"],
21
+ "format": "misp_standard",
22
+ }
23
+
24
+ moduleinfo = {
25
+ 'version': '0.1',
26
+ 'author': 'Stefano Ortolani',
27
+ 'description': 'Deprecation notice: this module will be deprecated by December 2021, please use vmware_nsx module.\n\nQuery Lastline with an analysis link and parse the report into MISP attributes and objects.',
28
+ 'module-type': ['expansion'],
29
+ 'name': 'Lastline Lookup',
30
+ 'logo': 'lastline.png',
31
+ 'requirements': [],
32
+ '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_import](https://github.com/MISP/misp-modules/tree/main/misp_modules/modules/import_mod/lastline_import.py) import module.',
33
+ 'references': ['https://www.lastline.com'],
34
+ 'input': 'Link to a Lastline analysis.',
35
+ 'output': 'MISP attributes and objects parsed from the analysis report.',
36
+ }
37
+
38
+ moduleconfig = [
39
+ "username",
40
+ "password",
41
+ "verify_ssl",
42
+ ]
43
+
44
+
45
+ def introspection():
46
+ return mispattributes
47
+
48
+
49
+ def version():
50
+ moduleinfo["config"] = moduleconfig
51
+ return moduleinfo
52
+
53
+
54
+ def handler(q=False):
55
+ if q is False:
56
+ return False
57
+
58
+ request = json.loads(q)
59
+
60
+ # Parse the init parameters
61
+ try:
62
+ config = request["config"]
63
+ auth_data = lastline_api.LastlineAbstractClient.get_login_params_from_dict(config)
64
+ if not request.get('attribute') or not check_input_attribute(request['attribute'], requirements=('type', 'value')):
65
+ return {'error': f'{standard_error_message}, {checking_error} that is the link to a Lastline analysis.'}
66
+ analysis_link = request['attribute']['value']
67
+ # The API url changes based on the analysis link host name
68
+ api_url = lastline_api.get_portal_url_from_task_link(analysis_link)
69
+ except Exception as e:
70
+ misperrors["error"] = "Error parsing configuration: {}".format(e)
71
+ return misperrors
72
+
73
+ # Parse the call parameters
74
+ try:
75
+ task_uuid = lastline_api.get_uuid_from_task_link(analysis_link)
76
+ except (KeyError, ValueError) as e:
77
+ misperrors["error"] = "Error processing input parameters: {}".format(e)
78
+ return misperrors
79
+
80
+ # Make the API calls
81
+ try:
82
+ api_client = lastline_api.PortalClient(api_url, auth_data, verify_ssl=config.get('verify_ssl', True).lower() in ("true"))
83
+ response = api_client.get_progress(task_uuid)
84
+ if response.get("completed") != 1:
85
+ raise ValueError("Analysis is not finished yet.")
86
+
87
+ response = api_client.get_result(task_uuid)
88
+ if not response:
89
+ raise ValueError("Analysis report is empty.")
90
+
91
+ except Exception as e:
92
+ misperrors["error"] = "Error issuing the API call: {}".format(e)
93
+ return misperrors
94
+
95
+ # Parse and return
96
+ result_parser = lastline_api.LastlineResultBaseParser()
97
+ result_parser.parse(analysis_link, response)
98
+
99
+ event = result_parser.misp_event
100
+ event_dictionary = json.loads(event.to_json())
101
+
102
+ return {
103
+ "results": {
104
+ key: event_dictionary[key]
105
+ for key in ('Attribute', 'Object', 'Tag')
106
+ if (key in event and event[key])
107
+ }
108
+ }
109
+
110
+
111
+ if __name__ == "__main__":
112
+ """Test querying information from a Lastline analysis link."""
113
+ import argparse
114
+ import configparser
115
+
116
+ parser = argparse.ArgumentParser()
117
+ parser.add_argument("-c", "--config-file", dest="config_file")
118
+ parser.add_argument("-s", "--section-name", dest="section_name")
119
+ args = parser.parse_args()
120
+ c = configparser.ConfigParser()
121
+ c.read(args.config_file)
122
+ a = lastline_api.LastlineAbstractClient.get_login_params_from_conf(c, args.section_name)
123
+
124
+ j = json.dumps(
125
+ {
126
+ "config": a,
127
+ "attribute": {
128
+ "value": (
129
+ "https://user.lastline.com/portal#/analyst/task/"
130
+ "1fcbcb8f7fb400100772d6a7b62f501b/overview"
131
+ )
132
+ }
133
+ }
134
+ )
135
+ print(json.dumps(handler(j), indent=4, sort_keys=True))
136
+
137
+ j = json.dumps(
138
+ {
139
+ "config": a,
140
+ "attribute": {
141
+ "value": (
142
+ "https://user.lastline.com/portal#/analyst/task/"
143
+ "f3c0ae115d51001017ff8da768fa6049/overview"
144
+ )
145
+ }
146
+ }
147
+ )
148
+ print(json.dumps(handler(j), indent=4, sort_keys=True))