mihari 5.4.2 → 5.4.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/frontend/package-lock.json +2399 -1504
  3. data/frontend/package.json +22 -22
  4. data/lib/mihari/analyzers/base.rb +25 -14
  5. data/lib/mihari/analyzers/binaryedge.rb +2 -48
  6. data/lib/mihari/analyzers/censys.rb +4 -20
  7. data/lib/mihari/analyzers/circl.rb +3 -27
  8. data/lib/mihari/analyzers/crtsh.rb +2 -17
  9. data/lib/mihari/analyzers/dnstwister.rb +2 -4
  10. data/lib/mihari/analyzers/greynoise.rb +5 -4
  11. data/lib/mihari/analyzers/hunterhow.rb +8 -23
  12. data/lib/mihari/analyzers/onyphe.rb +5 -39
  13. data/lib/mihari/analyzers/otx.rb +3 -39
  14. data/lib/mihari/analyzers/passivetotal.rb +4 -42
  15. data/lib/mihari/analyzers/pulsedive.rb +1 -1
  16. data/lib/mihari/analyzers/rule.rb +18 -13
  17. data/lib/mihari/analyzers/securitytrails.rb +4 -42
  18. data/lib/mihari/analyzers/shodan.rb +7 -39
  19. data/lib/mihari/analyzers/urlscan.rb +3 -39
  20. data/lib/mihari/analyzers/virustotal.rb +1 -1
  21. data/lib/mihari/analyzers/virustotal_intelligence.rb +2 -25
  22. data/lib/mihari/analyzers/zoomeye.rb +18 -84
  23. data/lib/mihari/clients/base.rb +9 -1
  24. data/lib/mihari/clients/binaryedge.rb +26 -4
  25. data/lib/mihari/clients/censys.rb +32 -2
  26. data/lib/mihari/clients/circl.rb +28 -1
  27. data/lib/mihari/clients/crtsh.rb +7 -2
  28. data/lib/mihari/clients/dnstwister.rb +4 -2
  29. data/lib/mihari/clients/greynoise.rb +31 -4
  30. data/lib/mihari/clients/hunterhow.rb +41 -3
  31. data/lib/mihari/clients/onyphe.rb +25 -3
  32. data/lib/mihari/clients/otx.rb +40 -0
  33. data/lib/mihari/clients/passivetotal.rb +33 -15
  34. data/lib/mihari/clients/publsedive.rb +1 -1
  35. data/lib/mihari/clients/securitytrails.rb +44 -0
  36. data/lib/mihari/clients/shodan.rb +31 -3
  37. data/lib/mihari/clients/urlscan.rb +32 -6
  38. data/lib/mihari/clients/virustotal.rb +29 -4
  39. data/lib/mihari/clients/zoomeye.rb +53 -2
  40. data/lib/mihari/commands/alert.rb +42 -13
  41. data/lib/mihari/commands/rule.rb +11 -7
  42. data/lib/mihari/commands/search.rb +54 -22
  43. data/lib/mihari/commands/web.rb +1 -1
  44. data/lib/mihari/config.rb +6 -1
  45. data/lib/mihari/emitters/base.rb +9 -3
  46. data/lib/mihari/emitters/slack.rb +1 -1
  47. data/lib/mihari/enrichers/base.rb +13 -0
  48. data/lib/mihari/enrichers/google_public_dns.rb +16 -1
  49. data/lib/mihari/enrichers/ipinfo.rb +9 -13
  50. data/lib/mihari/enrichers/shodan.rb +1 -2
  51. data/lib/mihari/enrichers/whois.rb +2 -2
  52. data/lib/mihari/errors.rb +16 -10
  53. data/lib/mihari/feed/parser.rb +2 -2
  54. data/lib/mihari/models/artifact.rb +1 -1
  55. data/lib/mihari/models/autonomous_system.rb +11 -5
  56. data/lib/mihari/models/cpe.rb +10 -4
  57. data/lib/mihari/models/dns.rb +11 -16
  58. data/lib/mihari/models/geolocation.rb +11 -5
  59. data/lib/mihari/models/port.rb +10 -4
  60. data/lib/mihari/models/reverse_dns.rb +10 -4
  61. data/lib/mihari/models/whois.rb +4 -1
  62. data/lib/mihari/schemas/analyzer.rb +1 -0
  63. data/lib/mihari/services/alert_builder.rb +43 -0
  64. data/lib/mihari/services/alert_proxy.rb +7 -25
  65. data/lib/mihari/services/alert_runner.rb +9 -0
  66. data/lib/mihari/services/rule_builder.rb +47 -0
  67. data/lib/mihari/services/rule_proxy.rb +5 -61
  68. data/lib/mihari/services/rule_runner.rb +9 -4
  69. data/lib/mihari/structs/binaryedge.rb +89 -0
  70. data/lib/mihari/structs/censys.rb +11 -11
  71. data/lib/mihari/structs/greynoise.rb +17 -8
  72. data/lib/mihari/structs/onyphe.rb +7 -7
  73. data/lib/mihari/structs/shodan.rb +7 -6
  74. data/lib/mihari/structs/urlscan.rb +4 -6
  75. data/lib/mihari/structs/virustotal_intelligence.rb +4 -6
  76. data/lib/mihari/type_checker.rb +1 -1
  77. data/lib/mihari/version.rb +1 -1
  78. data/lib/mihari/web/endpoints/alerts.rb +33 -15
  79. data/lib/mihari/web/endpoints/artifacts.rb +53 -25
  80. data/lib/mihari/web/endpoints/configs.rb +2 -2
  81. data/lib/mihari/web/endpoints/ip_addresses.rb +3 -5
  82. data/lib/mihari/web/endpoints/rules.rb +97 -71
  83. data/lib/mihari/web/endpoints/tags.rb +15 -5
  84. data/lib/mihari/web/public/assets/index-ef33a6cd.js +1738 -0
  85. data/lib/mihari/web/public/index.html +1 -1
  86. data/lib/mihari/web/public/redoc-static.html +419 -382
  87. data/lib/mihari.rb +4 -0
  88. data/mihari.gemspec +10 -9
  89. metadata +38 -21
  90. data/lib/mihari/web/public/assets/index-4d7eda9f.js +0 -1738
