mihari 5.3.0 → 5.3.2

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 (62) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +8 -2
  3. data/frontend/package-lock.json +657 -576
  4. data/frontend/package.json +23 -20
  5. data/frontend/src/ace-config.ts +6 -0
  6. data/frontend/src/components/Loading.vue +1 -1
  7. data/frontend/src/components/alert/Alert.vue +1 -1
  8. data/frontend/src/components/alert/AlertsWrapper.vue +1 -1
  9. data/frontend/src/components/alert/Form.vue +2 -2
  10. data/frontend/src/components/artifact/Artifact.vue +3 -3
  11. data/frontend/src/components/config/Configs.vue +2 -2
  12. data/frontend/src/components/rule/EditRule.vue +4 -3
  13. data/frontend/src/components/rule/Form.vue +2 -2
  14. data/frontend/src/components/rule/InputForm.vue +18 -59
  15. data/frontend/src/components/rule/NewRule.vue +1 -1
  16. data/frontend/src/components/rule/Rule.vue +3 -3
  17. data/frontend/src/components/rule/RulesWrapper.vue +1 -1
  18. data/frontend/src/components/rule/YAML.vue +21 -28
  19. data/frontend/src/main.ts +33 -3
  20. data/frontend/src/views/Artifact.vue +3 -8
  21. data/frontend/src/views/EditRule.vue +2 -7
  22. data/frontend/src/views/Rule.vue +3 -8
  23. data/lib/mihari/analyzers/base.rb +6 -0
  24. data/lib/mihari/analyzers/binaryedge.rb +1 -1
  25. data/lib/mihari/analyzers/censys.rb +1 -1
  26. data/lib/mihari/analyzers/onyphe.rb +1 -1
  27. data/lib/mihari/analyzers/rule.rb +4 -7
  28. data/lib/mihari/analyzers/shodan.rb +1 -1
  29. data/lib/mihari/analyzers/urlscan.rb +1 -1
  30. data/lib/mihari/analyzers/virustotal_intelligence.rb +1 -1
  31. data/lib/mihari/analyzers/zoomeye.rb +2 -2
  32. data/lib/mihari/commands/rule.rb +3 -3
  33. data/lib/mihari/commands/search.rb +3 -3
  34. data/lib/mihari/constants.rb +3 -0
  35. data/lib/mihari/emitters/base.rb +2 -2
  36. data/lib/mihari/emitters/misp.rb +3 -3
  37. data/lib/mihari/emitters/slack.rb +1 -1
  38. data/lib/mihari/emitters/the_hive.rb +1 -1
  39. data/lib/mihari/emitters/webhook.rb +1 -1
  40. data/lib/mihari/mixins/configurable.rb +5 -0
  41. data/lib/mihari/mixins/falsepositive.rb +1 -1
  42. data/lib/mihari/mixins/retriable.rb +0 -2
  43. data/lib/mihari/{structs → services}/rule.rb +16 -16
  44. data/lib/mihari/version.rb +1 -1
  45. data/lib/mihari/web/endpoints/rules.rb +9 -8
  46. data/lib/mihari/web/public/assets/index-116033d0.js +1737 -0
  47. data/lib/mihari/web/public/assets/index-33165282.css +1 -0
  48. data/lib/mihari/web/public/assets/mode-yaml-a21faa53.js +8 -0
  49. data/lib/mihari/web/public/index.html +2 -2
  50. data/lib/mihari.rb +3 -2
  51. data/mihari.gemspec +5 -4
  52. metadata +15 -21
  53. data/lib/mihari/web/public/assets/fa-brands-400-20c4a58b.ttf +0 -0
  54. data/lib/mihari/web/public/assets/fa-brands-400-74833209.woff2 +0 -0
  55. data/lib/mihari/web/public/assets/fa-regular-400-528d022d.ttf +0 -0
  56. data/lib/mihari/web/public/assets/fa-regular-400-8e7e5ea1.woff2 +0 -0
  57. data/lib/mihari/web/public/assets/fa-solid-900-67a65763.ttf +0 -0
  58. data/lib/mihari/web/public/assets/fa-solid-900-7152a693.woff2 +0 -0
  59. data/lib/mihari/web/public/assets/fa-v4compatibility-0515a423.ttf +0 -0
  60. data/lib/mihari/web/public/assets/fa-v4compatibility-694a17c3.woff2 +0 -0
  61. data/lib/mihari/web/public/assets/index-2ba8f0a6.css +0 -5
  62. data/lib/mihari/web/public/assets/index-71285b15.js +0 -50
