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,81 @@
1
+ import json
2
+ import vulners
3
+
4
+ misperrors = {'error': 'Error'}
5
+ mispattributes = {'input': ['vulnerability'], 'output': ['text']}
6
+ moduleinfo = {
7
+ 'version': '0.1',
8
+ 'author': 'Igor Ivanov',
9
+ 'description': 'An expansion hover module to expand information about CVE id using Vulners API.',
10
+ 'module-type': ['hover'],
11
+ 'name': 'Vulners Lookup',
12
+ 'logo': 'vulners.png',
13
+ 'requirements': ['Vulners python library', 'An access to the Vulners API'],
14
+ 'features': 'This module takes a vulnerability attribute as input and queries the Vulners API in order to get some additional data about it.\n\nThe API then returns details about the vulnerability.',
15
+ 'references': ['https://vulners.com/'],
16
+ 'input': 'A vulnerability attribute.',
17
+ 'output': 'Text giving additional information about the CVE in input.',
18
+ }
19
+
20
+ # Get API key from https://vulners.com/userinfo
21
+ moduleconfig = ["apikey"]
22
+
23
+
24
+ def handler(q=False):
25
+ if q is False:
26
+ return False
27
+ request = json.loads(q)
28
+ if not request.get('vulnerability'):
29
+ misperrors['error'] = 'Vulnerability id missing'
30
+ return misperrors
31
+
32
+ ai_summary = ''
33
+ exploit_summary = ''
34
+ vuln_summary = ''
35
+
36
+ if not request.get('config') or not request['config'].get('apikey'):
37
+ return {'error': "A Vulners api key is required for this module."}
38
+
39
+ key = request['config']['apikey']
40
+ vulners_api = vulners.Vulners(api_key=key)
41
+ vulnerability = request.get('vulnerability')
42
+ vulners_document = vulners_api.document(vulnerability)
43
+
44
+ # Get AI scoring from the document if it's already calculated
45
+ # There is no need to call AI Scoring method
46
+ if 'score' in vulners_document.get('enchantments', {}):
47
+ vulners_ai_score = vulners_document['enchantments']['score']['value']
48
+ else:
49
+ vulners_ai_score = vulners_api.get_ai_score(vulnerability)
50
+ if len(vulners_ai_score) == 2:
51
+ vulners_ai_score = vulners_ai_score[0]
52
+
53
+ vulners_exploits = vulners_api.searchExploit(vulnerability)
54
+
55
+ if vulners_document:
56
+ vuln_summary += vulners_document.get('description')
57
+ else:
58
+ vuln_summary += 'Non existing CVE'
59
+
60
+ if vulners_ai_score:
61
+ ai_summary += 'Vulners AI Score is ' + str(vulners_ai_score) + " "
62
+
63
+ if vulners_exploits:
64
+ exploit_summary += " || " + str(len(vulners_exploits)) + " Public exploits available:\n "
65
+ for exploit in vulners_exploits:
66
+ exploit_summary += exploit['title'] + " " + exploit['href'] + "\n "
67
+ exploit_summary += "|| Vulnerability Description: " + vuln_summary
68
+
69
+ summary = ai_summary + exploit_summary + vuln_summary
70
+
71
+ r = {'results': [{'types': mispattributes['output'], 'values': summary}]}
72
+ return r
73
+
74
+
75
+ def introspection():
76
+ return mispattributes
77
+
78
+
79
+ def version():
80
+ moduleinfo['config'] = moduleconfig
81
+ return moduleinfo
@@ -0,0 +1,221 @@
1
+ import json
2
+ from pymisp import MISPAttribute, MISPEvent
3
+ from urllib.parse import urlparse
4
+
5
+ import logging
6
+
7
+ import vysion.client as vysion
8
+
9
+ import vysion.dto as dto
10
+ from vysion.dto.util import MISPProcessor
11
+ from . import standard_error_message
12
+
13
+ misperrors = {"error": "Error"}
14
+ mispattributes = {
15
+ "input": [
16
+ "email",
17
+ "domain",
18
+ "hostname",
19
+ "url",
20
+ "text",
21
+ "btc",
22
+ "phone-number",
23
+ "target-org",
24
+ "xmr",
25
+ "dash",
26
+ ],
27
+ "format": "misp_standard",
28
+ }
29
+
30
+ # possible module-types: 'expansion', 'hover' or both
31
+ moduleinfo = {
32
+ 'version': '1',
33
+ 'author': 'Byron Labs',
34
+ 'description': 'Module to enrich the information by making use of the Vysion API.',
35
+ 'module-type': ['expansion'],
36
+ 'name': 'Vysion Enrich',
37
+ 'logo': 'vysion.png',
38
+ 'requirements': ['Vysion python library', 'Vysion API Key'],
39
+ 'features': "This module gets correlated information from Byron Labs' dark web intelligence database. With this you will get several objects containing information related to, for example, an organization victim of a ransomware attack.",
40
+ 'references': ['https://vysion.ai/', 'https://developers.vysion.ai/', 'https://github.com/ByronLabs/vysion-cti/tree/main'],
41
+ 'input': 'company(target-org), country, info, BTC, XMR and DASH address.',
42
+ 'output': 'MISP objects containing title, link to our webapp and TOR, i2p or clearnet URLs.',
43
+ }
44
+
45
+ # config fields that your code expects from the site admin
46
+ moduleconfig = [
47
+ "apikey",
48
+ "event_limit",
49
+ "proxy_host",
50
+ "proxy_port",
51
+ "proxy_username",
52
+ "proxy_password",
53
+ ]
54
+
55
+ LOGGER = logging.getLogger("vysion")
56
+ LOGGER.setLevel(logging.INFO)
57
+ LOGGER.debug("Starting Vysion")
58
+
59
+ DEFAULT_RESULTS_LIMIT = 10
60
+
61
+
62
+ def get_proxy_settings(config: dict) -> dict:
63
+ """Returns proxy settings in the requests format.
64
+ If no proxy settings are set, return None."""
65
+ proxies = None
66
+ host = config.get("proxy_host")
67
+ port = config.get("proxy_port")
68
+ username = config.get("proxy_username")
69
+ password = config.get("proxy_password")
70
+
71
+ if host:
72
+ if not port:
73
+ misperrors["error"] = (
74
+ "The vysion_proxy_host config is set, "
75
+ "please also set the vysion_proxy_port."
76
+ )
77
+ raise KeyError
78
+ parsed = urlparse(host)
79
+ if "http" in parsed.scheme:
80
+ scheme = "http"
81
+ else:
82
+ scheme = parsed.scheme
83
+ netloc = parsed.netloc
84
+ host = f"{netloc}:{port}"
85
+
86
+ if username:
87
+ if not password:
88
+ misperrors["error"] = (
89
+ "The vysion_proxy_username config is set, "
90
+ "please also set the vysion_proxy_password."
91
+ )
92
+ raise KeyError
93
+ auth = f"{username}:{password}"
94
+ host = auth + "@" + host
95
+
96
+ proxies = {"http": f"{scheme}://{host}", "https": f"{scheme}://{host}"}
97
+ return proxies
98
+
99
+
100
+ def parse_error(status_code: int) -> str:
101
+
102
+ status_mapping = {
103
+ 500: "Vysion is blind.",
104
+ 400: "Incorrect request, please check the arguments.",
105
+ 403: "You don't have enough privileges to make the request.",
106
+ }
107
+
108
+ if status_code in status_mapping:
109
+ return status_mapping[status_code]
110
+
111
+ return "Vysion may not be accessible."
112
+
113
+
114
+ def handler(q=False):
115
+
116
+ if q is False:
117
+ return False
118
+
119
+ request = json.loads(q)
120
+
121
+ if not request.get("config") or not request["config"].get("apikey"):
122
+ misperrors["error"] = "A Vysion api key is required for this module."
123
+ return misperrors
124
+
125
+ if not request.get("attribute"):
126
+ return {
127
+ "error": f"{standard_error_message}, which should contain at least a type, a value and an uuid."
128
+ }
129
+
130
+ if request["attribute"]["type"] not in mispattributes["input"]:
131
+ return {"error": "Unsupported attribute type."}
132
+
133
+ # event_limit = request["config"].get("event_limit")
134
+ attribute = request["attribute"]
135
+ proxy_settings = get_proxy_settings(request.get("config"))
136
+
137
+ try:
138
+
139
+ client = vysion.Client(
140
+ api_key=request["config"]["apikey"],
141
+ headers={
142
+ "x-tool": "MISPModuleVysionExpansion",
143
+ },
144
+ proxy=proxy_settings["http"] if proxy_settings else None,
145
+ )
146
+
147
+ LOGGER.debug(attribute)
148
+
149
+ misp_attribute = MISPAttribute()
150
+ misp_attribute.from_dict(**attribute)
151
+
152
+ attribute_type = misp_attribute.type
153
+ attribute_value = misp_attribute.value
154
+
155
+ # https://www.misp-project.org/datamodels/#types
156
+
157
+ LOGGER.debug(attribute_type)
158
+
159
+ result = None
160
+
161
+ if attribute_type == "email":
162
+ result = client.find_email(attribute_value)
163
+ elif attribute_type == "domain":
164
+ result = client.find_url(attribute_value)
165
+ elif attribute_type == "url":
166
+ result = client.find_url(attribute_value)
167
+ elif attribute_type == "text":
168
+ result = client.search(attribute_value)
169
+ elif attribute_type == "target-org":
170
+ result = client.search(attribute_value)
171
+ elif attribute_type == "phone-number":
172
+ result = client.search(attribute_value)
173
+ elif attribute_type == "btc":
174
+ result = client.find_wallet("BTC",attribute_value)
175
+ elif attribute_type == "xmr":
176
+ result = client.find_wallet("XMR",attribute_value)
177
+ elif attribute_type == "dash":
178
+ result = client.find_wallet("DASH",attribute_value)
179
+
180
+ if result is None:
181
+ return {"results": {}}
182
+
183
+ p = MISPProcessor()
184
+ misp_event: MISPEvent = p.process(result, ref_attribute=misp_attribute)
185
+
186
+ LOGGER.info("Vysion client initialized")
187
+
188
+ LOGGER.info("Vysion result obtained")
189
+
190
+ return {
191
+ "results": {
192
+ "Object": [
193
+ json.loads(object.to_json()) for object in misp_event.objects
194
+ ],
195
+ "Attribute": [
196
+ json.loads(attribute.to_json())
197
+ for attribute in misp_event.attributes
198
+ ],
199
+ "Tag": [
200
+ json.loads(tag.to_json())
201
+ for tag in misp_event.tags
202
+ ]
203
+ }
204
+ }
205
+
206
+ except vysion.APIError as ex:
207
+
208
+ LOGGER.error("Error in Vysion")
209
+ LOGGER.error(ex)
210
+
211
+ misperrors["error"] = ex.message
212
+ return misperrors
213
+
214
+
215
+ def introspection():
216
+ return mispattributes
217
+
218
+
219
+ def version():
220
+ moduleinfo["config"] = moduleconfig
221
+ return moduleinfo
@@ -0,0 +1,72 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ import json
4
+ import socket
5
+
6
+ misperrors = {'error': 'Error'}
7
+ mispattributes = {'input': ['domain', 'ip-src', 'ip-dst'], 'output': ['freetext']}
8
+ moduleinfo = {
9
+ 'version': '0.1',
10
+ 'author': 'Raphaël Vinot',
11
+ 'description': 'Module to query a local instance of uwhois (https://github.com/rafiot/uwhoisd).',
12
+ 'module-type': ['expansion'],
13
+ 'name': 'Whois Lookup',
14
+ 'logo': '',
15
+ 'requirements': ['uwhois: A whois python library'],
16
+ 'features': "This module takes a domain or IP address attribute as input and queries a 'Univseral Whois proxy server' to get the correct details of the Whois query on the input value (check the references for more details about this whois server).",
17
+ 'references': ['https://github.com/Lookyloo/uwhoisd'],
18
+ 'input': 'A domain or IP address attribute.',
19
+ 'output': 'Text describing the result of a whois request for the input value.',
20
+ }
21
+
22
+ moduleconfig = ['server', 'port']
23
+
24
+
25
+ def handler(q=False):
26
+ if q is False:
27
+ return False
28
+ request = json.loads(q)
29
+ if request.get('domain'):
30
+ toquery = request['domain']
31
+ elif request.get('ip-src'):
32
+ toquery = request['ip-src']
33
+ elif request.get('ip-dst'):
34
+ toquery = request['ip-dst']
35
+ else:
36
+ misperrors['error'] = "Unsupported attributes type"
37
+ return misperrors
38
+
39
+ if not request.get('config') or (
40
+ not request['config'].get('server') and not request['config'].get('port')
41
+ ):
42
+ misperrors['error'] = 'Whois local instance address is missing'
43
+ return misperrors
44
+
45
+ if 'event_id' in request:
46
+ return handle_expansion(
47
+ request['config']['server'], int(request['config']['port']), toquery
48
+ )
49
+
50
+
51
+ def handle_expansion(server, port, query):
52
+ bytes_whois = b''
53
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
54
+ sock.connect((server, port))
55
+ sock.sendall(f'{query}\n'.encode())
56
+ while True:
57
+ data = sock.recv(2048)
58
+ if not data:
59
+ break
60
+ bytes_whois += data
61
+ return {
62
+ 'results': [{'types': mispattributes['output'], 'values': bytes_whois.decode()}]
63
+ }
64
+
65
+
66
+ def introspection():
67
+ return mispattributes
68
+
69
+
70
+ def version():
71
+ moduleinfo['config'] = moduleconfig
72
+ return moduleinfo
@@ -0,0 +1,232 @@
1
+ import json
2
+
3
+ import requests
4
+
5
+ misperrors = {'error': 'Error'}
6
+ mispattributes = {
7
+ 'input': ['domain'],
8
+ 'output': ['domain', 'dns-soa-email',
9
+ 'whois-registrant-email', 'whois-registrant-phone',
10
+ 'whois-registrant-name',
11
+ 'whois-registrar', 'whois-creation-date', 'domain']
12
+ }
13
+ moduleinfo = {
14
+ 'version': '1',
15
+ 'author': 'WhoisFreaks',
16
+ 'description': 'An expansion module for https://whoisfreaks.com/ that will provide an enriched analysis of the provided domain, including WHOIS and DNS information.',
17
+ 'module-type': ['expansion', 'hover'],
18
+ 'name': 'WhoisFreaks Lookup',
19
+ 'logo': 'whoisfreaks.png',
20
+ 'requirements': ['An access to the Whoisfreaks API_KEY'],
21
+ 'features': 'The module takes a domain as input and queries the Whoisfreaks API with it.\n\nSome parsing operations are then processed on the result of the query to extract as much information as possible.\n\nAfter this we map the extracted data to MISP attributes.',
22
+ 'references': ['https://whoisfreaks.com/'],
23
+ 'input': 'A domain whose Data is required',
24
+ 'output': 'MISP attributes resulting from the query on Whoisfreaks API, included in the following list:\n- domain\n- dns-soa-email\n- whois-registrant-email\n- whois-registrant-phone\n- whois-registrant-name\n- whois-registrar\n- whois-creation-date\n- domain',
25
+ }
26
+
27
+ # config fields that your code expects from the site admin
28
+ moduleconfig = ['apikey']
29
+
30
+
31
+ def handler(q=False):
32
+ if q:
33
+
34
+ request = json.loads(q)
35
+
36
+ if 'config' not in request or (not (request['config'].get('apikey') or ('apiKey' in request['config']))):
37
+ misperrors['error'] = 'WhoisFreaks authentication is missing' + request
38
+ return misperrors
39
+
40
+ apiKey = request['config'].get('apikey')
41
+
42
+ if request.get('domain'):
43
+ domain = request['domain']
44
+ return handle_domain(apiKey, domain, misperrors)
45
+ else:
46
+ misperrors['error'] = "Unsupported attributes types"
47
+ return misperrors
48
+ else:
49
+ return False
50
+
51
+
52
+ def handle_domain(apiKey, domain, errors):
53
+ result_filtered = {"results": []}
54
+ r, status_ok = expand_whois(apiKey, domain)
55
+ if status_ok:
56
+ if r:
57
+ result_filtered['results'].extend(r)
58
+
59
+ r, status_ok = expand_dns(apiKey, domain)
60
+ if status_ok:
61
+ if r:
62
+ result_filtered['results'].extend(r)
63
+
64
+ return result_filtered
65
+
66
+
67
+ def expand_whois(apiKey, domain):
68
+ r = []
69
+ ns_servers = []
70
+ status_ok = False
71
+
72
+ try:
73
+ results = get_whois_response(domain, apiKey)
74
+
75
+ if results:
76
+ status_ok = True
77
+
78
+ if 'create_date' in results:
79
+ r.append(
80
+ {
81
+ 'types': ['whois-creation-date'],
82
+ 'values': [results['create_date']],
83
+ 'categories': ['Attribution'],
84
+ 'comment': 'Creation Date for %s by whoisFreaks'
85
+ % domain
86
+
87
+ }
88
+ )
89
+
90
+ if 'domain_registrar' in results:
91
+ if 'registrar_name' in results['domain_registrar']:
92
+ r.append(
93
+ {
94
+ 'types': ['whois-registrant-name'],
95
+ 'values': [results['domain_registrar']['registrar_name']],
96
+ 'categories': ['Attribution'],
97
+ 'comment': 'Whois information of %s by whoisFreaks'
98
+ % domain
99
+ }
100
+ )
101
+ if 'email_address' in results['domain_registrar']:
102
+ r.append(
103
+ {
104
+ 'types': ['whois-registrant-email'],
105
+ 'values': [results['domain_registrar']['email_address']],
106
+ 'categories': ['Attribution'],
107
+ 'comment': 'Whois information of %s by whoisFreaks'
108
+ % domain
109
+ }
110
+ )
111
+
112
+ if 'phone_number' in results['domain_registrar']:
113
+ r.append(
114
+ {
115
+ 'types': ['whois-registrant-email'],
116
+ 'values': [results['domain_registrar']['phone_number']],
117
+ 'categories': ['Attribution'],
118
+ 'comment': 'Whois information of %s by whoisFreaks'
119
+ % domain
120
+ }
121
+ )
122
+
123
+ if 'name_servers' in results:
124
+ ns_servers = results['name_servers']
125
+ r.append(
126
+ {
127
+ 'types': ['domain'],
128
+ 'values': ns_servers,
129
+ 'categories': ['Attribution'],
130
+ 'comment': 'Name server for %s by whoisFreaks'
131
+ % domain
132
+
133
+ }
134
+ )
135
+
136
+ except Exception:
137
+ misperrors['error'] = "Error while processing Whois Data"
138
+ return [], False
139
+
140
+ return r, status_ok
141
+
142
+
143
+ def expand_dns(apiKey, domain):
144
+ r = []
145
+ status_ok = False
146
+ list_ipv4 = []
147
+ list_ipv6 = []
148
+ servers_mx = []
149
+ soa_hostnames = []
150
+
151
+ try:
152
+ results = get_dns_response(domain, apiKey)
153
+
154
+ if results:
155
+ status_ok = True
156
+
157
+ if 'dnsRecords' in results:
158
+ dns_records = results['dnsRecords']
159
+
160
+ for record in dns_records:
161
+ if record['dnsType'] == 'A':
162
+ list_ipv4.append(record['address'])
163
+ elif record['dnsType'] == 'AAAA':
164
+ list_ipv6.append(record['address'])
165
+ elif record['dnsType'] == 'MX':
166
+ servers_mx.append(record['target'])
167
+ elif record['dnsType'] == 'SOA':
168
+ soa_hostnames.append(record['host'])
169
+
170
+ if list_ipv4:
171
+ r.append({'types': ['domain|ip'],
172
+ 'values': ['%s|%s' % (domain, ipv4) for ipv4 in
173
+ list_ipv4],
174
+ 'categories': ['Network activity'],
175
+ 'comment': 'ipv4 of %s ' %
176
+ domain
177
+ })
178
+ if list_ipv6:
179
+ r.append({'types': ['domain|ip'],
180
+ 'values': ['%s|%s' % (domain, ipv6) for ipv6 in
181
+ list_ipv6],
182
+ 'categories': ['Network activity'],
183
+ 'comment': 'ipv6 of %s' %
184
+ domain
185
+ })
186
+
187
+ if servers_mx:
188
+ r.append({'types': ['domain'],
189
+ 'values': servers_mx,
190
+ 'categories': ['Network activity'],
191
+ 'comment': 'mx of %s' %
192
+ domain
193
+ })
194
+ if soa_hostnames:
195
+ r.append({'types': ['domain'],
196
+ 'values': soa_hostnames,
197
+ 'categories': ['Network activity'],
198
+ 'comment': 'soa hostname of %s' %
199
+ domain
200
+ })
201
+
202
+
203
+ except Exception:
204
+ misperrors['error'] = "Error while processing Whois Data"
205
+ return [], False
206
+
207
+ return r, status_ok
208
+
209
+
210
+ def get_whois_response(domain, apiKey):
211
+ query = requests.get(
212
+ f"https://api.whoisfreaks.com/v1.0/whois?apiKey={apiKey}&whois=live&domainName={domain}"
213
+ )
214
+ if query.status_code != 200 and query.status_code != 206:
215
+ return {'error': f'Error while querying whoisfreaks.com - {query.status_code}: {query.reason}'}
216
+ return query.json()
217
+
218
+
219
+ def get_dns_response(domain, apiKey):
220
+ query = requests.get(
221
+ f"https://api.whoisfreaks.com/v1.0/dns/live?apiKey={apiKey}&domainName={domain}&type=SOA,AAAA,A,MX"
222
+ )
223
+ if query.status_code != 200 and query.status_code != 206:
224
+ return {'error': f'Error while querying whoisfreaks.com - {query.status_code}: {query.reason}'}
225
+ return query.json()
226
+
227
+ def introspection():
228
+ return mispattributes
229
+
230
+ def version():
231
+ moduleinfo['config'] = moduleconfig
232
+ return moduleinfo
@@ -0,0 +1,58 @@
1
+ import json
2
+ from SPARQLWrapper import SPARQLWrapper, JSON
3
+
4
+ misperrors = {'error': 'Error'}
5
+ mispattributes = {'input': ['text'], 'output': ['text']}
6
+ moduleinfo = {
7
+ 'version': '0.2',
8
+ 'author': 'Roman Graf',
9
+ 'description': 'An expansion hover module to extract information from Wikidata to have additional information about particular term for analysis.',
10
+ 'module-type': ['hover'],
11
+ 'name': 'Wikidata Lookup',
12
+ 'logo': 'wikidata.png',
13
+ 'requirements': ['SPARQLWrapper python library'],
14
+ 'features': 'This module takes a text attribute as input and queries the Wikidata API. If the text attribute is clear enough to define a specific term, the API returns a wikidata link in response.',
15
+ 'references': ['https://www.wikidata.org'],
16
+ 'input': 'Text attribute.',
17
+ 'output': 'Text attribute.',
18
+ }
19
+ moduleconfig = []
20
+ # sample query text 'Microsoft' should provide Wikidata link https://www.wikidata.org/wiki/Q2283 in response
21
+ wiki_api_url = 'https://query.wikidata.org/bigdata/namespace/wdq/sparql'
22
+
23
+
24
+ def handler(q=False):
25
+ if q is False:
26
+ return False
27
+ request = json.loads(q)
28
+ if not request.get('text'):
29
+ misperrors['error'] = 'Query text missing'
30
+ return misperrors
31
+
32
+ sparql = SPARQLWrapper(wiki_api_url, agent='Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36')
33
+ query_string = \
34
+ "SELECT ?item \n" \
35
+ "WHERE { \n" \
36
+ "?item rdfs:label\"" + request.get('text') + "\" @en \n" \
37
+ "}\n"
38
+ sparql.setQuery(query_string)
39
+ sparql.setReturnFormat(JSON)
40
+ results = sparql.query().convert()
41
+ try:
42
+ result = results["results"]["bindings"]
43
+ summary = result[0]["item"]["value"] if result else 'No additional data found on Wikidata'
44
+ except Exception as e:
45
+ misperrors['error'] = 'wikidata API not accessible {}'.format(e)
46
+ return misperrors['error']
47
+
48
+ r = {'results': [{'types': mispattributes['output'], 'values': summary}]}
49
+ return r
50
+
51
+
52
+ def introspection():
53
+ return mispattributes
54
+
55
+
56
+ def version():
57
+ moduleinfo['config'] = moduleconfig
58
+ return moduleinfo