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,8 @@
1
+ """vt_graph_parser.
2
+
3
+ This module provides methods to import graph from misp.
4
+ """
5
+
6
+
7
+ from .helpers import * # noqa
8
+ from .importers import * # noqa
@@ -0,0 +1,20 @@
1
+ """vt_graph_parser.errors.
2
+
3
+ This module provides custom errors for data importers.
4
+ """
5
+
6
+
7
+ class GraphImportError(Exception):
8
+ pass
9
+
10
+
11
+ class InvalidFileFormatError(Exception):
12
+ pass
13
+
14
+
15
+ class MispEventNotFoundError(Exception):
16
+ pass
17
+
18
+
19
+ class ServerError(Exception):
20
+ pass
@@ -0,0 +1,7 @@
1
+ """vt_graph_parser.helpers.
2
+
3
+ This modules provides functions and attributes to help MISP importers.
4
+ """
5
+
6
+
7
+ __all__ = ["parsers", "rules", "wrappers"]
@@ -0,0 +1,88 @@
1
+ """vt_graph_parser.helpers.parsers.
2
+
3
+ This module provides parsers for MISP inputs.
4
+ """
5
+
6
+
7
+ from vt_graph_parser.helpers.wrappers import MispAttribute
8
+
9
+
10
+ MISP_INPUT_ATTR = [
11
+ "hostname",
12
+ "domain",
13
+ "ip-src",
14
+ "ip-dst",
15
+ "md5",
16
+ "sha1",
17
+ "sha256",
18
+ "url",
19
+ "filename|md5",
20
+ "filename",
21
+ "target-user",
22
+ "target-email"
23
+ ]
24
+
25
+ VIRUSTOTAL_GRAPH_LINK_PREFIX = "https://www.virustotal.com/graph/"
26
+
27
+
28
+ def _parse_data(attributes, objects):
29
+ """Parse MISP event attributes and objects data.
30
+
31
+ Args:
32
+ attributes (dict): dictionary which contains the MISP event attributes data.
33
+ objects (dict): dictionary which contains the MISP event objects data.
34
+
35
+ Returns:
36
+ ([MispAttribute], str): MISP attributes and VTGraph link if exists.
37
+ Link defaults to "".
38
+ """
39
+ attributes_data = []
40
+ vt_graph_link = ""
41
+
42
+ # Get simple MISP event attributes.
43
+ attributes_data += (
44
+ [attr for attr in attributes
45
+ if attr.get("type") in MISP_INPUT_ATTR])
46
+
47
+ # Get attributes from MISP objects too.
48
+ if objects:
49
+ for object_ in objects:
50
+ object_attrs = object_.get("Attribute", [])
51
+ attributes_data += (
52
+ [attr for attr in object_attrs
53
+ if attr.get("type") in MISP_INPUT_ATTR])
54
+
55
+ # Check if there is any VirusTotal Graph computed in MISP event.
56
+ vt_graph_links = (
57
+ attr for attr in attributes if attr.get("type") == "link"
58
+ and attr.get("value", "").startswith(VIRUSTOTAL_GRAPH_LINK_PREFIX))
59
+
60
+ # MISP could have more than one VirusTotal Graph, so we will take
61
+ # the last one.
62
+ current_id = 0 # MISP attribute id is the number of the attribute.
63
+ vt_graph_link = ""
64
+ for link in vt_graph_links:
65
+ if int(link.get("id")) > current_id:
66
+ current_id = int(link.get("id"))
67
+ vt_graph_link = link.get("value")
68
+
69
+ attributes = [
70
+ MispAttribute(data["type"], data["category"], data["value"])
71
+ for data in attributes_data]
72
+ return (attributes,
73
+ vt_graph_link.replace(VIRUSTOTAL_GRAPH_LINK_PREFIX, ""))
74
+
75
+
76
+ def parse_pymisp_response(payload):
77
+ """Get event attributes and VirusTotal Graph id from pymisp response.
78
+
79
+ Args:
80
+ payload (dict): dictionary which contains pymisp response.
81
+
82
+ Returns:
83
+ ([MispAttribute], str): MISP attributes and VTGraph link if exists.
84
+ Link defaults to "".
85
+ """
86
+ event_attrs = payload.get("Attribute", [])
87
+ objects = payload.get("Object")
88
+ return _parse_data(event_attrs, objects)
@@ -0,0 +1,304 @@
1
+ """vt_graph_parser.helpers.rules.
2
+
3
+ This module provides rules that helps MISP importers to connect MISP attributes
4
+ between them using VirusTotal relationship. Check all available relationship
5
+ here:
6
+
7
+ - File: https://docs.virustotal.com/reference/files#relationships
8
+ - URL: https://docs.virustotal.com/reference/url-object#relationships
9
+ - Domain: https://docs.virustotal.com/reference/domains-object#relationships
10
+ - IP: https://docs.virustotal.com/reference/ip-object#relationships
11
+ """
12
+
13
+
14
+ import abc
15
+
16
+
17
+ class MispEventRule(object):
18
+ """Rules for MISP event nodes connection object wrapper."""
19
+
20
+ def __init__(self, last_rule=None, node=None):
21
+ """Create a MispEventRule instance.
22
+
23
+ MispEventRule is a collection of rules that can infer the relationships
24
+ between nodes from MISP events.
25
+
26
+ Args:
27
+ last_rule (MispEventRule): previous rule.
28
+ node (Node): actual node.
29
+ """
30
+ self.last_rule = last_rule
31
+ self.node = node
32
+ self.relation_event = {
33
+ "ip_address": self.__ip_transition,
34
+ "url": self.__url_transition,
35
+ "domain": self.__domain_transition,
36
+ "file": self.__file_transition
37
+ }
38
+
39
+ def get_last_different_rule(self):
40
+ """Search the last rule whose event was different from actual.
41
+
42
+ Returns:
43
+ MispEventRule: the last different rule.
44
+ """
45
+ if not isinstance(self, self.last_rule.__class__):
46
+ return self.last_rule
47
+ else:
48
+ return self.last_rule.get_last_different_rule()
49
+
50
+ def resolve_relation(self, graph, node, misp_category):
51
+ """Try to infer a relationship between two nodes.
52
+
53
+ This method is based on a non-deterministic finite automaton for
54
+ this reason the future rule only depends on the actual rule and the input
55
+ node.
56
+
57
+ For example if the actual rule is a MISPEventDomainRule and the given node
58
+ is an ip_address node, the connection type between them will be
59
+ `resolutions` and the this rule will transit to MISPEventIPRule.
60
+
61
+ Args:
62
+ graph (VTGraph): graph to be computed.
63
+ node (Node): the node to be linked.
64
+ misp_category: (str): MISP category of the given node.
65
+
66
+ Returns:
67
+ MispEventRule: the transited rule.
68
+ """
69
+ if node.node_type in self.relation_event:
70
+ return self.relation_event[node.node_type](graph, node, misp_category)
71
+ else:
72
+ return self.manual_link(graph, node)
73
+
74
+ def manual_link(self, graph, node):
75
+ """Creates a manual link between self.node and the given node.
76
+
77
+ We accept MISP types that VirusTotal does not know how to link, so we create
78
+ a end to end relationship instead of create an unknown relationship node.
79
+
80
+ Args:
81
+ graph (VTGraph): graph to be computed.
82
+ node (Node): the node to be linked.
83
+
84
+ Returns:
85
+ MispEventRule: the transited rule.
86
+ """
87
+ graph.add_link(self.node.node_id, node.node_id, "manual")
88
+ return self
89
+
90
+ @abc.abstractmethod
91
+ def __file_transition(self, graph, node, misp_category):
92
+ """Make a new transition due to file attribute event.
93
+
94
+ Args:
95
+ graph (VTGraph): graph to be computed.
96
+ node (Node): the node to be linked.
97
+ misp_category: (str): MISP category of the given node.
98
+
99
+ Returns:
100
+ MispEventRule: the transited rule.
101
+ """
102
+ pass
103
+
104
+ @abc.abstractmethod
105
+ def __ip_transition(self, graph, node, misp_category):
106
+ """Make a new transition due to ip attribute event.
107
+
108
+ Args:
109
+ graph (VTGraph): graph to be computed.
110
+ node (Node): the node to be linked.
111
+ misp_category: (str): MISP category of the given node.
112
+
113
+ Returns:
114
+ MispEventRule: the transited rule.
115
+ """
116
+ pass
117
+
118
+ @abc.abstractmethod
119
+ def __url_transition(self, graph, node, misp_category):
120
+ """Make a new transition due to url attribute event.
121
+
122
+ Args:
123
+ graph (VTGraph): graph to be computed.
124
+ node (Node): the node to be linked.
125
+ misp_category: (str): MISP category of the given node.
126
+
127
+ Returns:
128
+ MispEventRule: the transited rule.
129
+ """
130
+ pass
131
+
132
+ @abc.abstractmethod
133
+ def __domain_transition(self, graph, node, misp_category):
134
+ """Make a new transition due to domain attribute event.
135
+
136
+ Args:
137
+ graph (VTGraph): graph to be computed.
138
+ node (Node): the node to be linked.
139
+ misp_category: (str): MISP category of the given node.
140
+
141
+ Returns:
142
+ MispEventRule: the transited rule.
143
+ """
144
+ pass
145
+
146
+
147
+ class MispEventURLRule(MispEventRule):
148
+ """Rule for URL event."""
149
+
150
+ def __init__(self, last_rule=None, node=None):
151
+ super(MispEventURLRule, self).__init__(last_rule, node)
152
+ self.relation_event = {
153
+ "ip_address": self.__ip_transition,
154
+ "url": self.__url_transition,
155
+ "domain": self.__domain_transition,
156
+ "file": self.__file_transition
157
+ }
158
+
159
+ def __file_transition(self, graph, node, misp_category):
160
+ graph.add_link(self.node.node_id, node.node_id, "downloaded_files")
161
+ return MispEventFileRule(self, node)
162
+
163
+ def __ip_transition(self, graph, node, misp_category):
164
+ graph.add_link(self.node.node_id, node.node_id, "contacted_ips")
165
+ return MispEventIPRule(self, node)
166
+
167
+ def __url_transition(self, graph, node, misp_category):
168
+ suitable_rule = self.get_last_different_rule()
169
+ if not isinstance(suitable_rule, MispEventInitialRule):
170
+ return suitable_rule.resolve_relation(graph, node, misp_category)
171
+ else:
172
+ return MispEventURLRule(self, node)
173
+
174
+ def __domain_transition(self, graph, node, misp_category):
175
+ graph.add_link(self.node.node_id, node.node_id, "contacted_domains")
176
+ return MispEventDomainRule(self, node)
177
+
178
+
179
+ class MispEventIPRule(MispEventRule):
180
+ """Rule for IP event."""
181
+
182
+ def __init__(self, last_rule=None, node=None):
183
+ super(MispEventIPRule, self).__init__(last_rule, node)
184
+ self.relation_event = {
185
+ "ip_address": self.__ip_transition,
186
+ "url": self.__url_transition,
187
+ "domain": self.__domain_transition,
188
+ "file": self.__file_transition
189
+ }
190
+
191
+ def __file_transition(self, graph, node, misp_category):
192
+ connection_type = "communicating_files"
193
+ if misp_category == "Artifacts dropped":
194
+ connection_type = "downloaded_files"
195
+ graph.add_link(self.node.node_id, node.node_id, connection_type)
196
+ return MispEventFileRule(self, node)
197
+
198
+ def __ip_transition(self, graph, node, misp_category):
199
+ suitable_rule = self.get_last_different_rule()
200
+ if not isinstance(suitable_rule, MispEventInitialRule):
201
+ return suitable_rule.resolve_relation(graph, node, misp_category)
202
+ else:
203
+ return MispEventIPRule(self, node)
204
+
205
+ def __url_transition(self, graph, node, misp_category):
206
+ graph.add_link(self.node.node_id, node.node_id, "urls")
207
+ return MispEventURLRule(self, node)
208
+
209
+ def __domain_transition(self, graph, node, misp_category):
210
+ graph.add_link(self.node.node_id, node.node_id, "resolutions")
211
+ return MispEventDomainRule(self, node)
212
+
213
+
214
+ class MispEventDomainRule(MispEventRule):
215
+ """Rule for domain event."""
216
+
217
+ def __init__(self, last_rule=None, node=None):
218
+ super(MispEventDomainRule, self).__init__(last_rule, node)
219
+ self.relation_event = {
220
+ "ip_address": self.__ip_transition,
221
+ "url": self.__url_transition,
222
+ "domain": self.__domain_transition,
223
+ "file": self.__file_transition
224
+ }
225
+
226
+ def __file_transition(self, graph, node, misp_category):
227
+ connection_type = "communicating_files"
228
+ if misp_category == "Artifacts dropped":
229
+ connection_type = "downloaded_files"
230
+ graph.add_link(self.node.node_id, node.node_id, connection_type)
231
+ return MispEventFileRule(self, node)
232
+
233
+ def __ip_transition(self, graph, node, misp_category):
234
+ graph.add_link(self.node.node_id, node.node_id, "resolutions")
235
+ return MispEventIPRule(self, node)
236
+
237
+ def __url_transition(self, graph, node, misp_category):
238
+ graph.add_link(self.node.node_id, node.node_id, "urls")
239
+ return MispEventURLRule(self, node)
240
+
241
+ def __domain_transition(self, graph, node, misp_category):
242
+ suitable_rule = self.get_last_different_rule()
243
+ if not isinstance(suitable_rule, MispEventInitialRule):
244
+ return suitable_rule.resolve_relation(graph, node, misp_category)
245
+ else:
246
+ graph.add_link(self.node.node_id, node.node_id, "siblings")
247
+ return MispEventDomainRule(self, node)
248
+
249
+
250
+ class MispEventFileRule(MispEventRule):
251
+ """Rule for File event."""
252
+
253
+ def __init__(self, last_rule=None, node=None):
254
+ super(MispEventFileRule, self).__init__(last_rule, node)
255
+ self.relation_event = {
256
+ "ip_address": self.__ip_transition,
257
+ "url": self.__url_transition,
258
+ "domain": self.__domain_transition,
259
+ "file": self.__file_transition
260
+ }
261
+
262
+ def __file_transition(self, graph, node, misp_category):
263
+ suitable_rule = self.get_last_different_rule()
264
+ if not isinstance(suitable_rule, MispEventInitialRule):
265
+ return suitable_rule.resolve_relation(graph, node, misp_category)
266
+ else:
267
+ return MispEventFileRule(self, node)
268
+
269
+ def __ip_transition(self, graph, node, misp_category):
270
+ graph.add_link(self.node.node_id, node.node_id, "contacted_ips")
271
+ return MispEventIPRule(self, node)
272
+
273
+ def __url_transition(self, graph, node, misp_category):
274
+ graph.add_link(self.node.node_id, node.node_id, "contacted_urls")
275
+ return MispEventURLRule(self, node)
276
+
277
+ def __domain_transition(self, graph, node, misp_category):
278
+ graph.add_link(self.node.node_id, node.node_id, "contacted_domains")
279
+ return MispEventDomainRule(self, node)
280
+
281
+
282
+ class MispEventInitialRule(MispEventRule):
283
+ """Initial rule."""
284
+
285
+ def __init__(self, last_rule=None, node=None):
286
+ super(MispEventInitialRule, self).__init__(last_rule, node)
287
+ self.relation_event = {
288
+ "ip_address": self.__ip_transition,
289
+ "url": self.__url_transition,
290
+ "domain": self.__domain_transition,
291
+ "file": self.__file_transition
292
+ }
293
+
294
+ def __file_transition(self, graph, node, misp_category):
295
+ return MispEventFileRule(self, node)
296
+
297
+ def __ip_transition(self, graph, node, misp_category):
298
+ return MispEventIPRule(self, node)
299
+
300
+ def __url_transition(self, graph, node, misp_category):
301
+ return MispEventURLRule(self, node)
302
+
303
+ def __domain_transition(self, graph, node, misp_category):
304
+ return MispEventDomainRule(self, node)
@@ -0,0 +1,58 @@
1
+ """vt_graph_parser.helpers.wrappers.
2
+
3
+ This module provides a Python object wrapper for MISP objects.
4
+ """
5
+
6
+
7
+ class MispAttribute(object):
8
+ """Python object wrapper for MISP attribute.
9
+
10
+ Attributes:
11
+ type (str): VirusTotal node type.
12
+ category (str): MISP attribute category.
13
+ value (str): node id.
14
+ label (str): node name.
15
+ misp_type (str): MISP node type.
16
+ """
17
+
18
+ MISP_TYPES_REFERENCE = {
19
+ "hostname": "domain",
20
+ "domain": "domain",
21
+ "ip-src": "ip_address",
22
+ "ip-dst": "ip_address",
23
+ "url": "url",
24
+ "filename|X": "file",
25
+ "filename": "file",
26
+ "md5": "file",
27
+ "sha1": "file",
28
+ "sha256": "file",
29
+ "target-user": "victim",
30
+ "target-email": "email"
31
+ }
32
+
33
+ def __init__(self, misp_type, category, value, label=""):
34
+ """Constructor for a MispAttribute.
35
+
36
+ Args:
37
+ misp_type (str): MISP type attribute.
38
+ category (str): MISP category attribute.
39
+ value (str): attribute value.
40
+ label (str): attribute label.
41
+ """
42
+ if misp_type.startswith("filename|"):
43
+ label, value = value.split("|")
44
+ misp_type = "filename|X"
45
+ if misp_type == "filename":
46
+ label = value
47
+
48
+ self.type = self.MISP_TYPES_REFERENCE.get(misp_type)
49
+ self.category = category
50
+ self.value = value
51
+ self.label = label
52
+ self.misp_type = misp_type
53
+
54
+ def __eq__(self, other):
55
+ return (isinstance(other, self.__class__) and self.value == other.value and self.type == other.type)
56
+
57
+ def __repr__(self):
58
+ return 'MispAttribute("{type}", "{category}", "{value}")'.format(type=self.type, category=self.category, value=self.value)
@@ -0,0 +1,7 @@
1
+ """vt_graph_parser.importers.
2
+
3
+ This module provides methods to import graphs from MISP.
4
+ """
5
+
6
+
7
+ __all__ = ["base", "pymisp_response"]
@@ -0,0 +1,98 @@
1
+ """vt_graph_parser.importers.base.
2
+
3
+ This module provides a common method to import graph from misp attributes.
4
+ """
5
+
6
+
7
+ import vt_graph_api
8
+ from vt_graph_parser.helpers.rules import MispEventInitialRule
9
+
10
+
11
+ def import_misp_graph(
12
+ misp_attributes, graph_id, vt_api_key, fetch_information, name,
13
+ private, fetch_vt_enterprise, user_editors, user_viewers, group_editors,
14
+ group_viewers, use_vt_to_connect_the_graph, max_api_quotas,
15
+ max_search_depth):
16
+ """Import VirusTotal Graph from MISP.
17
+
18
+ Args:
19
+ misp_attributes ([MispAttribute]): list with the MISP attributes which
20
+ will be added to the returned graph.
21
+ graph_id: if supplied, the graph will be loaded instead of compute it again.
22
+ vt_api_key (str): VT API Key.
23
+ fetch_information (bool): whether the script will fetch
24
+ information for added nodes in VT. Defaults to True.
25
+ name (str): graph title. Defaults to "".
26
+ private (bool): True for private graphs. You need to have
27
+ Private Graph premium features enabled in your subscription. Defaults
28
+ to False.
29
+ fetch_vt_enterprise (bool, optional): if True, the graph will search any
30
+ available information using VirusTotal Intelligence for the node if there
31
+ is no normal information for it. Defaults to False.
32
+ user_editors ([str]): usernames that can edit the graph.
33
+ Defaults to None.
34
+ user_viewers ([str]): usernames that can view the graph.
35
+ Defaults to None.
36
+ group_editors ([str]): groups that can edit the graph.
37
+ Defaults to None.
38
+ group_viewers ([str]): groups that can view the graph.
39
+ Defaults to None.
40
+ use_vt_to_connect_the_graph (bool): if True, graph nodes will
41
+ be linked using VirusTotal API. Otherwise, the links will be generated
42
+ using production rules based on MISP attributes order. Defaults to
43
+ False.
44
+ max_api_quotas (int): maximum number of api quotas that could
45
+ be consumed to resolve graph using VirusTotal API. Defaults to 20000.
46
+ max_search_depth (int, optional): max search depth to explore
47
+ relationship between nodes when use_vt_to_connect_the_graph is True.
48
+ Defaults to 3.
49
+
50
+ If use_vt_to_connect_the_graph is True, it will take some time to compute
51
+ graph.
52
+
53
+ Returns:
54
+ vt_graph_api.graph.VTGraph: the imported graph.
55
+ """
56
+
57
+ rule = MispEventInitialRule()
58
+
59
+ # Check if the event has been already computed in VirusTotal Graph. Otherwise
60
+ # a new graph will be created.
61
+ if not graph_id:
62
+ graph = vt_graph_api.VTGraph(
63
+ api_key=vt_api_key, name=name, private=private,
64
+ user_editors=user_editors, user_viewers=user_viewers,
65
+ group_editors=group_editors, group_viewers=group_viewers)
66
+ else:
67
+ graph = vt_graph_api.VTGraph.load_graph(graph_id, vt_api_key)
68
+
69
+ attributes_to_add = [attr for attr in misp_attributes
70
+ if not graph.has_node(attr.value)]
71
+
72
+ total_expandable_attrs = max(sum(
73
+ 1 for attr in attributes_to_add
74
+ if attr.type in vt_graph_api.Node.SUPPORTED_NODE_TYPES),
75
+ 1)
76
+
77
+ max_quotas_per_search = max(
78
+ int(max_api_quotas / total_expandable_attrs), 1)
79
+
80
+ previous_node_id = ""
81
+ for attr in attributes_to_add:
82
+ # Add the current attr as node to the graph.
83
+ added_node = graph.add_node(
84
+ attr.value, attr.type, fetch_information, fetch_vt_enterprise,
85
+ attr.label)
86
+ # If use_vt_to_connect_the_grap is True the nodes will be connected using
87
+ # VT API.
88
+ if use_vt_to_connect_the_graph:
89
+ if (attr.type not in vt_graph_api.Node.SUPPORTED_NODE_TYPES and previous_node_id):
90
+ graph.add_link(previous_node_id, attr.value, "manual")
91
+ else:
92
+ graph.connect_with_graph(
93
+ attr.value, max_quotas_per_search, max_search_depth,
94
+ fetch_info_collected_nodes=fetch_information)
95
+ else:
96
+ rule = rule.resolve_relation(graph, added_node, attr.category)
97
+
98
+ return graph
@@ -0,0 +1,73 @@
1
+ """vt_graph_parser.importers.pymisp_response.
2
+
3
+ This modules provides a graph importer method for MISP event by using the
4
+ response payload giving by MISP API directly.
5
+ """
6
+
7
+
8
+ from vt_graph_parser.helpers.parsers import parse_pymisp_response
9
+ from vt_graph_parser.importers.base import import_misp_graph
10
+
11
+
12
+ def from_pymisp_response(
13
+ payload, vt_api_key, fetch_information=True,
14
+ private=False, fetch_vt_enterprise=False, user_editors=None,
15
+ user_viewers=None, group_editors=None, group_viewers=None,
16
+ use_vt_to_connect_the_graph=False, max_api_quotas=1000,
17
+ max_search_depth=3, expand_node_one_level=False):
18
+ """Import VirusTotal Graph from MISP JSON file.
19
+
20
+ Args:
21
+ payload (dict): dictionary which contains the request payload.
22
+ vt_api_key (str): VT API Key.
23
+ fetch_information (bool, optional): whether the script will fetch
24
+ information for added nodes in VT. Defaults to True.
25
+ name (str, optional): graph title. Defaults to "".
26
+ private (bool, optional): True for private graphs. You need to have
27
+ Private Graph premium features enabled in your subscription. Defaults
28
+ to False.
29
+ fetch_vt_enterprise (bool, optional): if True, the graph will search any
30
+ available information using VirusTotal Intelligence for the node if there
31
+ is no normal information for it. Defaults to False.
32
+ user_editors ([str], optional): usernames that can edit the graph.
33
+ Defaults to None.
34
+ user_viewers ([str], optional): usernames that can view the graph.
35
+ Defaults to None.
36
+ group_editors ([str], optional): groups that can edit the graph.
37
+ Defaults to None.
38
+ group_viewers ([str], optional): groups that can view the graph.
39
+ Defaults to None.
40
+ use_vt_to_connect_the_graph (bool, optional): if True, graph nodes will
41
+ be linked using VirusTotal API. Otherwise, the links will be generated
42
+ using production rules based on MISP attributes order. Defaults to
43
+ False.
44
+ max_api_quotas (int, optional): maximum number of api quotas that could
45
+ be consumed to resolve graph using VirusTotal API. Defaults to 20000.
46
+ max_search_depth (int, optional): max search depth to explore
47
+ relationship between nodes when use_vt_to_connect_the_graph is True.
48
+ Defaults to 3.
49
+ expand_one_level (bool, optional): expand entire graph one level.
50
+ Defaults to False.
51
+
52
+ If use_vt_to_connect_the_graph is True, it will take some time to compute
53
+ graph.
54
+
55
+ Raises:
56
+ LoaderError: if JSON file is invalid.
57
+
58
+ Returns:
59
+ [vt_graph_api.graph.VTGraph: the imported graph].
60
+ """
61
+ graphs = []
62
+ for event_payload in payload['data']:
63
+ misp_attrs, graph_id = parse_pymisp_response(event_payload)
64
+ name = "Graph created from MISP event"
65
+ graph = import_misp_graph(
66
+ misp_attrs, graph_id, vt_api_key, fetch_information, name,
67
+ private, fetch_vt_enterprise, user_editors, user_viewers, group_editors,
68
+ group_viewers, use_vt_to_connect_the_graph, max_api_quotas,
69
+ max_search_depth)
70
+ if expand_node_one_level:
71
+ graph.expand_n_level(1)
72
+ graphs.append(graph)
73
+ return graphs
@@ -0,0 +1,4 @@
1
+ from .expansion import * # noqa
2
+ from .import_mod import * # noqa
3
+ from .export_mod import * # noqa
4
+ from .action_mod import * # noqa
@@ -0,0 +1 @@
1
+ __all__ = ['testaction', 'mattermost', 'slack']