mihari 5.5.0 → 5.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/docs/analyzers/passivetotal.md +4 -0
  3. data/docs/analyzers/securitytrails.md +4 -0
  4. data/docs/analyzers/virustotal.md +4 -0
  5. data/docs/analyzers/virustotal_intelligence.md +4 -0
  6. data/docs/emitters/hive.md +1 -1
  7. data/docs/emitters/slack.md +0 -5
  8. data/docs/rule.md +1 -4
  9. data/docs/usage.md +5 -2
  10. data/frontend/src/components/ErrorMessage.vue +0 -1
  11. data/frontend/src/components/alert/Alerts.vue +0 -1
  12. data/frontend/src/components/alert/AlertsWithPagination.vue +0 -1
  13. data/frontend/src/components/alert/AlertsWrapper.vue +0 -6
  14. data/frontend/src/components/alert/Form.vue +1 -3
  15. data/frontend/src/components/artifact/Artifact.vue +0 -17
  16. data/frontend/src/components/artifact/ArtifactWrapper.vue +0 -2
  17. data/frontend/src/components/artifact/WhoisRecord.vue +0 -3
  18. data/frontend/src/components/config/ConfigsWrapper.vue +0 -2
  19. data/frontend/src/components/rule/EditRule.vue +0 -3
  20. data/frontend/src/components/rule/EditRuleWrapper.vue +0 -2
  21. data/frontend/src/components/rule/Form.vue +1 -3
  22. data/frontend/src/components/rule/NewRule.vue +0 -3
  23. data/frontend/src/components/rule/Rule.vue +1 -7
  24. data/frontend/src/components/rule/RuleWrapper.vue +0 -2
  25. data/frontend/src/components/rule/RulesWrapper.vue +0 -6
  26. data/frontend/src/swagger.yaml +254 -254
  27. data/lib/mihari/analyzers/base.rb +4 -41
  28. data/lib/mihari/analyzers/passivetotal.rb +9 -0
  29. data/lib/mihari/analyzers/pulsedive.rb +1 -1
  30. data/lib/mihari/analyzers/rule.rb +24 -59
  31. data/lib/mihari/analyzers/securitytrails.rb +9 -0
  32. data/lib/mihari/analyzers/virustotal.rb +11 -2
  33. data/lib/mihari/analyzers/virustotal_intelligence.rb +16 -0
  34. data/lib/mihari/analyzers/zoomeye.rb +2 -2
  35. data/lib/mihari/base.rb +69 -0
  36. data/lib/mihari/cli/main.rb +36 -0
  37. data/lib/mihari/commands/alert.rb +6 -33
  38. data/lib/mihari/commands/rule.rb +7 -12
  39. data/lib/mihari/commands/search.rb +10 -38
  40. data/lib/mihari/constants.rb +3 -3
  41. data/lib/mihari/emitters/base.rb +3 -33
  42. data/lib/mihari/emitters/database.rb +1 -1
  43. data/lib/mihari/enrichers/base.rb +2 -33
  44. data/lib/mihari/enrichers/google_public_dns.rb +9 -0
  45. data/lib/mihari/schemas/analyzer.rb +24 -24
  46. data/lib/mihari/schemas/emitter.rb +6 -13
  47. data/lib/mihari/schemas/enricher.rb +4 -11
  48. data/lib/mihari/schemas/options.rb +27 -0
  49. data/lib/mihari/schemas/rule.rb +2 -2
  50. data/lib/mihari/services/alert_runner.rb +1 -1
  51. data/lib/mihari/services/rule_runner.rb +1 -11
  52. data/lib/mihari/types.rb +1 -14
  53. data/lib/mihari/version.rb +1 -1
  54. data/lib/mihari/web/public/assets/{index-33165282.css → index-56fc2187.css} +1 -1
  55. data/lib/mihari/web/public/assets/{index-b5d817a3.js → index-9cc489e6.js} +2 -2
  56. data/lib/mihari/web/public/index.html +2 -2
  57. data/lib/mihari.rb +67 -37
  58. data/mihari.gemspec +1 -0
  59. metadata +20 -4
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Mihari
4
4
  module Emitters