@@ -17,15 +17,15 @@
17
17
  "@fortawesome/fontawesome-svg-core": "^6.4.2",
18
18
  "@fortawesome/free-solid-svg-icons": "^6.4.2",
19
19
  "@fortawesome/vue-fontawesome": "^3.0.3",
20
- "@vueuse/core": "^10.3.0",
21
- "@vueuse/router": "^10.3.0",
22
- "ace-builds": "^1.24.1",
23
- "axios": "^1.4.0",
20
+ "@vueuse/core": "^10.4.1",
21
+ "@vueuse/router": "^10.4.1",
22
+ "ace-builds": "^1.28.0",
23
+ "axios": "^1.5.0",
24
24
  "bulma": "^0.9.4",
25
25
  "bulma-helpers": "^0.4.3",
26
- "dayjs": "^1.11.9",
26
+ "dayjs": "^1.11.10",
27
27
  "font-awesome-animation": "^1.1.1",
28
- "js-sha256": "^0.9.0",
28
+ "js-sha256": "^0.10.1",
29
29
  "truncate": "^3.0.0",
30
30
  "ts-dedent": "^2.2.0",
31
31
  "url-parse": "^1.5.10",
@@ -33,24 +33,24 @@
33
33
  "vue": "^3.3.4",
34
34
  "vue-concurrency": "4.0.1",
35
35
  "vue-json-pretty": "^2.2.4",
36
- "vue-router": "^4.2.4",
36
+ "vue-router": "^4.2.5",
37
37
  "vue3-ace-editor": "^2.2.3"
38
38
  },
