mihari 5.6.2 → 5.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (150) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +5 -1
  3. data/README.md +1 -0
  4. data/config.ru +1 -1
  5. data/docs/analyzers/fofa.md +31 -0
  6. data/docs/analyzers/index.md +1 -0
  7. data/frontend/package-lock.json +73 -73
  8. data/frontend/package.json +5 -5
  9. data/frontend/src/components/alert/Form.vue +1 -14
  10. data/frontend/src/components/artifact/AS.vue +2 -8
  11. data/frontend/src/components/artifact/DnsRecords.vue +2 -8
  12. data/frontend/src/components/artifact/ReverseDnsNames.vue +2 -10
  13. data/frontend/src/components/artifact/WhoisRecord.vue +1 -1
  14. data/lib/mihari/actor.rb +14 -4
  15. data/lib/mihari/analyzers/base.rb +13 -12
  16. data/lib/mihari/analyzers/binaryedge.rb +4 -1
  17. data/lib/mihari/analyzers/censys.rb +4 -2
  18. data/lib/mihari/analyzers/circl.rb +4 -1
  19. data/lib/mihari/analyzers/crtsh.rb +4 -1
  20. data/lib/mihari/analyzers/dnstwister.rb +4 -1
  21. data/lib/mihari/analyzers/feed.rb +3 -0
  22. data/lib/mihari/analyzers/fofa.rb +65 -0
  23. data/lib/mihari/analyzers/greynoise.rb +4 -1
  24. data/lib/mihari/analyzers/hunterhow.rb +6 -1
  25. data/lib/mihari/analyzers/onyphe.rb +4 -1
  26. data/lib/mihari/analyzers/otx.rb +4 -1
  27. data/lib/mihari/analyzers/passivetotal.rb +4 -1
  28. data/lib/mihari/analyzers/pulsedive.rb +3 -0
  29. data/lib/mihari/analyzers/securitytrails.rb +4 -1
  30. data/lib/mihari/analyzers/shodan.rb +4 -1
  31. data/lib/mihari/analyzers/urlscan.rb +4 -1
  32. data/lib/mihari/analyzers/virustotal.rb +4 -1
  33. data/lib/mihari/analyzers/virustotal_intelligence.rb +4 -1
  34. data/lib/mihari/analyzers/zoomeye.rb +5 -2
  35. data/lib/mihari/cli/alert.rb +3 -0
  36. data/lib/mihari/cli/base.rb +3 -0
  37. data/lib/mihari/cli/database.rb +3 -0
  38. data/lib/mihari/cli/main.rb +3 -0
  39. data/lib/mihari/cli/rule.rb +3 -0
  40. data/lib/mihari/clients/base.rb +3 -0
  41. data/lib/mihari/clients/binaryedge.rb +5 -2
  42. data/lib/mihari/clients/censys.rb +7 -4
  43. data/lib/mihari/clients/circl.rb +3 -0
  44. data/lib/mihari/clients/crtsh.rb +3 -0
  45. data/lib/mihari/clients/dnstwister.rb +3 -0
  46. data/lib/mihari/clients/fofa.rb +83 -0
  47. data/lib/mihari/clients/greynoise.rb +5 -2
  48. data/lib/mihari/clients/hunterhow.rb +5 -2
  49. data/lib/mihari/clients/misp.rb +3 -0
  50. data/lib/mihari/clients/onyphe.rb +5 -2
  51. data/lib/mihari/clients/otx.rb +3 -0
  52. data/lib/mihari/clients/passivetotal.rb +3 -0
  53. data/lib/mihari/clients/publsedive.rb +4 -1
  54. data/lib/mihari/clients/securitytrails.rb +3 -0
  55. data/lib/mihari/clients/shodan.rb +5 -2
  56. data/lib/mihari/clients/the_hive.rb +3 -0
  57. data/lib/mihari/clients/urlscan.rb +7 -4
  58. data/lib/mihari/clients/virustotal.rb +5 -2
  59. data/lib/mihari/clients/zoomeye.rb +3 -0
  60. data/lib/mihari/commands/alert.rb +5 -14
  61. data/lib/mihari/commands/database.rb +3 -0
  62. data/lib/mihari/commands/rule.rb +10 -1
  63. data/lib/mihari/commands/search.rb +9 -6
  64. data/lib/mihari/commands/version.rb +3 -0
  65. data/lib/mihari/commands/web.rb +4 -1
  66. data/lib/mihari/config.rb +139 -150
  67. data/lib/mihari/constants.rb +1 -1
  68. data/lib/mihari/database.rb +6 -0
  69. data/lib/mihari/emitters/base.rb +13 -11
  70. data/lib/mihari/emitters/database.rb +4 -1
  71. data/lib/mihari/emitters/misp.rb +7 -4
  72. data/lib/mihari/emitters/slack.rb +3 -3
  73. data/lib/mihari/emitters/the_hive.rb +3 -3
  74. data/lib/mihari/emitters/webhook.rb +4 -3
  75. data/lib/mihari/enrichers/base.rb +15 -9
  76. data/lib/mihari/enrichers/google_public_dns.rb +6 -5
  77. data/lib/mihari/enrichers/ipinfo.rb +10 -8
  78. data/lib/mihari/enrichers/shodan.rb +4 -6
  79. data/lib/mihari/enrichers/whois.rb +12 -9
  80. data/lib/mihari/errors.rb +6 -0
  81. data/lib/mihari/feed/parser.rb +3 -0
  82. data/lib/mihari/feed/reader.rb +3 -0
  83. data/lib/mihari/http.rb +6 -0
  84. data/lib/mihari/mixins/autonomous_system.rb +3 -0
  85. data/lib/mihari/mixins/configurable.rb +3 -0
  86. data/lib/mihari/mixins/error_notification.rb +3 -0
  87. data/lib/mihari/mixins/falsepositive.rb +3 -0
  88. data/lib/mihari/mixins/refang.rb +3 -0
  89. data/lib/mihari/mixins/retriable.rb +6 -2
  90. data/lib/mihari/models/alert.rb +7 -4
  91. data/lib/mihari/models/artifact.rb +6 -0
  92. data/lib/mihari/models/autonomous_system.rb +4 -1
  93. data/lib/mihari/models/cpe.rb +4 -1
  94. data/lib/mihari/models/dns.rb +4 -1
  95. data/lib/mihari/models/geolocation.rb +4 -1
  96. data/lib/mihari/models/port.rb +4 -1
  97. data/lib/mihari/models/reverse_dns.rb +4 -1
  98. data/lib/mihari/models/rule.rb +6 -3
  99. data/lib/mihari/models/tag.rb +3 -0
  100. data/lib/mihari/models/tagging.rb +3 -0
  101. data/lib/mihari/models/whois.rb +4 -3
  102. data/lib/mihari/rule.rb +17 -12
  103. data/lib/mihari/schemas/alert.rb +3 -0
  104. data/lib/mihari/schemas/analyzer.rb +11 -0
  105. data/lib/mihari/schemas/emitter.rb +3 -0
  106. data/lib/mihari/schemas/enricher.rb +3 -0
  107. data/lib/mihari/schemas/macros.rb +4 -0
  108. data/lib/mihari/schemas/mixins.rb +5 -0
  109. data/lib/mihari/schemas/rule.rb +3 -0
  110. data/lib/mihari/service.rb +16 -0
  111. data/lib/mihari/services/alert_builder.rb +8 -5
  112. data/lib/mihari/services/alert_proxy.rb +6 -1
  113. data/lib/mihari/services/alert_runner.rb +8 -12
  114. data/lib/mihari/services/rule_builder.rb +8 -5
  115. data/lib/mihari/services/rule_runner.rb +8 -10
  116. data/lib/mihari/structs/binaryedge.rb +13 -28
  117. data/lib/mihari/structs/censys.rb +48 -127
  118. data/lib/mihari/structs/config.rb +19 -30
  119. data/lib/mihari/structs/filters.rb +38 -0
  120. data/lib/mihari/structs/fofa.rb +44 -0
  121. data/lib/mihari/structs/google_public_dns.rb +10 -28
  122. data/lib/mihari/structs/greynoise.rb +33 -84
  123. data/lib/mihari/structs/hunterhow.rb +24 -22
  124. data/lib/mihari/structs/ipinfo.rb +14 -35
  125. data/lib/mihari/structs/onyphe.rb +31 -76
  126. data/lib/mihari/structs/shodan.rb +47 -112
  127. data/lib/mihari/structs/urlscan.rb +24 -63
  128. data/lib/mihari/structs/virustotal_intelligence.rb +20 -56
  129. data/lib/mihari/type_checker.rb +4 -0
  130. data/lib/mihari/types.rb +3 -0
  131. data/lib/mihari/version.rb +1 -1
  132. data/lib/mihari/web/api.rb +15 -10
  133. data/lib/mihari/web/app.rb +59 -54
  134. data/lib/mihari/web/endpoints/alerts.rb +94 -89
  135. data/lib/mihari/web/endpoints/artifacts.rb +115 -110
  136. data/lib/mihari/web/endpoints/configs.rb +18 -13
  137. data/lib/mihari/web/endpoints/ip_addresses.rb +21 -16
  138. data/lib/mihari/web/endpoints/rules.rb +203 -198
  139. data/lib/mihari/web/endpoints/tags.rb +41 -36
  140. data/lib/mihari/web/middleware/connection_adapter.rb +16 -9
  141. data/lib/mihari/web/middleware/error_notification_adapter.rb +17 -10
  142. data/lib/mihari/web/public/assets/{index-28d4c79d.js → index-821134e2.js} +30 -30
  143. data/lib/mihari/web/public/assets/mode-yaml-24faa242.js +8 -0
  144. data/lib/mihari/web/public/index.html +1 -1
  145. data/lib/mihari.rb +24 -5
  146. data/mihari.gemspec +8 -1
  147. data/mkdocs.yml +3 -2
  148. metadata +39 -7
  149. data/lib/mihari/templates/rule.yml.erb +0 -5
  150. data/lib/mihari/web/public/assets/mode-yaml-a21faa53.js +0 -8