@@ -37,14 +37,14 @@ module Mihari
37
37
  class Rule
38
38
  include Mixins::FalsePositive
39
39
 
40
- # @return [Mihari::Structs::Rule]
40
+ # @return [Mihari::Services::Rule]
41
41
  attr_reader :rule
42
42
 
43
43
  # @return [Time]
44
44
  attr_reader :base_time
45
45
 
46
46
  #
47
- # @param [Mihari::Structs::Rule] rule
47
+ # @param [Mihari::Services::Rule] rule
48
48
  #
49
49
  def initialize(rule)
50
50
  @rule = rule
@@ -146,11 +146,8 @@ module Mihari
146
146
  def falsepositive?(value)
147
147
  return true if rule.falsepositives.include?(value)
148
148
 
149
- rule.falsepositives.select do |falsepositive|
150
- falsepositive.is_a?(Regexp)
151
- end.any? do |falseposistive|
152
- falseposistive.match?(value)
153
- end
149
+ regexps = rule.falsepositives.select { |fp| fp.is_a?(Regexp) }
150
+ regexps.any? { |fp| fp.match?(value) }
154
151
  end
155
152
 
156
153
  #
@@ -60,7 +60,7 @@ module Mihari
60
60
  break if res.total <= page * PAGE_SIZE
61
61
 
62
62
  # sleep #{interval} seconds to avoid the rate limitation (if it is set)
63
- sleep interval
63
+ sleep_interval
64
64
  rescue JSON::ParserError
65
65
  # ignore JSON::ParserError
66
66
  # ref. https://github.com/ninoseki/mihari/issues/197
@@ -77,7 +77,7 @@ module Mihari
77
77
  search_after = res.results.last.sort.join(",")
78
78
 
79
79
  # sleep #{interval} seconds to avoid the rate limitation (if it is set)
80
- sleep(interval) if interval
80
+ sleep_interval
81
81
  end
82
82
 
83
83
  responses
@@ -53,7 +53,7 @@ module Mihari
53
53
 
54
54
  cursor = response.meta.cursor
55
55
  # sleep #{interval} seconds to avoid the rate limitation (if it is set)
56
- sleep(interval) if interval
56
+ sleep_interval
57
57
  end
58
58
 
59
59
  responses
@@ -104,7 +104,7 @@ module Mihari
104
104
  break if total <= page * PAGE_SIZE
105
105
 
106
106
  # sleep #{interval} seconds to avoid the rate limitation (if it is set)
107
- sleep(interval) if interval
107
+ sleep_interval
108
108
  end
109
109
  convert_responses responses.compact
110
110
  end
@@ -137,7 +137,7 @@ module Mihari
137
137
  break if total <= page * PAGE_SIZE
138
138
 
139
139
  # sleep #{interval} seconds to avoid the rate limitation (if it is set)
140
- sleep(interval) if interval
140
+ sleep_interval
141
141
  end
142
142
  convert_responses responses.compact
143
143
  end
@@ -15,7 +15,7 @@ module Mihari
15
15
  # @param [String] path
16
16
  #
17
17
  def validate(path)
18
- rule = Structs::Rule.from_path_or_id(path)
18
+ rule = Services::Rule.from_path_or_id(path)
19
19
 
20
20
  begin
21
21
  rule.validate!
@@ -44,10 +44,10 @@ module Mihari
44
44
 
45
45
  no_commands do
46
46
  #
47
- # @return [Mihari::Structs::Rule]
47
+ # @return [Mihari::Services::Rule]
48
48
  #
49
49
  def rule_template
