mihari 6.0.0 → 6.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +4 -0
  3. data/lib/mihari/actor.rb +4 -6
  4. data/lib/mihari/analyzers/base.rb +10 -3
  5. data/lib/mihari/analyzers/circl.rb +1 -1
  6. data/lib/mihari/analyzers/dnstwister.rb +1 -1
  7. data/lib/mihari/analyzers/hunterhow.rb +1 -1
  8. data/lib/mihari/analyzers/otx.rb +1 -1
  9. data/lib/mihari/analyzers/passivetotal.rb +1 -1
  10. data/lib/mihari/analyzers/pulsedive.rb +1 -1
  11. data/lib/mihari/analyzers/securitytrails.rb +1 -1
  12. data/lib/mihari/analyzers/virustotal.rb +1 -1
  13. data/lib/mihari/clients/google_public_dns.rb +31 -0
  14. data/lib/mihari/config.rb +10 -2
  15. data/lib/mihari/{type_checker.rb → data_type.rb} +32 -37
  16. data/lib/mihari/database.rb +8 -4
  17. data/lib/mihari/emitters/misp.rb +2 -2
  18. data/lib/mihari/emitters/slack.rb +5 -5
  19. data/lib/mihari/emitters/the_hive.rb +2 -2
  20. data/lib/mihari/enrichers/base.rb +2 -0
  21. data/lib/mihari/enrichers/google_public_dns.rb +4 -21
  22. data/lib/mihari/enrichers/ipinfo.rb +1 -0
  23. data/lib/mihari/enrichers/shodan.rb +1 -0
  24. data/lib/mihari/enrichers/whois.rb +11 -16
  25. data/lib/mihari/entities/artifact.rb +1 -0
  26. data/lib/mihari/mixins/falsepositive.rb +2 -2
  27. data/lib/mihari/models/artifact.rb +14 -6
  28. data/lib/mihari/models/dns.rb +3 -8
  29. data/lib/mihari/rule.rb +20 -7
  30. data/lib/mihari/schemas/options.rb +5 -1
  31. data/lib/mihari/structs/google_public_dns.rb +4 -8
  32. data/lib/mihari/version.rb +1 -1
  33. data/lib/mihari/web/app.rb +2 -2
  34. data/lib/mihari/web/public/assets/index-1d77cd61.js +1756 -0
  35. data/lib/mihari/web/public/assets/{index-56fc2187.css → index-4c8509ee.css} +1 -1
  36. data/lib/mihari/web/public/index.html +2 -2
  37. data/lib/mihari/web/public/redoc-static.html +5 -5
  38. data/lib/mihari.rb +10 -10
  39. data/mihari.gemspec +5 -4
  40. data/mkdocs.yml +1 -0
  41. data/requirements.txt +1 -1
  42. metadata +23 -50
  43. data/lib/mihari/web/public/assets/index-07cddfcd.js +0 -1750
@@ -20,16 +20,11 @@ module Mihari
20
20
  # @return [Array<Mihari::Models::DnsRecord>]
21
21
  #
22
22
  def build_by_domain(domain, enricher: Enrichers::GooglePublicDNS.new)
23
- result = enricher.result(domain).bind do |responses|
23
+ enricher.result(domain).bind do |res|
24
24
  Success(
25
- responses.map do |res|
26
- res.answers.map do |answer|
27
- new(resource: answer.resource_type, value: answer.data)
28
- end
29
- end.flatten
25
+ res.answers.map { |answer| new(resource: answer.resource_type, value: answer.data) }
30
26
  )
31
- end
32
- result.value_or []
27
+ end.value_or([])
33
28
  end
34
29
  end
35
30
  end
data/lib/mihari/rule.rb CHANGED
@@ -110,9 +110,7 @@ module Mihari
110
110
  # @return [Array<Mihari::Models::Artifact>]
111
111
  #
112
112
  def artifacts
113
- analyzers.flat_map do |analyzer|
114
- # @type [Dry::Monads::Result::Success<Array<Mihari::Models::Artifact>>, Dry::Monads::Result::Failure]
115
- result = analyzer.result
113
+ analyzer_results.flat_map do |result|
116
114
  case result
117
115
  when Success
118
116
  artifacts = result.value!
@@ -123,7 +121,7 @@ module Mihari
123
121
  else
124
122
  raise result.failure unless analyzer.ignore_error?
125
123
  end
126
- end.compact
124
+ end
127
125
  end
128
126
 
129
127
  #
@@ -292,15 +290,30 @@ module Mihari
292
290
  # @return [Array<Mihari::Analyzers::Base>]
293
291
  #
294
292
  def analyzers
295
- @analyzers ||= queries.map do |query_params|
296
- analyzer_name = query_params[:analyzer]
293
+ @analyzers ||= queries.map do |params|
294
+ analyzer_name = params[:analyzer]
297
295
  klass = get_analyzer_class(analyzer_name)