39
39
  "devDependencies": {
40
- "@redocly/cli": "1.0.2",
41
- "@rushstack/eslint-patch": "^1.3.3",
42
- "@tsconfig/node20": "^20.1.1",
43
- "@types/jsdom": "^21.1.1",
44
- "@types/node": "^20.5.1",
45
- "@types/url-parse": "^1.4.8",
46
- "@typescript-eslint/eslint-plugin": "^6.4.0",
47
- "@typescript-eslint/parser": "^6.4.0",
48
- "@vitejs/plugin-vue": "^4.3.1",
40
+ "@redocly/cli": "1.2.0",
41
+ "@rushstack/eslint-patch": "^1.4.0",
42
+ "@tsconfig/node20": "^20.1.2",
43
+ "@types/jsdom": "^21.1.3",
44
+ "@types/node": "^20.6.4",
45
+ "@types/url-parse": "^1.4.9",
46
+ "@typescript-eslint/eslint-plugin": "^6.7.2",
47
+ "@typescript-eslint/parser": "^6.7.2",
48
+ "@vitejs/plugin-vue": "^4.3.4",
49
49
  "@vue/eslint-config-prettier": "^8.0.0",
50
- "@vue/eslint-config-typescript": "^11.0.3",
50
+ "@vue/eslint-config-typescript": "^12.0.0",
51
51
  "@vue/test-utils": "2.4.1",
52
52
  "@vue/tsconfig": "^0.4.0",
53
- "eslint": "^8.47.0",
53
+ "eslint": "^8.50.0",
54
54
  "eslint-config-prettier": "^9.0.0",
55
55
  "eslint-plugin-prettier": "^5.0.0",
56
56
  "eslint-plugin-simple-import-sort": "^10.0.0",
@@ -58,10 +58,10 @@
58
58
  "husky": "^8.0.3",
59
59
  "jsdom": "^22.1.0",
60
60
  "npm-run-all": "^4.1.5",
61
- "prettier": "^3.0.2",
62
- "typescript": "~5.1.6",
61
+ "prettier": "^3.0.3",
62
+ "typescript": "~5.2.2",
63
63
  "vite": "^4.4.9",
64
- "vitest": "^0.34.2",
65
- "vue-tsc": "^1.8.8"
64
+ "vitest": "^0.34.5",
65
+ "vue-tsc": "^1.8.13"
66
66
  }
67
67
  }
@@ -3,6 +3,8 @@
3
3
  module Mihari
4
4
  module Analyzers
5
5
  class Base
6
+ include Dry::Monads[:result, :try]
7
+
6
8
  include Mixins::Configurable
7
9
  include Mixins::Retriable
8
10
 
@@ -25,28 +27,38 @@ module Mihari
25
27
  # @return [Integer, nil]
26
28
  #
27
29
  def interval
28
- @interval ||= options[:interval]
30
+ options[:interval]
29
31
  end
30
32
 
31
33
  #
32
34
  # @return [Integer]
33
35
  #
34
36
  def retry_interval
35
- @retry_interval ||= options[:retry_interval] || Mihari.config.retry_interval
37
+ options[:retry_interval] || Mihari.config.retry_interval
36
38
  end
37
39
 
38
40
  #
39
41
  # @return [Integer]
40
42
  #
41
43
  def retry_times
42
- @retry_times ||= options[:retry_times] || Mihari.config.retry_times
44
+ options[:retry_times] || Mihari.config.retry_times
43
45
  end
44
46
 
45
47
  #
46
48
  # @return [Integer]
47
49
  #
48
50
  def pagination_limit
49
- @pagination_limit ||= options[:pagination_limit] || Mihari.config.pagination_limit
51
+ options[:pagination_limit] || Mihari.config.pagination_limit
52
+ end
53
+
54
+ #
55
+ # @return [Boolean]
56
+ #
57
+ def ignore_error?
58
+ ignore_error = options[:ignore_error]
59
+ return ignore_error unless ignore_error.nil?
60
+
61
+ Mihari.config.ignore_error
50
62
  end
51
63
 
52
64
  # @return [Array<String>, Array<Mihari::Artifact>]
@@ -63,7 +75,7 @@ module Mihari
63
75
  #
64
76
  def normalized_artifacts
65
77
  retry_on_error(times: retry_times, interval: retry_interval) do