5
- class Base
5
+ class Base < Mihari::Base
6
6
  include Dry::Monads[:result, :try]
7
7
 
8
8
  include Mixins::Configurable
@@ -14,9 +14,6 @@ module Mihari
14
14
  # @return [Mihari::Services::Rule]
15
15
  attr_reader :rule
16
16
 
17
- # @return [Hash]
18
- attr_reader :options
19
-
20
17
  #
21
18
  # @param [Array<Mihari::Artifact>] artifacts
22
19
  # @param [Mihari::Services::RuleProxy] rule
@@ -24,37 +21,10 @@ module Mihari
24
21
  # @param [Hash] **_params
25
22
  #
26
23
  def initialize(artifacts:, rule:, options: nil, **_params)
24
+ super(options: options)
25
+
27
26
  @artifacts = artifacts
28
27
  @rule = rule
29
- @options = options || {}
30
- end
31
-
32
- #
33
- # @return [Integer]
34
- #
35
- def retry_interval
36
- options[:retry_interval] || Mihari.config.retry_interval
37
- end
38
-
39
- #
40
- # @return [Boolean]
41
- #
42
- def retry_exponential_backoff
43
- options[:retry_exponential_backoff] || Mihari.config.retry_exponential_backoff
44
- end
45
-
46
- #
47
- # @return [Integer]
48
- #
49
- def retry_times
50
- options[:retry_times] || Mihari.config.retry_times
51
- end
52
-
53
- #
54
- # @return [Integer, nil]
55
- #
56
- def timeout
57
- options[:timeout]
58
28
  end
59
29
 
60
30
  # @return [Boolean]
@@ -13,7 +13,7 @@ module Mihari
13
13
  # @return [Mihari::Alert, nil]
14
14
  #
15
15
  def emit
16
- return nil if artifacts.empty?
16
+ return if artifacts.empty?
17
17
 
18
18
  tags = rule.tags.filter_map { |name| Tag.find_or_create_by(name: name) }.uniq
19
19
  taggings = tags.map { |tag| Tagging.new(tag_id: tag.id) }
@@ -2,45 +2,14 @@
2
2
 
3
3
  module Mihari
4
4
  module Enrichers
5
- class Base
5
+ class Base < Mihari::Base
6
6
  include Mixins::Configurable
7
7
  include Mixins::Retriable
8
8
 
9
9
  include Dry::Monads[:result, :try]
10
10
 
11
- # @return [Hash]
12
- attr_reader :options
13
-
14
11
  def initialize(options: nil)
15
- @options = options || {}
16
- end
17
-
18
- #
19
- # @return [Integer]
20
- #
21
- def retry_interval
22
- options[:retry_interval] || Mihari.config.retry_interval
23
- end
24
-
25
- #
26
- # @return [Boolean]
27
- #
28
- def retry_exponential_backoff
29
- options[:retry_exponential_backoff] || Mihari.config.retry_exponential_backoff
30
- end
31
-
32
- #
33
- # @return [Integer]
34
- #
35
- def retry_times
36
- options[:retry_times] || Mihari.config.retry_times
37
- end
38
-
39
- #
40
- # @return [Integer, nil]
41
- #
42
- def timeout
43
- options[:timeout]
12
+ super(options: options)
44
13
  end
45
14
 
46
15
  def query_result(value)
@@ -38,6 +38,15 @@ module Mihari
38
38
  nil
39
39
  end
40
40
 
41
+ class << self
42
+ #
43
+ # @return [String]
44
+ #
45
+ def class_key
46
+ "google_public_dns"
47
+ end
48
+ end
49
+
41
50
  private
42
51
 
43
52
  def http
@@ -2,37 +2,31 @@
2
2
 
3
3
  module Mihari
4
4
  module Schemas