298
- analyzer = klass.from_query(query_params)
296
+ analyzer = klass.from_query(params)
299
297
  analyzer.validate_configuration!
300
298
  analyzer
301
299
  end
302
300
  end
303
301
 
302
+ def parallel_analyzers
303
+ analyzers.select(&:parallel?)
304
+ end
305
+
306
+ def serial_analyzers
307
+ analyzers.reject(&:parallel?)
308
+ end
309
+
310
+ # @return [Array<Dry::Monads::Result::Success<Array<Mihari::Models::Artifact>>, Dry::Monads::Result::Failure>]
311
+ def analyzer_results
312
+ parallel_results = Parallel.map(parallel_analyzers) { |analyzer| analyzer.result }
313
+ serial_results = serial_analyzers.map(&:result)
314
+ parallel_results + serial_results
315
+ end
316
+
304
317
  #
305
318
  # Get emitter class
306
319
  #
@@ -15,7 +15,11 @@ module Mihari
15
15
  optional(:ignore_error).value(:bool).default(Mihari.config.ignore_error)
16
16
  end
17
17
 
18
- AnalyzerOptions = Options | IgnoreErrorOptions
18
+ ParallelOptions = Dry::Schema.Params do
19
+ optional(:parallel).value(:bool).default(Mihari.config.parallel)
20
+ end
21
+
22
+ AnalyzerOptions = Options | IgnoreErrorOptions | ParallelOptions
19
23
 
20
24
  PaginationOptions = Dry::Schema.Params do
21
25
  optional(:pagination_interval).value(:integer).default(Mihari.config.pagination_interval)
@@ -3,13 +3,9 @@
3
3
  module Mihari
4
4
  module Structs
5
5
  module GooglePublicDNS
6
- INT_TYPE_TO_TYPE = {
7
- 1 => "A",
8
- 2 => "NS",
9
- 5 => "CNAME",
10
- 16 => "TXT",
11
- 28 => "AAAA"
12
- }.freeze
6
+ INT_TYPE_TO_TYPE =
7
+ { 1 => :A, 38 => :A6, 28 => :AAAA, 18 => :AFSDB, 255 => :ANY, 42 => :APL, 34 => :ATMA, 252 => :AXFR, 37 => :CERT,
8
+ 5 => :CNAME, 49 => :DHCID, 32_769 => :DLV, 39 => :DNAME, 48 => :DNSKEY, 43 => :DS, 31 => :EID, 102 => :GID, 27 => :GPOS, 13 => :HINFO, 45 => :IPSECKEY, 20 => :ISDN, 251 => :IXFR, 25 => :KEY, 36 => :KX, 29 => :LOC, 254 => :MAILA, 253 => :MAILB, 7 => :MB, 3 => :MD, 4 => :MF, 8 => :MG, 14 => :MINFO, 9 => :MR, 15 => :MX, 35 => :NAPTR, 32 => :NIMLOC, 2 => :NS, 22 => :NSAP, 23 => :NSAP_PTR, 47 => :NSEC, 50 => :NSEC3, 51 => :NSEC3PARAMS, 10 => :NULL, 30 => :NXT, 41 => :OPT, 12 => :PTR, 26 => :PX, 17 => :RP, 46 => :RRSIG, 21 => :RT, 24 => :SIG, 40 => :SINK, 6 => :SOA, 33 => :SRV, 44 => :SSHFP, 250 => :TSIG, 16 => :TXT, 101 => :UID, 100 => :UINFO, 103 => :UNSPEC, 11 => :WKS, 19 => :X25 }
13
9
 
14
10
  class Answer < Dry::Struct
15
11
  # @!attribute [r] name
@@ -30,7 +26,7 @@ module Mihari
30
26
  #
31
27
  def from_dynamic!(d)
32
28
  d = Types::Hash[d]
33
- resource_type = INT_TYPE_TO_TYPE[d.fetch("type")]
29
+ resource_type = INT_TYPE_TO_TYPE[d.fetch("type")].to_s
34
30
  new(
35
31
  name: d.fetch("name"),
36
32
  data: d.fetch("data"),
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Mihari
4
- VERSION = "6.0.0"
4
+ VERSION = "6.2.0"
5
5
  end
@@ -53,17 +53,17 @@ module Mihari
53
53
 
54
54
  class << self
55
55
  def instance
56
- @instance ||= Rack::Builder.new do
56
+ Rack::Builder.new do
57
57
  use Rack::Cors do
58
58
  allow do
59
59
  origins "*"
60
60
  resource "*", headers: :any, methods: %i[get post put delete options]
61
61
  end
62
62
  end
63
-
64
63
  use Middleware::ConnectionAdapter
65
64
  use Middleware::ErrorNotificationAdapter
66
65
 
66
+ use Sentry::Rack::CaptureExceptions if Sentry.initialized?
67
67
  use BetterErrors::Middleware if ENV["RACK_ENV"] == "development" && defined?(BetterErrors::Middleware)
68
68
 
69
69
  run App.new