66
- @normalized_artifacts ||= artifacts.compact.sort.map do |artifact|
78
+ artifacts.compact.sort.map do |artifact|
67
79
  # No need to set data_type manually
68
80
  # It is set automatically in #initialize
69
81
  artifact = artifact.is_a?(Artifact) ? artifact : Artifact.new(data: artifact)
@@ -73,6 +85,13 @@ module Mihari
73
85
  end
74
86
  end
75
87
 
88
+ #
89
+ # @return [Dry::Monads::Result::Success<Array<Mihari::Artifact>>, Dry::Monads::Result::Failure]
90
+ #
91
+ def result
92
+ Try[StandardError] { normalized_artifacts }.to_result
93
+ end
94
+
76
95
  # @return [String]
77
96
  def class_name
78
97
  self.class.to_s.split("::").last
@@ -80,12 +99,6 @@ module Mihari
80
99
 
81
100
  alias_method :source, :class_name
82
101
 
83
- private
84
-
85
- def sleep_interval
86
- sleep(interval) if interval
87
- end
88
-
89
102
  class << self
90
103
  #
91
104
  # Initialize an analyzer by query params
@@ -101,9 +114,7 @@ module Mihari
101
114
  query = copied[:query]
102
115
 
103
116
  # delete analyzer and query
104
- %i[analyzer query].each do |key|
105
- copied.delete key
106
- end
117
+ %i[analyzer query].each { |key| copied.delete key }
107
118
 
108
119
  copied[:options] = copied[:options] || nil
109
120
 
@@ -18,16 +18,7 @@ module Mihari
18
18
  end
19
19
 
20
20
  def artifacts
21
- results = search
22
- return [] unless results || results.empty?
23
-
24
- results.map do |result|
25
- events = result["events"] || []
26
- events.filter_map do |event|
27
- data = event.dig("target", "ip")
28
- data.nil? ? nil : Artifact.new(data: data, source: source, metadata: event)
29
- end
30
- end.flatten
21
+ client.search_with_pagination(query, pagination_limit: pagination_limit).map(&:artifacts).flatten
31
22
  end
32
23
 
33
24
  def configuration_keys
@@ -36,49 +27,12 @@ module Mihari
36
27
 
37
28
  private
38
29
 
39
- PAGE_SIZE = 20
40
-
41
- #
42
- # Search with pagination
43
- #
44
- # @param [Integer] page
45
- #
46
- # @return [Hash]
47
- #
48
- def search_with_page(page: 1)
49
- client.search(query, page: page)
50
- rescue StatusCodeError => e
51
- raise RetryableError, e if e.message.include?("Request time limit exceeded")
52
-
53
- raise e
54
- end
55
-
56
- #
57
- # Search
58
- #
59
- # @return [Array<Hash>]
60
- #
61
- def search
62
- responses = []
63
- (1..pagination_limit).each do |page|
64
- res = search_with_page(page: page)
65
- total = res["total"].to_i
66
-
67
- responses << res
68
- break if total <= page * PAGE_SIZE
69
-
70
- # sleep #{interval} seconds to avoid the rate limitation (if it is set)
71
- sleep_interval
72
- end
73
- responses
74
- end
75
-
76
30
  #
77
31
  #
78
32
  # @return [Mihari::Clients::BinaryEdge]
79
33
  #
80
34
  def client
81
- @client ||= Clients::BinaryEdge.new(api_key: api_key)
35
+ @client ||= Clients::BinaryEdge.new(api_key: api_key, interval: interval)
82
36
  end
83
37
  end
84
38
  end
@@ -27,25 +27,9 @@ module Mihari
27
27
  # @return [Array<Mihari::Artifact>]
28
28
  #
29
29
  def artifacts