50
- Structs::Rule.from_path File.expand_path("../templates/rule.yml.erb", __dir__)
50
+ Services::Rule.from_path File.expand_path("../templates/rule.yml.erb", __dir__)
51
51
  end
52
52
 
53
53
  #
@@ -33,12 +33,12 @@ module Mihari
33
33
  end
34
34
 
35
35
  def update_or_create
36
- rule.model.save
36
+ rule.to_model.save
37
37
  end
38
38
 
39
39
  def run
40
40
  begin
41
- analyzer = rule.analyzer
41
+ analyzer = rule.to_analyzer
42
42
  rescue ConfigurationError => e
43
43
  # if there is a configuration error, output that error without the stack trace
44
44
  Mihari.logger.error e.to_s
@@ -69,7 +69,7 @@ module Mihari
69
69
  #
70
70
  def search(path_or_id)
71
71
  Mihari::Database.with_db_connection do
72
- rule = Structs::Rule.from_path_or_id path_or_id
72
+ rule = Services::Rule.from_path_or_id path_or_id
73
73
 
74
74
  begin
75
75
  rule.validate!
@@ -1,10 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Mihari
4
+ # @return [Array<String>]
4
5
  DEFAULT_DATA_TYPES = %w[hash ip domain url mail].freeze
5
6
 
7
+ # @return [Array<Hash>]
6
8
  DEFAULT_EMITTERS = %w[database misp slack the_hive].map { |name| { emitter: name } }.freeze
7
9
 
10
+ # @return [Array<Hash>]
8
11
  DEFAULT_ENRICHERS = %w[whois ipinfo shodan google_public_dns].map { |name| { enricher: name } }.freeze
9
12
 
10
13
  DEFAULT_RETRY_TIMES = 3
@@ -9,12 +9,12 @@ module Mihari
9
9
  # @return [Array<Mihari::Artifact>]
10
10
  attr_reader :artifacts
11
11
 
12
- # @return [Mihari::Structs::Rule]
12
+ # @return [Mihari::Services::Rule]
13
13
  attr_reader :rule
14
14
 
15
15
  #
16
16
  # @param [Array<Mihari::Artifact>] artifacts
17
- # @param [Mihari::Structs::Rule] rule
17
+ # @param [Mihari::Services::Rule] rule
18
18
  # @param [Hash] **_options
19
19
  #
20
20
  def initialize(artifacts:, rule:, **_options)
@@ -12,12 +12,12 @@ module Mihari
12
12
  # @return [Array<Mihari::Artifact>]
13
13
  attr_reader :artifacts
14
14
 
15
- # @return [Mihari::Structs::Rule]
15
+ # @return [Mihari::Services::Rule]
16
16
  attr_reader :rule
17
17
 
18
18
  #
19
19
  # @param [Array<Mihari::Artifact>] artifacts
20
- # @param [Mihari::Structs::Rule] rule
20
+ # @param [Mihari::Services::Rule] rule
21
21
  # @param [Hash] **options
22
22
  #
23
23
  def initialize(artifacts:, rule:, **options)
@@ -47,7 +47,7 @@ module Mihari
47
47
  # Create a MISP event
48
48
  #
49
49
  # @param [Arra<Mihari::Artifact>] artifacts
50
- # @param [Mihari::Structs::Rule] rule
50
+ # @param [Mihari::Services::Rule] rule
51
51
  #
52
52
  # @return [::MISP::Event]
53
53
  #
@@ -133,7 +133,7 @@ module Mihari
133
133
 
134
134
  #
135
135
  # @param [Array<Mihari::Artifact>] artifacts
136
- # @param [Mihari::Structs::Rule] rule
136
+ # @param [Mihari::Services::Rule] rule
137
137
  # @param [Hash] **_options
138
138
  #
139
139
  def initialize(artifacts:, rule:, **options)
@@ -14,7 +14,7 @@ module Mihari
14
14
 
15
15
  #
16
16
  # @param [Array<Mihari::Artifact>] artifacts
17
- # @param [Mihari::Structs::Rule] rule
17
+ # @param [Mihari::Services::Rule] rule
18
18
  # @param [Hash] **options