5
- AnalyzerOptions = Dry::Schema.Params do
6
- optional(:pagination_interval).value(:integer).default(Mihari.config.pagination_interval)
7
- optional(:pagination_limit).value(:integer).default(Mihari.config.pagination_limit)
8
- optional(:retry_times).value(:integer).default(Mihari.config.retry_times)
9
- optional(:retry_interval).value(:integer).default(Mihari.config.retry_interval)
10
- optional(:retry_exponential_backoff).value(:bool).default(Mihari.config.retry_exponential_backoff)
11
- optional(:ignore_error).value(:bool).default(Mihari.config.ignore_error)
12
- optional(:timeout).value(:integer)
13
- end
14
-
15
- AnalyzerWithoutAPIKey = Dry::Schema.Params do
16
- required(:analyzer).value(Types::String.enum("dnstwister"))
17
- required(:query).value(:string)
18
- optional(:options).hash(AnalyzerOptions)
19
- end
20
-
21
- AnalyzerWithAPIKey = Dry::Schema.Params do
5
+ AnalyzerAPIKeyPagination = Dry::Schema.Params do
22
6
  required(:analyzer).value(
23
7
  Types::String.enum(
24
8
  "binaryedge",
25
9
  "greynoise",
26
10
  "onyphe",
11
+ "shodan",
12
+ "urlscan",
13
+ "virustotal_intelligence",
14
+ "vt_intel"
15
+ )
16
+ )
17
+ required(:query).value(:string)
18
+ optional(:api_key).value(:string)
19
+ optional(:options).hash(AnalyzerPaginationOptions)
20
+ end
21
+
22
+ AnalyzerAPIKey = Dry::Schema.Params do
23
+ required(:analyzer).value(
24
+ Types::String.enum(
27
25
  "otx",
28
26
  "pulsedive",
29
27
  "securitytrails",
30
- "shodan",
31
28
  "st",
32
- "urlscan",
33
- "virustotal_intelligence",
34
29
  "virustotal",
35
- "vt_intel",
36
30
  "vt"
37
31
  )
38
32
  )
@@ -41,12 +35,18 @@ module Mihari
41
35
  optional(:options).hash(AnalyzerOptions)
42
36
  end
43
37
 
38
+ DNSTwister = Dry::Schema.Params do
39
+ required(:analyzer).value(Types::String.enum("dnstwister"))
40
+ required(:query).value(:string)
41
+ optional(:options).hash(AnalyzerOptions)
42
+ end
43
+
44
44
  Censys = Dry::Schema.Params do
45
45
  required(:analyzer).value(Types::String.enum("censys"))
46
46
  required(:query).value(:string)
47
47
  optional(:id).value(:string)
48
48
  optional(:secret).value(:string)
49
- optional(:options).hash(AnalyzerOptions)
49
+ optional(:options).hash(AnalyzerPaginationOptions)
50
50
  end
51
51
 
52
52
  CIRCL = Dry::Schema.Params do
@@ -69,7 +69,7 @@ module Mihari
69
69
  required(:analyzer).value(Types::String.enum("zoomeye"))
70
70
  required(:query).value(:string)
71
71
  required(:type).value(Types::String.enum("host", "web"))
72
- optional(:options).hash(AnalyzerOptions)
72
+ optional(:options).hash(AnalyzerPaginationOptions)
73
73
  end
74
74
 
75
75
  Crtsh = Dry::Schema.Params do
@@ -85,7 +85,7 @@ module Mihari
85
85
  required(:start_time).value(:date)
86
86
  required(:end_time).value(:date)
87
87
  optional(:api_key).value(:string)
88
- optional(:options).hash(AnalyzerOptions)
88
+ optional(:options).hash(AnalyzerPaginationOptions)
89
89
  end
90
90
 
91
91
  Feed = Dry::Schema.Params do
@@ -3,38 +3,31 @@
3
3
  module Mihari
4
4
  module Schemas
5
5
  module Emitters
6
- EmitterOptions = Dry::Schema.Params do
7
- optional(:retry_times).value(:integer).default(Mihari.config.retry_times)
8
- optional(:retry_interval).value(:integer).default(Mihari.config.retry_interval)
9
- optional(:retry_exponential_backoff).value(:bool).default(Mihari.config.retry_exponential_backoff)
10
- optional(:timeout).value(:integer)
11
- end
12
-
13
6
  Database = Dry::Schema.Params do
