mihari 4.5.1 → 4.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/lib/mihari/analyzers/rule.rb +6 -3
  3. data/lib/mihari/emitters/the_hive.rb +69 -10
  4. data/lib/mihari/emitters/webhook.rb +1 -1
  5. data/lib/mihari/schemas/emitter.rb +1 -0
  6. data/lib/mihari/structs/rule.rb +3 -0
  7. data/lib/mihari/version.rb +1 -1
  8. data/lib/mihari/web/endpoints/rules.rb +2 -1
  9. data/lib/mihari/web/public/index.html +1 -1
  10. data/lib/mihari/web/public/redoc-static.html +317 -314
  11. data/lib/mihari/web/public/static/css/{chunk-vendors.da2a7bfc.css → chunk-vendors.06251949.css} +2 -2
  12. data/lib/mihari/web/public/static/fonts/{fa-brands-400.f7223235.ttf → fa-brands-400.7fa789ab.ttf} +0 -0
  13. data/lib/mihari/web/public/static/fonts/fa-brands-400.859fc388.woff2 +0 -0
  14. data/lib/mihari/web/public/static/fonts/fa-regular-400.2ffd018f.woff2 +0 -0
  15. data/lib/mihari/web/public/static/fonts/{fa-regular-400.a7fde52b.ttf → fa-regular-400.da02cb7e.ttf} +0 -0
  16. data/lib/mihari/web/public/static/fonts/{fa-solid-900.5b03221c.ttf → fa-solid-900.3a463ec3.ttf} +0 -0
  17. data/lib/mihari/web/public/static/fonts/fa-solid-900.40ddefd7.woff2 +0 -0
  18. data/lib/mihari/web/public/static/fonts/{fa-v4compatibility.42932bea.ttf → fa-v4compatibility.924588dc.ttf} +0 -0
  19. data/lib/mihari/web/public/static/js/app-legacy.9d5c9c3d.js +2 -0
  20. data/lib/mihari/web/public/static/js/app-legacy.9d5c9c3d.js.map +1 -0
  21. data/lib/mihari/web/public/static/js/app.823b5af7.js +2 -0
  22. data/lib/mihari/web/public/static/js/app.823b5af7.js.map +1 -0
  23. data/lib/mihari/web/public/static/js/chunk-vendors-legacy.b110c129.js +25 -0
  24. data/lib/mihari/web/public/static/js/chunk-vendors-legacy.b110c129.js.map +1 -0
  25. data/lib/mihari/web/public/static/js/chunk-vendors.dde2116c.js +31 -0
  26. data/lib/mihari/web/public/static/js/chunk-vendors.dde2116c.js.map +1 -0
  27. data/lib/mihari.rb +49 -28
  28. data/mihari.gemspec +7 -8
  29. data/sig/lib/mihari/emitters/the_hive.rbs +4 -0
  30. data/sig/lib/mihari.rbs +1 -0
  31. metadata +32 -46
  32. data/lib/mihari/web/public/static/fonts/fa-brands-400.edf40f86.woff2 +0 -0
  33. data/lib/mihari/web/public/static/fonts/fa-regular-400.3665ebc7.woff2 +0 -0
  34. data/lib/mihari/web/public/static/fonts/fa-solid-900.0d2abd43.woff2 +0 -0
  35. data/lib/mihari/web/public/static/js/app-legacy.c3595dce.js +0 -2
  36. data/lib/mihari/web/public/static/js/app-legacy.c3595dce.js.map +0 -1
  37. data/lib/mihari/web/public/static/js/app.afd5025f.js +0 -2
  38. data/lib/mihari/web/public/static/js/app.afd5025f.js.map +0 -1
  39. data/lib/mihari/web/public/static/js/chunk-vendors-legacy.d6b76c57.js +0 -25
  40. data/lib/mihari/web/public/static/js/chunk-vendors-legacy.d6b76c57.js.map +0 -1
  41. data/lib/mihari/web/public/static/js/chunk-vendors.3bdbaffb.js +0 -31
  42. data/lib/mihari/web/public/static/js/chunk-vendors.3bdbaffb.js.map +0 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dd4057ff69b6e8ee676c7ebf7e672b6830d26a02e22ebe372d2786f5220ae8d3
4
- data.tar.gz: 202c7bce234c823fb10fe40fc1f7af2c25d676f587871d0a49740fd8f3af4325
3
+ metadata.gz: 1f340898bd140d76041cde8c5cb266bcb379f056bac511fcd9de9a4dd20fc299
4
+ data.tar.gz: fb96310ecb6efb1dd5059feea692a8128bdff3610579473134653979c2f0512c
5
5
  SHA512:
6
- metadata.gz: ed3c42b58a305f20e7d981a1ae5e19d6efe493d7252645cf54f78c16fe38607305497e983f80d1d04ab8964f0166f19ace1ba62bece5ecdeadb0b6041d4be49f
7
- data.tar.gz: 12966b0cc1143bcff8e9a44dd5904c7fa70c234f26613df35e5be162c5e18805e15adb1a8fd1ddd8c1ad84d221b528d411daa29b764e67eed4357a86f6bf0cc7
6
+ metadata.gz: 8d9758d027fc056f52be261fb2d7c6fa81dc402d4f47c01a8e49c93e1bc084a501af74c0e51c73ac2967c7795529130f1c34801661f1a9935075e197eaf446b0
7
+ data.tar.gz: e48d29aa3756a260cc273f9b05e65aa28e6e9e67f377fcc9c4ff722931f7789f363478c9a33470aea41a1bd72a9c9e73c05b76583d52bdb80096c2fdaf627b54
@@ -127,9 +127,12 @@ module Mihari
127
127
  # @return [Boolean]
128
128
  #
129
129
  def disallowed_data_value?(value)
130
- normalized_disallowed_data_values.any? do |disallowed_data_value|
131
- return value == disallowed_data_value if disallowed_data_value.is_a?(String)
132
- return disallowed_data_value.match?(value) if disallowed_data_value.is_a?(Regexp)
130
+ return true if normalized_disallowed_data_values.include?(value)
131
+
132
+ normalized_disallowed_data_values.select do |disallowed_data_value|
133
+ disallowed_data_value.is_a?(Regexp)
134
+ end.any? do |disallowed_data_value|
135
+ disallowed_data_value.match?(value)
133
136
  end
134
137
  end
135
138
 
@@ -11,11 +11,15 @@ module Mihari
11
11
  # @return [String, nil]
12
12
  attr_reader :api_key
13
13
 
14
+ # @return [String, nil]
15
+ attr_reader :api_version
16
+
14
17
  def initialize(*args, **kwargs)
15
18
  super(*args, **kwargs)
16
19
 
17
20
  @api_endpoint = kwargs[:api_endpoint] || Mihari.config.thehive_api_endpoint
18
21
  @api_key = kwargs[:api_key] || Mihari.config.thehive_api_key
22
+ @api_version = kwargs[:api_version] || Mihari.config.thehive_api_version
19
23
  end
20
24
 
21
25
  # @return [Boolean]
@@ -26,14 +30,28 @@ module Mihari
26
30
  def emit(title:, description:, artifacts:, tags: [], **_options)
27
31
  return if artifacts.empty?
28
32
 
29
- api.alert.create(
30
- title: title,
31
- description: description,
32
- artifacts: artifacts.map { |artifact| { data: artifact.data, data_type: artifact.data_type, message: description } },
33
- tags: tags,
34
- type: "external",
35
- source: "mihari"
36
- )
33
+ payload = payload(title: title, description: description, artifacts: artifacts, tags: tags)
34
+ api.alert.create(**payload)
35
+ end
36
+
37
+ #
38
+ # Normalize API version for API client
39
+ #
40
+ # @param [String] version
41
+ #
42
+ # @return [String, nil]
43
+ #
44
+ def normalized_api_version
45
+ @normalized_api_version ||= [].tap do |out|
46
+ # v4 does not have version prefix in path (/api/)
47
+ # v5 has version prefix in path (/api/v1/)
48
+ table = {
49
+ "" => nil,
50
+ "v4" => nil,
51
+ "v5" => "v1"
52
+ }
53
+ out << table[api_version.to_s.downcase]
54
+ end.first
37
55
  end
38
56
 
39
57
  private
@@ -43,7 +61,7 @@ module Mihari
43
61
  end
44
62
 
45
63
  def api
46
- @api ||= Hachi::API.new(api_endpoint: api_endpoint, api_key: api_key)
64
+ @api ||= Hachi::API.new(api_endpoint: api_endpoint, api_key: api_key, api_version: normalized_api_version)
47
65
  end
48
66
 
49
67
  #
@@ -64,6 +82,35 @@ module Mihari
64
82
  !api_key.nil?
65
83
  end
66
84
 
85
+ def payload(title:, description:, artifacts:, tags: [])
86
+ return v4_payload(title: title, description: description, artifacts: artifacts, tags: tags) if normalized_api_version.nil?
87
+
88
+ v5_payload(title: title, description: description, artifacts: artifacts, tags: tags)
89
+ end
90
+
91
+ def v4_payload(title:, description:, artifacts:, tags: [])
92
+ {
93
+ title: title,
94
+ description: description,
95
+ artifacts: artifacts.map { |artifact| { data: artifact.data, data_type: artifact.data_type, message: description } },
96
+ tags: tags,
97
+ type: "external",
98
+ source: "mihari"
99
+ }
100
+ end
101
+
102
+ def v5_payload(title:, description:, artifacts:, tags: [])
103
+ {
104
+ title: title,
105
+ description: description,
106
+ observables: artifacts.map { |artifact| { data: artifact.data, data_type: artifact.data_type, message: description } },
107
+ tags: tags,
108
+ type: "external",
109
+ source: "mihari",
110
+ source_ref: "1"
111
+ }
112
+ end
113
+
67
114
  #