30
- artifacts = []
31
-
32
- cursor = nil
33
- pagination_limit.times do
34
- response = client.search(query, cursor: cursor)
35
- artifacts << response.result.to_artifacts
36
- cursor = response.result.links.next
37
- # NOTE: Censys's search API is unstable recently
38
- # it may returns empty links or empty string cursors
39
- # - Empty links: "links": {}
40
- # - Empty cursors: "links": { "next": "", "prev": "" }
41
- # So it needs to check both cases
42
- break if cursor.nil? || cursor.empty?
43
-
44
- # sleep #{interval} seconds to avoid the rate limitation (if it is set)
45
- sleep_interval
46
- end
47
-
48
- artifacts.flatten.uniq(&:data)
30
+ client.search_with_pagination(query, pagination_limit: pagination_limit).map do |res|
31
+ res.result.artifacts
32
+ end.flatten.uniq(&:data)
49
33
  end
50
34
 
51
35
  #
@@ -68,7 +52,7 @@ module Mihari
68
52
  # @return [Mihari::Clients::Censys]
69
53
  #
70
54
  def client
71
- @client ||= Clients::Censys.new(id: id, secret: secret)
55
+ @client ||= Clients::Censys.new(id: id, secret: secret, interval: interval)
72
56
  end
73
57
 
74
58
  #
@@ -32,11 +32,11 @@ module Mihari
32
32
  def artifacts
33
33
  case type
34
34
  when "domain"
35
- passive_dns_search
35
+ client.passive_dns_search query
36
36
  when "hash"
37
- passive_ssl_search
37
+ client.passive_ssl_search query
38
38
  else
39
- raise InvalidInputError, "#{@query}(type: #{@type || "unknown"}) is not supported."
39
+ raise ValueError, "#{@query}(type: #{@type || "unknown"}) is not supported."
40
40
  end
41
41
  end
42
42
 
@@ -54,30 +54,6 @@ module Mihari
54
54
  @client ||= Clients::CIRCL.new(username: username, password: password)
55
55
  end
56
56
 
57
- #
58
- # Passive DNS search
59
- #
60
- # @return [Array<String>]
61
- #
62
- def passive_dns_search
63
- results = client.dns_query(query)
64
- results.filter_map do |result|
65
- type = result["rrtype"]
66
- (type == "A") ? result["rdata"] : nil
67
- end.uniq
68
- end
69
-
70
- #
71
- # Passive SSL search
72
- #
73
- # @return [Array<String>]
74
- #
75
- def passive_ssl_search
76
- result = client.ssl_cquery(query)
77
- seen = result["seen"] || []
78
- seen.uniq
79
- end
80
-
81
57
  def username?
82
58
  !username.nil?
83
59
  end
@@ -18,13 +18,8 @@ module Mihari
18
18
  end
19
19
 
20
20
  def artifacts
21
- results = search
22
- results.map do |result|
23
- values = result["name_value"].to_s.lines.map(&:chomp)
24
- values.map do |value|
25
- Artifact.new(data: value, source: source, metadata: result)
26
- end
27
- end.flatten
21
+ exclude = exclude_expired ? "expired" : nil
22
+ client.search(query, exclude: exclude)
28
23
  end
29
24
 
30
25
  private
@@ -35,16 +30,6 @@ module Mihari
35
30
  def client
36
31
  @client ||= Mihari::Clients::Crtsh.new
37
32
  end
38
-
39
- #
40
- # Search
41
- #
42
- # @return [Array<Hash>]
43
- #
44
- def search
45
- exclude = exclude_expired ? "expired" : nil
46
- client.search(query, exclude: exclude)
47
- end
48
33
  end
49
34
  end
50
35
  end
@@ -19,11 +19,9 @@ module Mihari
19
19
  end
20
20
 
21
21
  def artifacts
22
- raise InvalidInputError, "#{query}(type: #{type || "unknown"}) is not supported." unless valid_type?
22
+ raise ValueError, "#{query}(type: #{type || "unknown"}) is not supported." unless valid_type?
23
23
 
24
- res = client.fuzz(query)
25
- fuzzy_domains = res["fuzzy_domains"] || []
26
- domains = fuzzy_domains.map { |domain| domain["domain"] }
24
+ domains = client.fuzz(query)
27
25
  Parallel.map(domains) do |domain|
28
26
  resolvable?(domain) ? domain : nil
29
27
  end.compact
@@ -3,8 +3,6 @@
3
3
  module Mihari
