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,290 @@
1
+ # This module does not appear to be actively maintained.
2
+ # Please see https://github.com/DomainTools/domaintools_misp
3
+ # for the official DomainTools-supported MISP app
4
+
5
+ import json
6
+ import logging
7
+ import sys
8
+
9
+ from domaintools import API
10
+
11
+
12
+ log = logging.getLogger('domaintools')
13
+ log.setLevel(logging.DEBUG)
14
+ ch = logging.StreamHandler(sys.stdout)
15
+ ch.setLevel(logging.DEBUG)
16
+ formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
17
+ ch.setFormatter(formatter)
18
+ log.addHandler(ch)
19
+
20
+ misperrors = {'error': 'Error'}
21
+ mispattributes = {
22
+ 'input': ['domain', 'email-src', 'email-dst', 'target-email', 'whois-registrant-email',
23
+ 'whois-registrant-name', 'whois-registrant-phone', 'ip-src', 'ip-dst'],
24
+ 'output': ['whois-registrant-email', 'whois-registrant-phone', 'whois-registrant-name',
25
+ 'whois-registrar', 'whois-creation-date', 'freetext', 'domain']
26
+ }
27
+
28
+ moduleinfo = {
29
+ 'version': '0.1',
30
+ 'author': 'Raphaël Vinot',
31
+ 'description': 'DomainTools MISP expansion module.',
32
+ 'module-type': ['expansion', 'hover'],
33
+ 'name': 'DomainTools Lookup',
34
+ 'logo': 'domaintools.png',
35
+ 'requirements': ['Domaintools python library', 'A Domaintools API access (username & apikey)'],
36
+ 'features': 'This module takes a MISP attribute as input to query the Domaintools API. The API returns then the result of the query with some types we map into compatible types we add as MISP attributes.\n\nPlease note that composite attributes composed by at least one of the input types mentionned below (domains, IPs, hostnames) are also supported.',
37
+ 'references': ['https://www.domaintools.com/'],
38
+ 'input': 'A MISP attribute included in the following list:\n- domain\n- hostname\n- email-src\n- email-dst\n- target-email\n- whois-registrant-email\n- whois-registrant-name\n- whois-registrant-phone\n- ip-src\n- ip-dst',
39
+ 'output': 'MISP attributes mapped after the Domaintools API has been queried, included in the following list:\n- whois-registrant-email\n- whois-registrant-phone\n- whois-registrant-name\n- whois-registrar\n- whois-creation-date\n- text\n- domain',
40
+ }
41
+
42
+ moduleconfig = ['username', 'api_key']
43
+
44
+ query_profiles = [
45
+ {'inputs': ['domain'], 'services': ['parsed_whois', 'domain_profile', 'reputation', 'reverse_ip']},
46
+ {'inputs': ['email-src', 'email-dst', 'target-email', 'whois-registrant-email', 'whois-registrant-name', 'whois-registrant-phone'], 'services': ['reverse_whois']},
47
+ {'inputs': ['ip-src', 'ip-dst'], 'services': ['host_domains']}
48
+ ]
49
+
50
+
51
+ class DomainTools(object):
52
+
53
+ def __init__(self):
54
+ self.reg_mail = {}
55
+ self.reg_phone = {}
56
+ self.reg_name = {}
57
+ self.registrar = {}
58
+ self.creation_date = {}
59
+ self.domain_ip = {}
60
+ self.domain = {}
61
+ self.risk = ()
62
+ self.freetext = ''
63
+
64
+ def _add_value(self, value_type, value, comment):
65
+ if value_type.get(value):
66
+ if comment and comment not in value_type[value]:
67
+ value_type[value] += ' - {}'.format(comment)
68
+ else:
69
+ value_type[value] = comment or ''
70
+ return value_type
71
+
72
+ def add_mail(self, mail, comment=None):
73
+ self.reg_mail = self._add_value(self.reg_mail, mail, comment)
74
+
75
+ def add_phone(self, phone, comment=None):
76
+ self.reg_phone = self._add_value(self.reg_phone, phone, comment)
77
+
78
+ def add_name(self, name, comment=None):
79
+ self.reg_name = self._add_value(self.reg_name, name, comment)
80
+
81
+ def add_registrar(self, reg, comment=None):
82
+ self.registrar = self._add_value(self.registrar, reg, comment)
83
+
84
+ def add_creation_date(self, date, comment=None):
85
+ self.creation_date = self._add_value(self.creation_date, date, comment)
86
+
87
+ def add_ip(self, ip, comment=None):
88
+ self.domain_ip = self._add_value(self.domain_ip, ip, comment)
89
+
90
+ def add_domain(self, domain, comment=None):
91
+ self.domain = self._add_value(self.domain, domain, comment)
92
+
93
+ def dump(self):
94
+ to_return = []
95
+ if self.reg_mail:
96
+ for mail, comment in self.reg_mail.items():
97
+ to_return.append({'type': 'whois-registrant-email', 'values': [mail], 'comment': comment or ''})
98
+ if self.reg_phone:
99
+ for phone, comment in self.reg_phone.items():
100
+ to_return.append({'type': 'whois-registrant-phone', 'values': [phone], 'comment': comment or ''})
101
+ if self.reg_name:
102
+ for name, comment in self.reg_name.items():
103
+ to_return.append({'type': 'whois-registrant-name', 'values': [name], 'comment': comment or ''})
104
+ if self.registrar:
105
+ for reg, comment in self.registrar.items():
106
+ to_return.append({'type': 'whois-registrar', 'values': [reg], 'comment': comment or ''})
107
+ if self.creation_date:
108
+ for date, comment in self.creation_date.items():
109
+ to_return.append({'type': 'whois-creation-date', 'values': [date], 'comment': comment or ''})
110
+ if self.domain_ip:
111
+ for ip, comment in self.domain_ip.items():
112
+ to_return.append({'types': ['ip-dst', 'ip-src'], 'values': [ip], 'comment': comment or ''})
113
+ if self.domain:
114
+ for domain, comment in self.domain.items():
115
+ to_return.append({'type': 'domain', 'values': [domain], 'comment': comment or ''})
116
+ if self.freetext:
117
+ to_return.append({'type': 'freetext', 'values': [self.freetext], 'comment': 'Freetext import'})
118
+ if self.risk:
119
+ to_return.append({'type': 'text', 'values': [self.risk[0]], 'comment': self.risk[1]})
120
+ return to_return
121
+
122
+
123
+ def parsed_whois(domtools, to_query, values):
124
+ whois_entry = domtools.parsed_whois(to_query)
125
+ if whois_entry.get('error'):
126
+ misperrors['error'] = whois_entry['error']['message']
127
+ return misperrors
128
+
129
+ if whois_entry.get('registrant'):
130
+ values.add_name(whois_entry['registrant'], 'Parsed registrant')
131
+
132
+ if whois_entry.get('registration'):
133
+ values.add_creation_date(whois_entry['registration']['created'], 'timestamp')
134
+
135
+ if whois_entry.get('whois'):
136
+ values.freetext = whois_entry['whois']['record']
137
+ if whois_entry.get('parsed_whois'):
138
+ if whois_entry['parsed_whois']['created_date']:
139
+ values.add_creation_date(whois_entry['parsed_whois']['created_date'], 'created')
140
+ if whois_entry['parsed_whois']['registrar']['name']:
141
+ values.add_registrar(whois_entry['parsed_whois']['registrar']['name'], 'name')
142
+ if whois_entry['parsed_whois']['registrar']['url']:
143
+ values.add_registrar(whois_entry['parsed_whois']['registrar']['url'], 'url')
144
+ if whois_entry['parsed_whois']['registrar']['iana_id']:
145
+ values.add_registrar(whois_entry['parsed_whois']['registrar']['iana_id'], 'iana_id')
146
+ for key, entry in whois_entry['parsed_whois']['contacts'].items():
147
+ if entry['email']:
148
+ values.add_mail(entry['email'], key)
149
+ if entry['phone']:
150
+ values.add_phone(entry['phone'], key)
151
+ if entry['name']:
152
+ values.add_name(entry['name'], key)
153
+ if whois_entry.emails():
154
+ for mail in whois_entry.emails():
155
+ if mail not in values.reg_mail.keys():
156
+ values.add_mail(mail, 'Maybe registrar')
157
+ return values
158
+
159
+
160
+ def domain_profile(domtools, to_query, values):
161
+ profile = domtools.domain_profile(to_query)
162
+ # NOTE: profile['website_data']['response_code'] could be used to see if the host is still up. Maybe set a tag.
163
+ if profile.get('error'):
164
+ misperrors['error'] = profile['error']['message']
165
+ return misperrors
166
+
167
+ if profile.get('registrant'):
168
+ values.add_name(profile['registrant']['name'], 'Profile registrant')
169
+
170
+ if profile.get('server'):
171
+ other_domains = profile['server']['other_domains']
172
+ values.add_ip(profile['server']['ip_address'], 'IP of {} (via DomainTools). Has {} other domains.'.format(to_query, other_domains))
173
+
174
+ if profile.get('registration'):
175
+ if profile['registration'].get('created'):
176
+ values.add_creation_date(profile['registration']['created'], 'created')
177
+ if profile['registration'].get('updated'):
178
+ values.add_creation_date(profile['registration']['updated'], 'updated')
179
+ if profile['registration'].get('registrar'):
180
+ values.add_registrar(profile['registration']['registrar'], 'name')
181
+ return values
182
+
183
+
184
+ def reputation(domtools, to_query, values):
185
+ rep = domtools.reputation(to_query, include_reasons=True)
186
+ # NOTE: use that value in a tag when we will have attribute level tagging
187
+ if rep and not rep.get('error'):
188
+ reasons = ', '.join(rep['reasons'])
189
+ values.risk = [rep['risk_score'], 'Risk value of {} (via Domain Tools), Reasons: {}'.format(to_query, reasons)]
190
+ return values
191
+
192
+
193
+ def reverse_ip(domtools, to_query, values):
194
+ rev_ip = domtools.reverse_ip(to_query)
195
+ if rev_ip and not rev_ip.get('error'):
196
+ ip_addresses = rev_ip['ip_addresses']
197
+ values.add_ip(ip_addresses['ip_address'], 'IP of {} (via DomainTools). Has {} other domains.'.format(to_query, ip_addresses['domain_count']))
198
+ for d in ip_addresses['domain_names']:
199
+ values.add_domain(d, 'Other domain on {}.'.format(ip_addresses['ip_address']))
200
+ return values
201
+
202
+
203
+ def reverse_whois(domtools, to_query, values):
204
+ rev_whois = domtools.reverse_whois(to_query, mode='purchase')
205
+ if rev_whois.get('error'):
206
+ misperrors['error'] = rev_whois['error']['message']
207
+ return misperrors
208
+ for d in rev_whois['domains']:
209
+ values.add_domain(d, 'Reverse domain related to {}.'.format(to_query))
210
+ return values
211
+
212
+
213
+ def host_domains(domtools, to_query, values):
214
+ hostdom = domtools.host_domains(to_query)
215
+ if hostdom.get('error'):
216
+ misperrors['error'] = hostdom['error']['message']
217
+ return misperrors
218
+ ip_addresses = hostdom['ip_addresses']
219
+ if to_query != ip_addresses['ip_address']:
220
+ values.add_ip(ip_addresses['ip_address'], 'IP of {} (via DomainTools). Has {} other domains.'.format(to_query, ip_addresses['domain_count']))
221
+ for d in ip_addresses['domain_names']:
222
+ values.add_domain(d, 'Other domain on {}.'.format(ip_addresses['ip_address']))
223
+ return values
224
+
225
+
226
+ def reverse_ip_whois(domtools, to_query, values):
227
+ # Disabled for now, dies with domaintools.exceptions.NotAuthorizedException
228
+ rev_whois = domtools.reverse_ip_whois(ip=to_query)
229
+ print(rev_whois)
230
+ if rev_whois.get('error'):
231
+ misperrors['error'] = rev_whois['error']['message']
232
+ return misperrors
233
+ # for d in rev_whois['domains']:
234
+ # values.add_domain(d, 'Reverse domain related to {}.'.format(to_query))
235
+ return values
236
+
237
+
238
+ def get_services(request):
239
+ for t in mispattributes['input']:
240
+ to_query = request.get(t)
241
+ if not to_query:
242
+ continue
243
+ for p in query_profiles:
244
+ if t in p['inputs']:
245
+ return p['services']
246
+
247
+
248
+ def handler(q=False):
249
+ if not q:
250
+ return q
251
+
252
+ request = json.loads(q)
253
+ to_query = None
254
+ for t in mispattributes['input']:
255
+ to_query = request.get(t)
256
+ if to_query:
257
+ break
258
+ if not to_query:
259
+ misperrors['error'] = "Unsupported attributes type"
260
+ return misperrors
261
+
262
+ if request.get('config'):
263
+ if (request['config'].get('username') is None) or (request['config'].get('api_key') is None):
264
+ misperrors['error'] = 'DomainTools authentication is incomplete'
265
+ return misperrors
266
+ else:
267
+ domtools = API(request['config'].get('username'), request['config'].get('api_key'))
268
+ else:
269
+ misperrors['error'] = 'DomainTools authentication is missing'
270
+ return misperrors
271
+
272
+ values = DomainTools()
273
+ services = get_services(request)
274
+ if services:
275
+ try:
276
+ for s in services:
277
+ globals()[s](domtools, to_query, values)
278
+ except Exception as e:
279
+ print(to_query, type(e), e)
280
+
281
+ return {'results': values.dump()}
282
+
283
+
284
+ def introspection():
285
+ return mispattributes
286
+
287
+
288
+ def version():
289
+ moduleinfo['config'] = moduleconfig
290
+ return moduleinfo
@@ -0,0 +1,91 @@
1
+ """
2
+ Export module for converting MISP events into Endgame EQL queries
3
+ """
4
+ import json
5
+ import logging
6
+
7
+ misperrors = {"error": "Error"}
8
+
9
+ moduleinfo = {
10
+ 'version': '0.1',
11
+ 'author': '92 COS DOM',
12
+ 'description': 'EQL query generation for a MISP attribute.',
13
+ 'module-type': ['expansion'],
14
+ 'name': 'EQL Query Generator',
15
+ 'logo': 'eql.png',
16
+ 'requirements': [],
17
+ 'features': 'This module adds a new attribute to a MISP event containing an EQL query for a network or file attribute.',
18
+ 'references': ['https://eql.readthedocs.io/en/latest/'],
19
+ 'input': 'A filename or ip attribute.',
20
+ 'output': 'Attribute containing EQL for a network or file attribute.',
21
+ }
22
+
23
+ # Map of MISP fields => Endgame fields
24
+ fieldmap = {
25
+ "ip-src": "source_address",
26
+ "ip-dst": "destination_address",
27
+ "filename": "file_name"
28
+ }
29
+
30
+ # Describe what events have what fields
31
+ event_types = {
32
+ "source_address": "network",
33
+ "destination_address": "network",
34
+ "file_name": "file"
35
+ }
36
+
37
+ # combine all the MISP fields from fieldmap into one big list
38
+ mispattributes = {
39
+ "input": list(fieldmap.keys())
40
+ }
41
+
42
+
43
+ def handler(q=False):
44
+ """
45
+ Convert a MISP query into a CSV file matching the ThreatConnect Structured Import file format.
46
+ Input
47
+ q: Query dictionary
48
+ """
49
+ if q is False or not q:
50
+ return False
51
+
52
+ # Check if we were given a configuration
53
+ request = json.loads(q)
54
+ config = request.get("config", {"Default_Source": ""})
55
+ logging.info("Setting config to: %s", config)
56
+
57
+ for supportedType in fieldmap.keys():
58
+ if request.get(supportedType):
59
+ attrType = supportedType
60
+
61
+ if attrType:
62
+ eqlType = fieldmap[attrType]
63
+ event_type = event_types[eqlType]
64
+ fullEql = "{} where {} == \"{}\"".format(event_type, eqlType, request[attrType])
65
+ else:
66
+ misperrors['error'] = "Unsupported attributes type"
67
+ return misperrors
68
+
69
+ response = []
70
+ response.append({'types': ['comment'], 'categories': ['External analysis'], 'values': fullEql, 'comment': "Event EQL queries"})
71
+ return {'results': response}
72
+
73
+
74
+ def introspection():
75
+ """
76
+ Relay the supported attributes to MISP.
77
+ No Input
78
+ Output
79
+ Dictionary of supported MISP attributes
80
+ """
81
+ return mispattributes
82
+
83
+
84
+ def version():
85
+ """
86
+ Relay module version and associated metadata to MISP.
87
+ No Input
88
+ Output
89
+ moduleinfo: metadata output containing all potential configuration values
90
+ """
91
+ return moduleinfo
@@ -0,0 +1,86 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ import json
4
+ from pyeupi import PyEUPI
5
+
6
+ misperrors = {'error': 'Error'}
7
+ mispattributes = {'input': ['hostname', 'domain', 'url'], 'output': ['freetext']}
8
+ moduleinfo = {
9
+ 'version': '0.1',
10
+ 'author': 'Raphaël Vinot',
11
+ 'description': 'A module to query the Phishing Initiative service (https://phishing-initiative.lu).',
12
+ 'module-type': ['expansion', 'hover'],
13
+ 'name': 'EUPI Lookup',
14
+ 'logo': 'eupi.png',
15
+ 'requirements': ['pyeupi: eupi python library', 'An access to the Phishing Initiative API (apikey & url)'],
16
+ 'features': 'This module takes a domain, hostname or url MISP attribute as input to query the Phishing Initiative API. The API returns then the result of the query with some information about the value queried.\n\nPlease note that composite attributes containing domain or hostname are also supported.',
17
+ 'references': ['https://phishing-initiative.eu/?lang=en'],
18
+ 'input': 'A domain, hostname or url MISP attribute.',
19
+ 'output': 'Text containing information about the input, resulting from the query on Phishing Initiative.',
20
+ }
21
+
22
+ moduleconfig = ['apikey', 'url']
23
+
24
+
25
+ def handler(q=False):
26
+ if q is False:
27
+ return False
28
+ request = json.loads(q)
29
+ if request.get('hostname'):
30
+ toquery = request['hostname']
31
+ elif request.get('domain'):
32
+ toquery = request['domain']
33
+ elif request.get('url'):
34
+ toquery = request['url']
35
+ else:
36
+ misperrors['error'] = "Unsupported attributes type"
37
+ return misperrors
38
+
39
+ if not request.get('config') and not (request['config'].get('apikey') and request['config'].get('url')):
40
+ misperrors['error'] = 'EUPI authentication is missing'
41
+ return misperrors
42
+
43
+ pyeupi = PyEUPI(request['config']['apikey'], request['config']['url'])
44
+
45
+ if 'event_id' in request:
46
+ return handle_expansion(pyeupi, toquery)
47
+ else:
48
+ return handle_hover(pyeupi, toquery)
49
+
50
+
51
+ def handle_expansion(pyeupi, url):
52
+ results = pyeupi.search_url(url=url)
53
+
54
+ if results.get('results'):
55
+ to_return = ''
56
+ for r in results['results']:
57
+ if r['tag_label'] != 'phishing':
58
+ continue
59
+ to_return += ' {} {} {} '.format(r['url'], r['domain'], r['ip_address'])
60
+ if to_return:
61
+ return {'results': [{'types': mispattributes['output'], 'values': to_return}]}
62
+ else:
63
+ misperrors['error'] = 'Unknown in the EUPI service'
64
+ return misperrors
65
+ else:
66
+ return {'results': [{'types': mispattributes['output'], 'values': ''}]}
67
+
68
+
69
+ def handle_hover(pyeupi, url):
70
+ try:
71
+ result = pyeupi.lookup(url=url)['results'][0]
72
+ except (KeyError, IndexError):
73
+ misperrors['error'] = 'Error in EUPI lookup'
74
+ return misperrors
75
+
76
+ return {'results': [{'types': mispattributes['output'],
77
+ 'values': result['tag_label'].title()}]}
78
+
79
+
80
+ def introspection():
81
+ return mispattributes
82
+
83
+
84
+ def version():
85
+ moduleinfo['config'] = moduleconfig
86
+ return moduleinfo
@@ -0,0 +1,83 @@
1
+ import json
2
+ from pymisp import MISPEvent, MISPObject
3
+ from . import check_input_attribute, standard_error_message
4
+ from pyfaup.faup import Faup
5
+
6
+ misperrors = {'error': 'Error'}
7
+ mispattributes = {'input': ['url'], 'format': 'misp_standard'}
8
+ moduleinfo = {
9
+ 'version': '1',
10
+ 'author': 'MISP Team',
11
+ 'description': 'Extract URL components',
12
+ 'module-type': ['expansion', 'hover'],
13
+ 'name': 'URL Components Extractor',
14
+ 'logo': '',
15
+ 'requirements': [],
16
+ 'features': '',
17
+ 'references': [],
18
+ 'input': '',
19
+ 'output': '',
20
+ }
21
+ moduleconfig = []
22
+
23
+
24
+ def createObjectFromURL(url):
25
+ f = Faup()
26
+ f.decode(url)
27
+ parsed = f.get()
28
+ obj = MISPObject('url')
29
+ obj.add_attribute('url', type='url', value=url)
30
+ if parsed['tld'] is not None:
31
+ obj.add_attribute('tld', type='text', value=parsed['tld'])
32
+ if parsed['subdomain'] is not None:
33
+ obj.add_attribute('subdomain', type='text', value=parsed['subdomain'])
34
+ obj.add_attribute('scheme', type='text', value=parsed['scheme'])
35
+ if parsed['resource_path'] is not None:
36
+ obj.add_attribute('resource_path', type='text', value=parsed['resource_path'])
37
+ if parsed['query_string'] is not None:
38
+ obj.add_attribute('query_string', type='text', value=parsed['query_string'])
39
+ if parsed['port'] is not None:
40
+ obj.add_attribute('port', type='port', value=parsed['port'])
41
+ obj.add_attribute('host', type='hostname', value=parsed['host'])
42
+ if parsed['fragment'] is not None:
43
+ obj.add_attribute('fragment', type='text', value=parsed['fragment'])
44
+ obj.add_attribute('domain_without_tld', type='text', value=parsed['domain_without_tld'])
45
+ obj.add_attribute('domain', type='domain', value=parsed['domain'])
46
+ return obj
47
+
48
+
49
+ def createEvent(urlObject, attributeUUID, urlAttribute):
50
+ mispEvent = MISPEvent()
51
+ mispEvent.add_attribute(**urlAttribute)
52
+ urlObject.add_reference(attributeUUID, 'generated-from')
53
+ mispEvent.add_object(urlObject)
54
+ return mispEvent
55
+
56
+ def handler(q=False):
57
+ if q is False:
58
+ return False
59
+ request = json.loads(q)
60
+ if not request.get('attribute') or not check_input_attribute(request['attribute']):
61
+ return {'error': f'{standard_error_message}, which should contain at least a type, a value and an uuid.'}
62
+ attribute = request['attribute']
63
+
64
+ if attribute['type'] not in mispattributes['input']:
65
+ return {'error': 'Bad attribute type'}
66
+
67
+ url = attribute['value']
68
+ urlObject = createObjectFromURL(url)
69
+
70
+ event = createEvent(urlObject, attribute['uuid'], attribute)
71
+ event = json.loads(event.to_json())
72
+
73
+ result = {'results': {'Object': event['Object']}}
74
+ return result
75
+
76
+
77
+ def introspection():
78
+ return mispattributes
79
+
80
+
81
+ def version():
82
+ moduleinfo['config'] = moduleconfig
83
+ return moduleinfo