14
7
  required(:emitter).value(Types::String.enum("database"))
15
- optional(:options).hash(EmitterOptions)
8
+ optional(:options).hash(Options)
16
9
  end
17
10
 
18
11
  MISP = Dry::Schema.Params do
19
12
  required(:emitter).value(Types::String.enum("misp"))
20
13
  optional(:url).value(:string)
21
14
  optional(:api_key).value(:string)
22
- optional(:options).hash(EmitterOptions)
15
+ optional(:options).hash(Options)
23
16
  end
24
17
 
25
18
  TheHive = Dry::Schema.Params do
26
- required(:emitter).value(Types::String.enum("the_hive"))
19
+ required(:emitter).value(Types::String.enum("thehive"))
27
20
  optional(:url).value(:string)
28
21
  optional(:api_key).value(:string)
29
22
  optional(:api_version).value(Types::String.enum("v4", "v5")).default("v4")
30
- optional(:options).hash(EmitterOptions)
23
+ optional(:options).hash(Options)
31
24
  end
32
25
 
33
26
  Slack = Dry::Schema.Params do
34
27
  required(:emitter).value(Types::String.enum("slack"))
35
28
  optional(:webhook_url).value(:string)
36
29
  optional(:channel).value(:string)
37
- optional(:options).hash(EmitterOptions)
30
+ optional(:options).hash(Options)
38
31
  end
39
32
 
40
33
  Webhook = Dry::Schema.Params do
@@ -43,7 +36,7 @@ module Mihari
43
36
  optional(:method).value(Types::HTTPRequestMethods).default("POST")
44
37
  optional(:headers).value(:hash).default({})
45
38
  optional(:template).value(:string)
46
- optional(:options).hash(EmitterOptions)
39
+ optional(:options).hash(Options)
47
40
  end
48
41
  end
49
42
  end
@@ -3,32 +3,25 @@
3
3
  module Mihari
4
4
  module Schemas
5
5
  module Enrichers
6
- EnricherOptions = Dry::Schema.Params do
7
- optional(:retry_times).value(:integer).default(Mihari.config.retry_times)
8
- optional(:retry_interval).value(:integer).default(Mihari.config.retry_interval)
9
- optional(:retry_exponential_backoff).value(:bool).default(Mihari.config.retry_exponential_backoff)
10
- optional(:timeout).value(:integer)
11
- end
12
-
13
6
  IPInfo = Dry::Schema.Params do
14
7
  required(:enricher).value(Types::String.enum("ipinfo"))
15
8
  optional(:api_key).value(:string)
16
- optional(:options).hash(EnricherOptions)
9
+ optional(:options).hash(Options)
17
10
  end
18
11
 
19
12
  Whois = Dry::Schema.Params do
20
13
  required(:enricher).value(Types::String.enum("whois"))
21
- optional(:options).hash(EnricherOptions)
14
+ optional(:options).hash(Options)
22
15
  end
23
16
 
24
17
  Shodan = Dry::Schema.Params do
25
18
  required(:enricher).value(Types::String.enum("shodan"))
26
- optional(:options).hash(EnricherOptions)
19
+ optional(:options).hash(Options)
27
20
  end
28
21
 
29
22
  GooglePublicDNS = Dry::Schema.Params do
30
23
  required(:enricher).value(Types::String.enum("google_public_dns"))
31
- optional(:options).hash(EnricherOptions)
24
+ optional(:options).hash(Options)
32
25
  end
33
26
  end
34
27
  end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/schema"