68
115
  # Check whether an API endpoint is reachable or not
69
116
  #
@@ -71,9 +118,21 @@ module Mihari
71
118
  #
72
119
  def ping?
73
120
  base_url = api_endpoint.end_with?("/") ? api_endpoint[0..-2] : api_endpoint
74
- url = "#{base_url}/index.html"
121
+
122
+ if normalized_api_version.nil?
123
+ # for v4
124
+ base_url = api_endpoint.end_with?("/") ? api_endpoint[0..-2] : api_endpoint
125
+ url = "#{base_url}/index.html"
126
+ else
127
+ # for v5
128
+ url = "#{base_url}/api/v1/status/public"
129
+ end
75
130
 
76
131
  http = Net::Ping::HTTP.new(url)
132
+
133
+ # use GET for v5
134
+ http.get_request = true if normalized_api_version
135
+
77
136
  http.ping?
78
137
  end
79
138
  end
@@ -11,7 +11,7 @@ module Mihari
11
11
  def emit(title:, description:, artifacts:, source:, tags:)
12
12
  return if artifacts.empty?
13
13
 
14
- headers = { 'content-type': "application/x-www-form-urlencoded" }
14
+ headers = { "content-type": "application/x-www-form-urlencoded" }
15
15
  headers["content-type"] = "application/json" if use_json_body?
16
16
 
17
17
  emitter = Emitters::HTTP.new(uri: Mihari.config.webhook_url)
@@ -16,6 +16,7 @@ module Mihari
16
16
  required(:emitter).value(Types::String.enum("the_hive"))
17
17
  optional(:api_endpoint).value(:string)
18
18
  optional(:api_key).value(:string)
19
+ optional(:api_version).value(Types::String.enum("v4", "v5")).default("v4")
19
20
  end
20
21
 
21
22
  Slack = Dry::Schema.Params do
@@ -36,6 +36,9 @@ module Mihari
36
36
  # @return [Array, nil]
37
37
  attr_reader :errors
38
38
 
39
+ # @return [String]
40
+ attr_writer :id
41
+
39
42
  def initialize(data, yaml)
40
43
  @data = data.deep_symbolize_keys
41
44
  @yaml = yaml
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Mihari
4
- VERSION = "4.5.1"
4
+ VERSION = "4.6.0"
5
5
  end
@@ -145,6 +145,7 @@ module Mihari
145
145
  end
146
146
 
147
147
  rule = Structs::Rule::Rule.from_yaml(yaml)
148
+ rule.id = id
148
149
 
149
150
  begin
150
151
  rule.validate!
@@ -159,7 +160,7 @@ module Mihari
159
160
  model = rule.to_model
160
161
  model.save
161
162
  rescue ActiveRecord::RecordNotUnique
162
- error!({ message: "ID:#{rule.id} is already registered" }, 400)
163
+ error!({ message: "ID:#{model.id} is already registered" }, 400)
163
164
  end
164
165
 
165
166
  status 201
@@ -1 +1 @@
1
- <!doctype html><html lang="en"><head><meta charset="utf-8"/><meta http-equiv="X-UA-Compatible" content="IE=edge"/><meta name="viewport" content="width=device-width,initial-scale=1"/><link rel="icon" href="/static/favicon.ico"/><title>Mihari</title><script defer="defer" type="module" src="/static/js/chunk-vendors.3bdbaffb.js"></script><script defer="defer" type="module" src="/static/js/app.afd5025f.js"></script><link href="/static/css/chunk-vendors.da2a7bfc.css" rel="stylesheet"><link href="/static/css/app.2a5d3d21.css" rel="stylesheet"><script defer="defer" src="/static/js/chunk-vendors-legacy.d6b76c57.js" nomodule></script><script defer="defer" src="/static/js/app-legacy.c3595dce.js" nomodule></script></head><body><noscript><strong>We're sorry but Mihari doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div></body></html>
1
+ <!doctype html><html lang="en"><head><meta charset="utf-8"/><meta http-equiv="X-UA-Compatible" content="IE=edge"/><meta name="viewport" content="width=device-width,initial-scale=1"/><link rel="icon" href="/static/favicon.ico"/><title>Mihari</title><script defer="defer" type="module" src="/static/js/chunk-vendors.dde2116c.js"></script><script defer="defer" type="module" src="/static/js/app.823b5af7.js"></script><link href="/static/css/chunk-vendors.06251949.css" rel="stylesheet"><link href="/static/css/app.2a5d3d21.css" rel="stylesheet"><script defer="defer" src="/static/js/chunk-vendors-legacy.b110c129.js" nomodule></script><script defer="defer" src="/static/js/app-legacy.9d5c9c3d.js" nomodule></script></head><body><noscript><strong>We're sorry but Mihari doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div></body></html>