19
19
  #
20
20
  def initialize(artifacts:, rule:, **options)
@@ -57,7 +57,7 @@ module Mihari
57
57
 
58
58
  #
59
59
  # @param [Array<Mihari::Artifact>] artifacts
60
- # @param [Mihari::Structs::Rule] rule
60
+ # @param [Mihari::Services::Rule] rule
61
61
  # @param [Hash] **options
62
62
  #
63
63
  def initialize(artifacts:, rule:, **options)
@@ -49,6 +49,11 @@ module Mihari
49
49
 
50
50
  private
51
51
 
52
+ #
53
+ # Check whether API key is set or not
54
+ #
55
+ # @return [Boolean]
56
+ #
52
57
  def api_key?
53
58
  value = method(:api_key).call
54
59
  !value.nil?
@@ -22,7 +22,7 @@ module Mihari
22
22
  memoize :normalize_falsepositive
23
23
 
24
24
  #
25
- # Check whetehr a value is valid format as a disallowed data value
25
+ # Check whether a value is valid format as a disallowed data value
26
26
  #
27
27
  # @param [String] value Data value
28
28
  #
@@ -21,8 +21,6 @@ module Mihari
21
21
  # @param [Integer] interval
22
22
  # @param [Array<StandardError>] on
23
23
  #
24
- # @return [nil]
25
- #
26
24
  def retry_on_error(times: 3, interval: 5, on: DEFAULT_ON)
27
25
  try = 0
28
26
  begin
@@ -8,7 +8,7 @@ require "securerandom"
8
8
  require "yaml"
9
9
 
10
10
  module Mihari
11
- module Structs
11
+ module Services
12
12
  class Rule
13
13
  include Mixins::FalsePositive
14
14
 
@@ -49,16 +49,16 @@ module Mihari
49
49
  end
50
50
 
51
51
  def validate!
52
- raise RuleValidationError if errors?
53
- rescue RuleValidationError => e
52
+ return unless errors?
53
+
54
54
  Mihari.logger.error "Failed to parse the input as a rule:"
55
55
  Mihari.logger.error JSON.pretty_generate(errors.to_h)
56
56
 
57
- raise e
57
+ raise RuleValidationError, errors
58
58
  end
59
59
 
60
60
  def [](key)
61
- data[key.to_sym]
61
+ data key.to_sym
62
62
  end
63
63
 
64
64
  #
@@ -141,7 +141,7 @@ module Mihari
141
141
  #
142
142
  # @return [Mihari::Rule]
143
143
  #
144
- def model
144
+ def to_model
145
145
  rule = Mihari::Rule.find(id)
146
146
 
147
147
  rule.title = title
@@ -161,8 +161,8 @@ module Mihari
161
161
  #
162
162
  # @return [Mihari::Analyzers::Rule]
163
163
  #
164
- def analyzer
165
- Mihari::Analyzers::Rule.new(self)
164
+ def to_analyzer
165
+ Mihari::Analyzers::Rule.new self
166
166
  end
167
167
 
168
168
  class << self
@@ -171,10 +171,10 @@ module Mihari
171
171
  #
172
172
  # @param [String] yaml
173
173
  #
174
- # @return [Mihari::Structs::Rule]
174
+ # @return [Mihari::Services::Rule]
175
175
  #
176
176
  def from_yaml(yaml)
177
- Structs::Rule.new YAML.safe_load(ERB.new(yaml).result, permitted_classes: [Date, Symbol])
177
+ Services::Rule.new YAML.safe_load(ERB.new(yaml).result, permitted_classes: [Date, Symbol])
178
178
  rescue Psych::SyntaxError => e
179
179
  raise YAMLSyntaxError, e.message
180
180
  end
@@ -182,10 +182,10 @@ module Mihari
182
182
  #
183
183
  # @param [Mihari::Rule] model
184
184
  #
185
- # @return [Mihari::Structs::Rule]
185
+ # @return [Mihari::Services::Rule]
186
186
  #
187
187
  def from_model(model)