4
+
5
+ module Mihari
6
+ module Schemas
7
+ Options = Dry::Schema.Params do
8
+ optional(:retry_times).value(:integer).default(Mihari.config.retry_times)
9
+ optional(:retry_interval).value(:integer).default(Mihari.config.retry_interval)
10
+ optional(:retry_exponential_backoff).value(:bool).default(Mihari.config.retry_exponential_backoff)
11
+ optional(:timeout).value(:integer)
12
+ end
13
+
14
+ IgnoreErrorOptions = Dry::Schema.Params do
15
+ optional(:ignore_error).value(:bool).default(Mihari.config.ignore_error)
16
+ end
17
+
18
+ AnalyzerOptions = Options | IgnoreErrorOptions
19
+
20
+ PaginationOptions = Dry::Schema.Params do
21
+ optional(:pagination_interval).value(:integer).default(Mihari.config.pagination_interval)
22
+ optional(:pagination_limit).value(:integer).default(Mihari.config.pagination_limit)
23
+ end
24
+
25
+ AnalyzerPaginationOptions = AnalyzerOptions | PaginationOptions
26
+ end
27
+ end
@@ -22,7 +22,7 @@ module Mihari
22
22
  optional(:updated_on).value(:date)
23
23
 
24
24
  required(:queries).value(:array).each do
25
- AnalyzerWithoutAPIKey | AnalyzerWithAPIKey | Censys | CIRCL | PassiveTotal | ZoomEye | Crtsh | Feed | HunterHow
25
+ AnalyzerAPIKey | AnalyzerAPIKeyPagination | Censys | CIRCL | PassiveTotal | ZoomEye | Crtsh | Feed | HunterHow | DNSTwister
26
26
  end
27
27
 
28
28
  optional(:emitters).value(:array).each do
@@ -33,7 +33,7 @@ module Mihari
33
33
  Enrichers::Whois | Enrichers::IPInfo | Enrichers::Shodan | Enrichers::GooglePublicDNS
34
34
  end.default(DEFAULT_ENRICHERS)
35
35
 
36
- optional(:data_types).value(array[Types::DataTypes]).default(DEFAULT_DATA_TYPES)
36
+ optional(:data_types).value(array[Types::DataTypes]).default(Mihari::Types::DataTypes.values)
37
37
  optional(:falsepositives).value(array[:string]).default([])
38
38
 
39
39
  optional(:artifact_lifetime).value(:integer)
@@ -16,7 +16,7 @@ module Mihari
16
16
  # @return [Mihari::Alert]
17
17
  #
18
18
  def run
19
- emitter = Mihari::Emitters::Database.new(artifacts: alert.artifacts, rule: alert.rule)
19
+ emitter = Emitters::Database.new(artifacts: alert.artifacts, rule: alert.rule)
20
20
  emitter.emit
21
21
  end
22
22
 
@@ -5,21 +5,11 @@ module Mihari
5
5
  class RuleRunner
6
6
  include Dry::Monads[:result, :try]
7
7
 
8
- include Mixins::ErrorNotification
9
-
10
8
  # @return [Mihari::Services::RuleProxy]
11
9
  attr_reader :rule
12
10
 
13
- # @return [Boolean]
14
- attr_reader :force_overwrite
15
-
16
- def initialize(rule, force_overwrite:)
11
+ def initialize(rule)
17
12
  @rule = rule
18
- @force_overwrite = force_overwrite
19
- end
20
-
21
- def force_overwrite?
22
- force_overwrite
23
13
  end
24
14
 
25
15
  #
data/lib/mihari/types.rb CHANGED
@@ -12,21 +12,8 @@ module Mihari
12
12
  Double = Strict::Float | Strict::Integer
13
13
  DateTime = Strict::DateTime
14
14
 
15
- DataTypes = Types::String.enum(*DEFAULT_DATA_TYPES)
15
+ DataTypes = Types::String.enum("hash", "ip", "domain", "url", "mail")
16
16
 
17
17
  HTTPRequestMethods = Types::String.enum("GET", "POST")
18
- HTTPRequestPayloadTypes = Types::String.enum("application/json", "application/x-www-form-urlencoded")
19
-
20
- EmitterTypes = Types::String.enum(
21
- "database",
22
- "webhook"
23
- )
24
-
25
- EnricherTypes = Types::String.enum(
26
- "whois",
27
- "ipinfo",
28
- "shodan",
29
- "google_public_dns"
30
- )
31
18
  end
32
19
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Mihari
4
- VERSION = "5.5.0"
4
+ VERSION = "5.6.0"
5
5
  end