4
4
  module Analyzers
5
5
  class GreyNoise < Base
6
- PAGE_SIZE = 10_000
7
-
8
6
  # @return [String, nil]
9
7
  attr_reader :api_key
10
8
 
@@ -20,7 +18,10 @@ module Mihari
20
18
  end
21
19
 
22
20
  def artifacts
23
- client.gnql_search(query, size: PAGE_SIZE).to_artifacts
21
+ client.gnql_search_with_pagination(
22
+ query,
23
+ pagination_limit: pagination_limit
24
+ ).map(&:artifacts).flatten
24
25
  end
25
26
 
26
27
  def configuration_keys
@@ -30,7 +31,7 @@ module Mihari
30
31
  private
31
32
 
32
33
  def client
33
- @client ||= Clients::GreyNoise.new(api_key: api_key)
34
+ @client ||= Clients::GreyNoise.new(api_key: api_key, interval: interval)
34
35
  end
35
36
  end
36
37
  end
@@ -30,25 +30,13 @@ module Mihari
30
30
  # @return [Array<Mihari::Artifact>]
31
31
  #
32
32
  def artifacts
33
- artifacts = []
34
-
35
- (1..pagination_limit).each do |page|
36
- res = client.search(
37
- query,
38
- page: page,
39
- page_size: PAGE_SIZE,
40
- start_time: start_time.strftime("%Y-%m-%d"),
41
- end_time: end_time.strftime("%Y-%m-%d")
42
- )
43
-
44
- artifacts << res.data.artifacts
45
-
46
- break if res.data.list.length < PAGE_SIZE
47
-
48
- sleep_interval
49
- end
50
-
51
- artifacts.flatten
33
+ client.search_with_pagination(
34
+ query,
35
+ start_time: start_time.strftime("%Y-%m-%d"),
36
+ end_time: end_time.strftime("%Y-%m-%d")
37
+ ).map do |res|
38
+ res.data.artifacts
39
+ end.flatten
52
40
  end
53
41
 
54
42
  def configuration_keys
@@ -57,11 +45,8 @@ module Mihari
57
45
 
58
46
  private
59
47
 
60
- # @return [Integer]
61
- PAGE_SIZE = 100
62
-
63
48
  def client
64
- @client ||= Clients::HunterHow.new(api_key: api_key)
49
+ @client ||= Clients::HunterHow.new(api_key: api_key, interval: interval)
65
50
  end
66
51
  end
67
52
  end
@@ -20,10 +20,10 @@ module Mihari
20
20
  end
21
21
 
22
22
  def artifacts
23
- responses = search
24
- return [] unless responses
25
-
26
- responses.map(&:to_artifacts).flatten
23
+ client.datascan_with_pagination(
24
+ query,
25
+ pagination_limit: pagination_limit
26
+ ).map(&:artifacts).flatten
27
27
  end
28
28
 
29
29
  def configuration_keys
@@ -32,42 +32,8 @@ module Mihari
32
32
 
33
33
  private
34
34
 
35
- PAGE_SIZE = 10
36
-
37
35
  def client
38
- @client ||= Clients::Onyphe.new(api_key: api_key)
39
- end
40
-
41
- #
42
- # Search with pagination
43
- #
44
- # @param [String] query
45
- # @param [Integer] page
46
- #
47
- # @return [Structs::Onyphe::Response]
48
- #
49
- def search_with_page(query, page: 1)
50
- client.datascan(query, page: page)
51
- end
52
-
53
- #
54
- # Search
55
- #
56
- # @return [Array<Structs::Onyphe::Response>]
57
- #
58
- def search
59
- responses = []
60
- (1..pagination_limit).each do |page|
61
- res = search_with_page(query, page: page)
62
- responses << res
63
-
64
- total = res.total
65
- break if total <= page * PAGE_SIZE
66
-
67
- # sleep #{interval} seconds to avoid the rate limitation (if it is set)
68
- sleep_interval
69
- end
70
- responses
36
+ @client ||= Clients::Onyphe.new(api_key: api_key, interval: interval)
71
37
  end
72
38
  end