188
- Structs::Rule.new(model.data)
188
+ Services::Rule.new model.data
189
189
  end
190
190
 
191
191
  #
@@ -193,7 +193,7 @@ module Mihari
193
193
  #
194
194
  # @param [String] path
195
195
  #
196
- # @return [Mihari::Structs::Rule, nil]
196
+ # @return [Mihari::Services::Rule, nil]
197
197
  #
198
198
  def from_path(path)
199
199
  return nil unless Pathname(path).exist?
@@ -206,18 +206,18 @@ module Mihari
206
206
  #
207
207
  # @param [String] id
208
208
  #
209
- # @return [Mihari::Structs::Rule, nil]
209
+ # @return [Mihari::Services::Rule, nil]
210
210
  #
211
211
  def from_id(id)
212
212
  return nil unless Mihari::Rule.exists?(id)
213
213
 
214
- Structs::Rule.from_model Mihari::Rule.find(id)
214
+ Services::Rule.from_model Mihari::Rule.find(id)
215
215
  end
216
216
 
217
217
  #
218
218
  # @param [String] path_or_id Path to YAML file or YAML string or ID of a rule in the database
219
219
  #
220
- # @return [Mihari::Structs::Rule]
220
+ # @return [Mihari::Services::Rule]
221
221
  #
222
222
  def from_path_or_id(path_or_id)
223
223
  rule = from_path(path_or_id)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Mihari
4
- VERSION = "5.3.0"
4
+ VERSION = "5.3.2"
5
5
  end
@@ -83,12 +83,13 @@ module Mihari
83
83
  id = params["id"].to_s
84
84
 
85
85
  begin
86
- rule = Mihari::Structs::Rule.from_model(Mihari::Rule.find(id))
86
+ rule = Mihari::Services::Rule.from_model(Mihari::Rule.find(id))
87
87
  rescue ActiveRecord::RecordNotFound
88
88
  error!({ message: "ID:#{id} is not found" }, 404)
89
89
  end
90
90
 
91
- rule.analyzer.run
91
+ analyzer = rule.to_analyzer
92
+ analyzer.run
92
93
 
93
94
  status 201
94
95
  present({ message: "ID:#{id} is ran successfully" }, with: Entities::Message)
@@ -105,7 +106,7 @@ module Mihari
105
106
  yaml = params[:yaml]
106
107
 
107
108
  begin
108
- rule = Structs::Rule.from_yaml(yaml)
109
+ rule = Services::Rule.from_yaml(yaml)
109
110
  rescue YAMLSyntaxError => e
110
111
  error!({ message: e.message }, 400)
111
112
  end
@@ -128,13 +129,13 @@ module Mihari
128
129
  end
129
130
 
130
131
  begin
131
- rule.model.save
132
+ rule.to_model.save
132
133
  rescue ActiveRecord::RecordNotUnique
133
134
  error!({ message: "ID:#{rule.id} is already registered" }, 400)
134
135
  end
135
136
 
136
137
  status 201
137
- present rule.model, with: Entities::Rule
138
+ present rule.to_model, with: Entities::Rule
138
139
  end
139
140
 
140
141
  desc "Update a rule", {
@@ -156,7 +157,7 @@ module Mihari
156
157
  end
157
158
 
158
159
  begin
159
- rule = Structs::Rule.from_yaml(yaml)
160
+ rule = Services::Rule.from_yaml(yaml)
160
161
  rescue YAMLSyntaxError => e
161
162
  error!({ message: e.message }, 400)
162
163
  end
@@ -171,13 +172,13 @@ module Mihari
171
172
  end
172
173
 
173
174
  begin
174
- rule.model.save
175
+ rule.to_model.save
175
176
  rescue ActiveRecord::RecordNotUnique
176
177
  error!({ message: "ID:#{id} is already registered" }, 400)
177
178
  end
178
179
 
179
180
  status 201
180
- present rule.model, with: Entities::Rule
181
+ present rule.to_model, with: Entities::Rule
181
182
  end
182
183
 
183
184
  desc "Delete a rule", {