@@ -2,6 +2,9 @@
2
2
 
3
3
  module Mihari
4
4
  module Analyzers
5
+ #
6
+ # CIRCL passive DNS/SSL analyzer
7
+ #
5
8
  class CIRCL < Base
6
9
  include Mixins::Refang
7
10
 
@@ -51,7 +54,7 @@ module Mihari
51
54
  private
52
55
 
53
56
  def client
54
- @client ||= Clients::CIRCL.new(username: username, password: password, timeout: timeout)
57
+ Clients::CIRCL.new(username: username, password: password, timeout: timeout)
55
58
  end
56
59
 
57
60
  def username?
@@ -2,6 +2,9 @@
2
2
 
3
3
  module Mihari
4
4
  module Analyzers
5
+ #
6
+ # crt.sh analyzer
7
+ #
5
8
  class Crtsh < Base
6
9
  # @return [Boolean]
7
10
  attr_reader :exclude_expired
@@ -28,7 +31,7 @@ module Mihari
28
31
  # @return [Mihari::Clients::Crtsh]
29
32
  #
30
33
  def client
31
- @client ||= Mihari::Clients::Crtsh.new(timeout: timeout)
34
+ Mihari::Clients::Crtsh.new(timeout: timeout)
32
35
  end
33
36
  end