73
39
  end
@@ -27,11 +27,11 @@ module Mihari
27
27
  def artifacts
28
28
  case type
29
29
  when "domain"
30
- domain_search
30
+ client.domain_search(query)
31
31
  when "ip"
32
- ip_search
32
+ client.ip_search(query)
33
33
  else
34
- raise InvalidInputError, "#{query}(type: #{type || "unknown"}) is not supported." unless valid_type?
34
+ raise ValueError, "#{query}(type: #{type || "unknown"}) is not supported." unless valid_type?
35
35
  end
36
36
  end
37
37
 
@@ -53,42 +53,6 @@ module Mihari
53
53
  def valid_type?
54
54
  %w[ip domain].include? type
55
55
  end
56
-
57
- #
58
- # Domain search
59
- #
60
- # @return [Array<String>]
61
- #
62
- def domain_search
63
- res = client.query_by_domain(query)
64
- return [] if res.nil?
65
-
66
- records = res["passive_dns"] || []
67
- records.filter_map do |record|
68
- record_type = record["record_type"]
69
- address = record["address"]
70
-
71
- address if record_type == "A"
72
- end.uniq
73
- end
74
-
75
- #
76
- # IP search
77
- #
78
- # @return [Array<String>]
79
- #
80
- def ip_search
81
- res = client.query_by_ip(query)
82
- return [] if res.nil?
83
-
84
- records = res["passive_dns"] || []
85
- records.filter_map do |record|
86
- record_type = record["record_type"]
87
- hostname = record["hostname"]
88
-
89
- hostname if record_type == "A"
90
- end.uniq
91
- end
92
56
  end
93
57
  end
94
58
  end
@@ -32,13 +32,13 @@ module Mihari
32
32
  def artifacts
33
33
  case type
34
34
  when "domain", "ip"
35
- passive_dns_search
35
+ client.passive_dns_search query
36
36
  when "mail"
37
- reverse_whois_search
37
+ client.reverse_whois_search query
38
38
  when "hash"
39
- ssl_search
39
+ client.ssl_search query
40
40
  else
41
- raise InvalidInputError, "#{query}(type: #{type || "unknown"}) is not supported." unless valid_type?
41
+ raise ValueError, "#{query}(type: #{type || "unknown"}) is not supported." unless valid_type?
42
42
  end
43
43
  end
44
44
 
@@ -65,44 +65,6 @@ module Mihari
65
65
  %w[ip domain mail hash].include? type
66
66
  end
67
67
 
68
- #
69
- # Passive DNS search
70
- #
71
- # @return [Array<String>]
72
- #
73
- def passive_dns_search
74
- res = client.passive_dns_search(query)
75
- res["results"] || []
76
- end
77
-
78
- #
79
- # Reverse whois search
80
- #
81
- # @return [Array<Mihari::Artifact>]
82
- #
83
- def reverse_whois_search
84
- res = client.reverse_whois_search(query: query, field: "email")
85
- results = res["results"] || []
86
- results.map do |result|
87
- data = result["domain"]
88
- Artifact.new(data: data, source: source, metadata: result)
89
- end.flatten
90
- end
91
-
92
- #
93
- # Passive SSL search
94
- #
95
- # @return [Array<Mihari::Artifact>]
96
- #
97
- def ssl_search
98
- res = client.ssl_search(query)
99
- results = res["results"] || []
100
- results.map do |result|
101
- data = result["ipAddresses"]
102
- data.map { |d| Artifact.new(data: d, source: source, metadata: result) }
103
- end.flatten
104
- end
105
-
106
68
  def username?
107
69
  !username.nil?
108
70
  end
@@ -25,7 +25,7 @@ module Mihari
25
25
  end
26
26
 
27
27
  def artifacts
28
- raise InvalidInputError, "#{query}(type: #{type || "unknown"}) is not supported." unless valid_type?
28
+ raise ValueError, "#{query}(type: #{type || "unknown"}) is not supported." unless valid_type?
29
29
 
30
30
  indicator = client.get_indicator(query)
31
31
  iid = indicator["iid"]