mihari 5.3.0 → 5.3.2

Sign up to get free protection for your applications and to get access to all the features.
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", {