34
37
  end
@@ -2,6 +2,9 @@
2
2
 
3
3
  module Mihari
4
4
  module Analyzers
5
+ #
6
+ # DNSTwister analyzer
7
+ #
5
8
  class DNSTwister < Base
6
9
  include Mixins::Refang
7
10
 
@@ -39,7 +42,7 @@ module Mihari
39
42
  end
40
43
 
41
44
  def client
42
- @client ||= Clients::DNSTwister.new(timeout: timeout)
45
+ Clients::DNSTwister.new(timeout: timeout)
43
46
  end
44
47
 
45
48
  #
@@ -5,6 +5,9 @@ require "mihari/feed/parser"
5
5
 
6
6
  module Mihari
7
7
  module Analyzers
8
+ #
9
+ # Feed analyzer
10
+ #
8
11
  class Feed < Base
9
12
  # @return [Hash, nil]
10
13
  attr_reader :data
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mihari
4
+ module Analyzers
5
+ #
6
+ # Fofa analyzer
7
+ #
8
+ class Fofa < Base
9
+ # @return [String, nil]
10
+ attr_reader :api_key
11
+
12
+ # @return [String, nil]
13
+ attr_reader :email
14
+
15
+ #
16
+ # @param [String] query
17
+ # @param [Hash, nil] options
18
+ # @param [String, nil] api_key
19
+ # @param [String, nil] email
20
+ #
21
+ def initialize(query, options: nil, api_key: nil, email: nil)
22
+ super(query, options: options)
23
+
24
+ @api_key = api_key || Mihari.config.fofa_api_key
25
+ @email = email || Mihari.config.fofa_email
26
+ end
27
+
28
+ def artifacts
29
+ client.search_with_pagination(query, pagination_limit: pagination_limit).map do |res|
30
+ (res.results || []).map { |result| result[1] }
31
+ end.flatten.compact
32
+ end
33
+
34
+ def configuration_keys
35
+ %w[fofa_api_key fofa_email]
36
+ end
37
+
38
+ def configured?
39
+ api_key? && email?
40
+ end
41
+
42
+ private
43
+
44
+ def api_key?
45
+ !api_key.nil?
46
+ end
47
+
48
+ def email?
49
+ !email.nil?
50
+ end
51
+
52
+ #
53
+ # @return [Mihari::Clients::Fofa]
54
+ #
55
+ def client
56
+ Clients::Fofa.new(
57
+ api_key: api_key,
58
+ email: email,
59
+ pagination_interval: pagination_interval,
60
+ timeout: timeout
61
+ )
62
+ end
63
+ end
64
+ end
65
+ end
@@ -2,6 +2,9 @@
2
2
 
3
3
  module Mihari
4
4
  module Analyzers
5
+ #
6
+ # GreyNoise analyzer
7
+ #
5
8
  class GreyNoise < Base
6
9
  # @return [String, nil]
7
10
  attr_reader :api_key
@@ -31,7 +34,7 @@ module Mihari
31
34
  private
32
35
 
33
36
  def client
34
- @client ||= Clients::GreyNoise.new(
37
+ Clients::GreyNoise.new(
35
38
  api_key: api_key,
36
39
  pagination_interval: pagination_interval,
37
40
  timeout: timeout
@@ -2,6 +2,9 @@
2
2
 
3
3
  module Mihari
4
4
  module Analyzers
5
+ #
6
+ # hunter.how analyzer
7
+ #
5
8
  class HunterHow < Base
6
9
  # @return [String, nil]
7
10
  attr_reader :api_key
@@ -14,6 +17,8 @@ module Mihari
14
17
 
15
18
  #
16
19
  # @param [String] query
20
+ # @param [Date] start_time
21
+ # @param [Date] end_time
17
22
  # @param [Hash, nil] options
18
23
  # @param [String, nil] api_key
19
24
  #
@@ -46,7 +51,7 @@ module Mihari
46
51
  private
47
52
 
48
53
  def client
49
- @client ||= Clients::HunterHow.new(
54
+ Clients::HunterHow.new(
50
55
  api_key: api_key,
51
56
  pagination_interval: pagination_interval,
52
57
  timeout: timeout
@@ -4,6 +4,9 @@ require "normalize_country"
4
4
 
5
5
  module Mihari
6
6
  module Analyzers
7
+ #
8
+ # Onyphe analyzer
9
+ #
7
10
  class Onyphe < Base
8
11
  # @return [String, nil]
9
12
  attr_reader :api_key
@@ -33,7 +36,7 @@ module Mihari
33
36
  private
34
37
 
35
38
  def client
36
- @client ||= Clients::Onyphe.new(
39
+ Clients::Onyphe.new(
37
40
  api_key: api_key,
38
41
  pagination_interval: pagination_interval,
39
42
  timeout: timeout
@@ -2,6 +2,9 @@
2
2
 
3
3
  module Mihari
4
4
  module Analyzers
5
+ #
6
+ # OTX analyzer
7
+ #
5
8
  class OTX < Base
6
9
  include Mixins::Refang
7
10
 
@@ -42,7 +45,7 @@ module Mihari
42
45
  private
43
46
 
44
47
  def client
45
- @client ||= Mihari::Clients::OTX.new(api_key: api_key, timeout: timeout)
48
+ Mihari::Clients::OTX.new(api_key: api_key, timeout: timeout)
46
49
  end
47
50
 
48
51
  #
@@ -2,6 +2,9 @@
2
2
 
3
3
  module Mihari
4
4
  module Analyzers
5
+ #
6
+ # PassiveTotal analyzer
7
+ #
5
8
  class PassiveTotal < Base
6
9
  include Mixins::Refang
7
10
 
@@ -62,7 +65,7 @@ module Mihari
62
65
  private
63
66
 
64
67
  def client
65
- @client ||= Clients::PassiveTotal.new(username: username, api_key: api_key, timeout: timeout)
68
+ Clients::PassiveTotal.new(username: username, api_key: api_key, timeout: timeout)
66
69
  end
67
70
 
68
71
  #
@@ -2,6 +2,9 @@
2
2
 
3
3
  module Mihari
4
4
  module Analyzers
5
+ #
6
+ # Pulsedive analyzer
7
+ #
5
8
  class Pulsedive < Base
6
9
  include Mixins::Refang
7
10
 
@@ -2,6 +2,9 @@
2
2
 
3
3
  module Mihari
4
4
  module Analyzers
5
+ #
6
+ # SecurityTrails
7
+ #
5
8
  class SecurityTrails < Base
6
9
  include Mixins::Refang
7
10
 
@@ -56,7 +59,7 @@ module Mihari
56
59
  private
57
60
 
58
61
  def client
59
- @client ||= Clients::SecurityTrails.new(api_key: api_key, timeout: timeout)
62
+ Clients::SecurityTrails.new(api_key: api_key, timeout: timeout)
60
63
  end
61
64
 
62
65
  #
@@ -2,6 +2,9 @@
2
2
 
3
3
  module Mihari
4
4
  module Analyzers
5
+ #
6
+ # Shodan analyzer
7
+ #
5
8
  class Shodan < Base
6
9
  # @return [String, nil]
7
10
  attr_reader :api_key
@@ -34,7 +37,7 @@ module Mihari
34
37
  # @return [Clients::Shodan]
35
38
  #
36
39
  def client
37
- @client ||= Clients::Shodan.new(
40
+ Clients::Shodan.new(
38
41
  api_key: api_key,
39
42
  pagination_interval: pagination_interval,
40
43
  timeout: timeout
@@ -2,6 +2,9 @@
2
2
 
3
3
  module Mihari
4
4
  module Analyzers
5
+ #
6
+ # urlscan.io analyzer
7
+ #
5
8
  class Urlscan < Base
6
9
  SUPPORTED_DATA_TYPES = %w[url domain ip].freeze
7
10
 
@@ -44,7 +47,7 @@ module Mihari
44
47
  private
45
48
 
46
49
  def client
47
- @client ||= Clients::UrlScan.new(
50
+ Clients::Urlscan.new(
48
51
  api_key: api_key,
49
52
  pagination_interval: pagination_interval,
50
53
  timeout: timeout
@@ -2,6 +2,9 @@
2
2
 
3
3
  module Mihari
4
4
  module Analyzers
5
+ #
6
+ # VirusTotal analyzer
7
+ #
5
8
  class VirusTotal < Base
6
9
  include Mixins::Refang
7
10
 
@@ -51,7 +54,7 @@ module Mihari
51
54
  private
52
55
 
53
56
  def client
54
- @client = Clients::VirusTotal.new(api_key: api_key)
57
+ Clients::VirusTotal.new(api_key: api_key)
55
58
  end
56
59
 
57
60
  #
@@ -2,6 +2,9 @@
2
2
 
3
3
  module Mihari
4
4
  module Analyzers
5
+ #
6
+ # VirusTotal Intelligence analyzer
7
+ #
5
8
  class VirusTotalIntelligence < Base
6
9
  # @return [String, nil]
7
10
  attr_reader :api_key
@@ -49,7 +52,7 @@ module Mihari
49
52
  # @return [::VirusTotal::API]
50
53
  #
51
54
  def client
52
- @client = Clients::VirusTotal.new(
55
+ Clients::VirusTotal.new(
53
56
  api_key: api_key,
54
57
  pagination_interval: pagination_interval,
55
58
  timeout: timeout
@@ -2,6 +2,9 @@
2
2
 
3
3
  module Mihari
4
4
  module Analyzers
5
+ #
6
+ # ZoomEye analyzer
7
+ #
5
8
  class ZoomEye < Base
6
9
  # @return [String, nil]
7
10
  attr_reader :api_key
@@ -53,7 +56,7 @@ module Mihari
53
56
  end
54
57
 
55
58
  def client
56
- @client ||= Clients::ZoomEye.new(
59
+ Clients::ZoomEye.new(
57
60
  api_key: api_key,
58
61
  pagination_interval: pagination_interval,
59
62
  timeout: timeout
@@ -63,7 +66,7 @@ module Mihari
63
66
  #
64
67
  # Convert responses into an array of String
65
68
  #
66
- # @param [Hash] response
69
+ # @param [Hash] res
67
70
  #
68
71
  # @return [Array<Mihari::Models::Artifact>]
69
72
  #
@@ -4,6 +4,9 @@ require "mihari/commands/alert"
4
4
 
5
5
  module Mihari
6
6
  module CLI
7
+ #
8
+ # Alert CLI class (mihari alert ...)
9
+ #
7
10
  class Alert < Base
8
11
  include Mihari::Commands::Alert
9
12
  end
@@ -2,6 +2,9 @@
2
2
 
3
3
  module Mihari
4
4
  module CLI
5
+ #
6
+ # Base class for Thor classes
7
+ #
5
8
  class Base < Thor
6
9
  class << self
7
10
  def exit_on_failure?
@@ -4,6 +4,9 @@ require "mihari/commands/database"
4
4
 
5
5
  module Mihari
6
6
  module CLI
7
+ #
8
+ # Database CLI class (mihari db ...)
9
+ #
7
10
  class Database < Base
8
11
  include Mihari::Commands::Database
9
12
  end
@@ -19,6 +19,9 @@ require "mihari/cli/rule"
19
19
 
20
20
  module Mihari
21
21
  module CLI
22
+ #
23
+ # Main CLI class
24
+ #
22
25
  class Main < Base
23
26
  class_option :debug, desc: "Sets up debug mode", aliases: ["-d"], type: :boolean
24
27
  class_around :safe_execute
@@ -4,6 +4,9 @@ require "mihari/commands/rule"
4
4
 
5
5
  module Mihari
6
6
  module CLI
7
+ #
8
+ # Rule CLI class (mihari rule ...)
9
+ #
7
10
  class Rule < Base
8
11
  include Mihari::Commands::Rule
9
12
  end
@@ -2,6 +2,9 @@
2
2
 
3
3
  module Mihari
4
4
  module Clients
5
+ #
6
+ # Base class for API clients
7
+ #
5
8
  class Base
6
9
  # @return [String]
7
10
  attr_reader :base_url
@@ -2,6 +2,9 @@
2
2
 
3
3
  module Mihari
4
4
  module Clients
5
+ #
6
+ # BinaryEdge API client
7
+ #
5
8
  class BinaryEdge < Base
6
9
  #
7
10
  # @param [String] base_url
@@ -27,7 +30,7 @@ module Mihari
27
30
  # @param [Integer] page Default 1, Maximum: 500
28
31
  # @param [Integer, nil] only_ips If selected, only output IP addresses, ports and protocols.
29
32
  #
30
- # @return [Structs::BinaryEdge::Response]
33
+ # @return [Mihari::Structs::BinaryEdge::Response]
31
34
  #
32
35
  def search(query, page: 1, only_ips: nil)
33
36
  params = {
@@ -45,7 +48,7 @@ module Mihari
45
48
  # @param [Integer, nil] only_ips
46
49
  # @param [Integer] pagination_limit
47
50
  #
48
- # @return [Enumerable<Structs::BinaryEdge::Response.>]
51
+ # @return [Enumerable<Mihari::Structs::BinaryEdge::Response>]
49
52
  #
50
53
  def search_with_pagination(query, only_ips: nil, pagination_limit: Mihari.config.pagination_limit)
51
54
  Enumerator.new do |y|
@@ -4,6 +4,9 @@ require "base64"
4
4
 
5
5
  module Mihari
6
6
  module Clients
7
+ #
8
+ # Censys API client
9
+ #
7
10
  class Censys < Base
8
11
  #
9
12
  # @param [String] base_url
@@ -36,10 +39,10 @@ module Mihari
36
39
  # For more details, see our documentation: https://search.censys.io/api/v2/docs
37
40
  #
38
41
  # @param [String] query the query to be executed.
39
- # @params [Integer, nil] per_page the number of results to be returned for each page.
40
- # @params [Integer, nil] cursor the cursor of the desired result set.
42
+ # @param [Integer, nil] per_page the number of results to be returned for each page.
43
+ # @param [Integer, nil] cursor the cursor of the desired result set.
41
44
  #
42
- # @return [Structs::Censys::Response]
45
+ # @return [Mihari::Structs::Censys::Response]
43
46
  #
44
47
  def search(query, per_page: nil, cursor: nil)
45
48
  params = { q: query, per_page: per_page, cursor: cursor }.compact
@@ -52,7 +55,7 @@ module Mihari
52
55
  # @param [Integer, nil] per_page
53
56
  # @param [Integer] pagination_limit
54
57
  #
55
- # @return [Enumerable<Structs::Censys::Response>]
58
+ # @return [Enumerable<Mihari::Structs::Censys::Response>]
56
59
  #
57
60
  def search_with_pagination(query, per_page: nil, pagination_limit: Mihari.config.pagination_limit)
58
61
  cursor = nil
@@ -4,6 +4,9 @@ require "base64"
4
4
 
5
5
  module Mihari
6
6
  module Clients
7
+ #
8
+ # CIRCL passive DNS/SSL API client
9
+ #
7
10
  class CIRCL < Base
8
11
  #
9
12
  # @param [String] base_url
@@ -2,6 +2,9 @@
2
2
 
3
3
  module Mihari
4
4
  module Clients
5
+ #
6
+ # crt.sh API client
7
+ #
5
8
  class Crtsh < Base
6
9
  #
7
10
  # @param [String] base_url
@@ -2,6 +2,9 @@
2
2
 
3
3
  module Mihari
4
4
  module Clients
5
+ #
6
+ # DNSTwister API client
7
+ #
5
8
  class DNSTwister < Base
6
9
  #
7
10
  # @param [String] base_url
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "base64"
4
+
5
+ module Mihari
6
+ module Clients
7
+ #
8
+ # Fofa API client
9
+ #
10
+ class Fofa < Base
11
+ PAGE_SIZE = 10_000
12
+
13
+ # @return [String]
14
+ attr_reader :api_key
15
+
16
+ # @return [String]
17
+ attr_reader :email
18
+
19
+ #
20
+ # @param [String] base_url
21
+ # @param [String, nil] api_key
22
+ # @param [String, nil] email
23
+ # @param [Hash] headers
24
+ # @param [Integer] pagination_interval
25
+ # @param [Integer, nil] timeout
26
+ #
27
+ # @param [Object] email
28
+ def initialize(
29
+ base_url = "https://fofa.info/",
30
+ api_key:,
31
+ email:,
32
+ headers: {},
33
+ pagination_interval: Mihari.config.pagination_interval,
34
+ timeout: nil
35
+ )
36
+ raise(ArgumentError, "api_key is required") unless api_key
37
+ raise(ArgumentError, "email is required") unless email
38
+
39
+ @api_key = api_key
40
+ @email = email
41
+
42
+ super(base_url, headers: headers, pagination_interval: pagination_interval, timeout: timeout)
43
+ end
44
+
45
+ #
46
+ # @param [String] query
47
+ # @param [Integer] size
48
+ # @param [Integer] page
49
+ #
50
+ # @return [Mihari::Structs::Fofa::Response]
51
+ #
52
+ def search(query, page:, size: PAGE_SIZE)
53
+ qbase64 = Base64.urlsafe_encode64(query)
54
+ params = { qbase64: qbase64, size: size, page: page, email: email, key: api_key }.compact
55
+ res = get("/api/v1/search/all", params: params)
56
+ Structs::Fofa::Response.from_dynamic! JSON.parse(res.body.to_s)
57
+ end
58
+
59
+ #
60
+ # @param [String] query
61
+ # @param [Integer] size
62
+ # @param [Integer] pagination_limit
63
+ #
64
+ # @return [Enumerable<Mihari::Structs::Fofa::Response>]
65
+ #
66
+ def search_with_pagination(query, size: PAGE_SIZE, pagination_limit: Mihari.config.pagination_limit)
67
+ Enumerator.new do |y|
68
+ (1..pagination_limit).each do |page|
69
+ res = search(query, page: page, size: size)
70
+
71
+ y.yield res
72
+
73
+ break if res.error
74
+
75
+ break if (res.results || []).length < size
76
+
77
+ sleep_pagination_interval
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
@@ -2,6 +2,9 @@
2
2
 
3
3
  module Mihari
4
4
  module Clients
5
+ #
6
+ # GreyNoise API client
7
+ #
5
8
  class GreyNoise < Base
6
9
  PAGE_SIZE = 10_000
7
10
 
@@ -32,7 +35,7 @@ module Mihari
32
35
  # @param [Integer] size Maximum amount of results to grab
33
36
  # @param [Integer, nil] scroll Scroll token to paginate through results
34
37
  #
35
- # @return [Hash]
38
+ # @return [Mihari::Structs::GreyNoise::Response]
36
39
  #
37
40
  def gnql_search(query, size: PAGE_SIZE, scroll: nil)
38
41
  params = { query: query, size: size, scroll: scroll }.compact
@@ -45,7 +48,7 @@ module Mihari
45
48
  # @param [Integer] size
46
49
  # @param [Integer] pagination_limit
47
50
  #
48
- # @return [Enumerable<Structs::GreyNoise::Response>]
51
+ # @return [Enumerable<Mihari::Structs::GreyNoise::Response>]
49
52
  #
50
53
  def gnql_search_with_pagination(query, size: PAGE_SIZE, pagination_limit: Mihari.config.pagination_limit)
51
54
  scroll = nil
@@ -4,6 +4,9 @@ require "base64"
4
4
 
5
5
  module Mihari
6
6
  module Clients
7
+ #
8
+ # hunter.how API client
9
+ #
7
10
  class HunterHow < Base
8
11
  PAGE_SIZE = 100
9
12
 
@@ -38,7 +41,7 @@ module Mihari
38
41
  # @param [String] start_time
39
42
  # @param [String] end_time
40
43
  #
41
- # @return [Structs::HunterHow::Response]
44
+ # @return [Mihari::Structs::HunterHow::Response]
42
45
  #
43
46
  def search(query, start_time:, end_time:, page: 1, page_size: PAGE_SIZE)
44
47
  params = {
@@ -60,7 +63,7 @@ module Mihari
60
63
  # @param [String] start_time
61
64
  # @param [String] end_time
62
65
  #
63
- # @return [Enumerable<Structs::HunterHow::Response>]
66
+ # @return [Enumerable<Mihari::Structs::HunterHow::Response>]
64
67
  #
65
68
  def search_with_pagination(
66
69
  query,
@@ -2,6 +2,9 @@
2
2
 
3
3
  module Mihari
4
4
  module Clients
5
+ #
6
+ # MISP API client
7
+ #
5
8
  class MISP < Base
6
9
  #
7
10
  # @param [String] base_url