mihari 6.0.0 → 6.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +4 -0
- data/lib/mihari/actor.rb +4 -6
- data/lib/mihari/analyzers/base.rb +10 -3
- data/lib/mihari/analyzers/circl.rb +1 -1
- data/lib/mihari/analyzers/dnstwister.rb +1 -1
- data/lib/mihari/analyzers/hunterhow.rb +1 -1
- data/lib/mihari/analyzers/otx.rb +1 -1
- data/lib/mihari/analyzers/passivetotal.rb +1 -1
- data/lib/mihari/analyzers/pulsedive.rb +1 -1
- data/lib/mihari/analyzers/securitytrails.rb +1 -1
- data/lib/mihari/analyzers/virustotal.rb +1 -1
- data/lib/mihari/clients/google_public_dns.rb +31 -0
- data/lib/mihari/config.rb +10 -2
- data/lib/mihari/{type_checker.rb → data_type.rb} +32 -37
- data/lib/mihari/database.rb +8 -4
- data/lib/mihari/emitters/misp.rb +2 -2
- data/lib/mihari/emitters/slack.rb +5 -5
- data/lib/mihari/emitters/the_hive.rb +2 -2
- data/lib/mihari/enrichers/base.rb +2 -0
- data/lib/mihari/enrichers/google_public_dns.rb +4 -21
- data/lib/mihari/enrichers/ipinfo.rb +1 -0
- data/lib/mihari/enrichers/shodan.rb +1 -0
- data/lib/mihari/enrichers/whois.rb +11 -16
- data/lib/mihari/entities/artifact.rb +1 -0
- data/lib/mihari/mixins/falsepositive.rb +2 -2
- data/lib/mihari/models/artifact.rb +14 -6
- data/lib/mihari/models/dns.rb +3 -8
- data/lib/mihari/rule.rb +20 -7
- data/lib/mihari/schemas/options.rb +5 -1
- data/lib/mihari/structs/google_public_dns.rb +4 -8
- data/lib/mihari/version.rb +1 -1
- data/lib/mihari/web/app.rb +2 -2
- data/lib/mihari/web/public/assets/index-1d77cd61.js +1756 -0
- data/lib/mihari/web/public/assets/{index-56fc2187.css → index-4c8509ee.css} +1 -1
- data/lib/mihari/web/public/index.html +2 -2
- data/lib/mihari/web/public/redoc-static.html +5 -5
- data/lib/mihari.rb +10 -10
- data/mihari.gemspec +5 -4
- data/mkdocs.yml +1 -0
- data/requirements.txt +1 -1
- metadata +23 -50
- data/lib/mihari/web/public/assets/index-07cddfcd.js +0 -1750
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d49d8a079c765cb4b7ad7a08825a9d0bd4e9e21fbaf2c0f185c4f27e8f2f2ca6
|
4
|
+
data.tar.gz: aa693115eb1dacc09d13ca0942d859e24566c09a4cd6d702840ec9df6c3cc87a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e50a254b0c5565c3691cc34df0413258a1903f8864f0ced141fab63cb673f02998451723036917f2adf21f759ec3f0086b772e98a02ee0436869dd5846bf3427
|
7
|
+
data.tar.gz: 63738367f8edd23331518eb839c188dde8fb67257b83b5cd6a11e79dc725aa89b151753e7429515ff1b2f7c689da77adf4eac998241b7bfd04f88302aa52c923
|
data/.rubocop.yml
CHANGED
data/lib/mihari/actor.rb
CHANGED
@@ -65,11 +65,9 @@ module Mihari
|
|
65
65
|
|
66
66
|
def result(...)
|
67
67
|
Try[StandardError] do
|
68
|
-
retry_on_error(
|
69
|
-
|
70
|
-
|
71
|
-
exponential_backoff: retry_exponential_backoff
|
72
|
-
) { call(...) }
|
68
|
+
retry_on_error(times: retry_times, interval: retry_interval, exponential_backoff: retry_exponential_backoff) do
|
69
|
+
call(...)
|
70
|
+
end
|
73
71
|
end.to_result
|
74
72
|
end
|
75
73
|
|
@@ -78,7 +76,7 @@ module Mihari
|
|
78
76
|
# @return [String]
|
79
77
|
#
|
80
78
|
def class_key
|
81
|
-
to_s.split("::").last
|
79
|
+
to_s.split("::").last.downcase
|
82
80
|
end
|
83
81
|
|
84
82
|
#
|
@@ -37,10 +37,14 @@ module Mihari
|
|
37
37
|
# @return [Boolean]
|
38
38
|
#
|
39
39
|
def ignore_error?
|
40
|
-
|
41
|
-
|
40
|
+
options[:ignore_error] || Mihari.config.ignore_error
|
41
|
+
end
|
42
42
|
|
43
|
-
|
43
|
+
#
|
44
|
+
# @return [Boolean]
|
45
|
+
#
|
46
|
+
def parallel?
|
47
|
+
options[:parallel] || Mihari.config.parallel
|
44
48
|
end
|
45
49
|
|
46
50
|
# @return [Array<String>, Array<Mihari::Models::Artifact>]
|
@@ -60,7 +64,10 @@ module Mihari
|
|
60
64
|
# No need to set data_type manually
|
61
65
|
# It is set automatically in #initialize
|
62
66
|
artifact = artifact.is_a?(Models::Artifact) ? artifact : Models::Artifact.new(data: artifact)
|
67
|
+
|
63
68
|
artifact.source = self.class.class_key
|
69
|
+
artifact.query = query
|
70
|
+
|
64
71
|
artifact
|
65
72
|
end.select(&:valid?).uniq(&:data)
|
66
73
|
end
|
@@ -26,7 +26,7 @@ module Mihari
|
|
26
26
|
def initialize(query, options: nil, username: nil, password: nil)
|
27
27
|
super(refang(query), options: options)
|
28
28
|
|
29
|
-
@type =
|
29
|
+
@type = DataType.type(query)
|
30
30
|
|
31
31
|
@username = username || Mihari.config.circl_passive_username
|
32
32
|
@password = password || Mihari.config.circl_passive_password
|
@@ -22,7 +22,7 @@ module Mihari
|
|
22
22
|
# @param [Hash, nil] options
|
23
23
|
# @param [String, nil] api_key
|
24
24
|
#
|
25
|
-
def initialize(query, start_time
|
25
|
+
def initialize(query, start_time: nil, end_time: nil, options: nil, api_key: nil)
|
26
26
|
super(query, options: options)
|
27
27
|
|
28
28
|
@api_key = api_key || Mihari.config.hunterhow_api_key
|
data/lib/mihari/analyzers/otx.rb
CHANGED
@@ -26,7 +26,7 @@ module Mihari
|
|
26
26
|
def initialize(query, options: nil, api_key: nil, username: nil)
|
27
27
|
super(refang(query), options: options)
|
28
28
|
|
29
|
-
@type =
|
29
|
+
@type = DataType.type(query)
|
30
30
|
|
31
31
|
@username = username || Mihari.config.passivetotal_username
|
32
32
|
@api_key = api_key || Mihari.config.passivetotal_api_key
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mihari
|
4
|
+
module Clients
|
5
|
+
#
|
6
|
+
# Google Public DNS enricher
|
7
|
+
#
|
8
|
+
class GooglePublicDNS < Base
|
9
|
+
#
|
10
|
+
# @param [String] base_url
|
11
|
+
# @param [Hash] headers
|
12
|
+
# @param [Integer, nil] timeout
|
13
|
+
#
|
14
|
+
def initialize(base_url = "https://dns.google", headers: {}, timeout: nil)
|
15
|
+
super(base_url, headers: headers, timeout: timeout)
|
16
|
+
end
|
17
|
+
|
18
|
+
#
|
19
|
+
# Query Google Public DNS by resource type
|
20
|
+
#
|
21
|
+
# @param [String] name
|
22
|
+
#
|
23
|
+
# @return [Mihari::Structs::GooglePublicDNS::Response, nil]
|
24
|
+
#
|
25
|
+
def query_all(name)
|
26
|
+
Structs::GooglePublicDNS::Response.from_dynamic! get_json("/resolve",
|
27
|
+
params: { name: name, type: "ALL" })
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/mihari/config.rb
CHANGED
@@ -42,10 +42,12 @@ module Mihari
|
|
42
42
|
ignore_error: false,
|
43
43
|
pagination_interval: 0,
|
44
44
|
pagination_limit: 100,
|
45
|
+
parallel: false,
|
45
46
|
retry_exponential_backoff: true,
|
46
47
|
retry_interval: 5,
|
47
48
|
retry_times: 3,
|
48
|
-
sentry_dsn: nil
|
49
|
+
sentry_dsn: nil,
|
50
|
+
sentry_trace_sample_rate: 0.25
|
49
51
|
)
|
50
52
|
|
51
53
|
# @!attribute [r] binaryedge_api_key
|
@@ -61,7 +63,7 @@ module Mihari
|
|
61
63
|
# @return [String, nil]
|
62
64
|
|
63
65
|
# @!attribute [r] database_url
|
64
|
-
# @return [
|
66
|
+
# @return [URI, nil]
|
65
67
|
|
66
68
|
# @!attribute [r] fofa_api_key
|
67
69
|
# @return [String, nil]
|
@@ -132,6 +134,9 @@ module Mihari
|
|
132
134
|
# @!attribute [r] sentry_dsn
|
133
135
|
# @return [String, nil]
|
134
136
|
|
137
|
+
# @!attribute [r] sentry_trace_sample_rate
|
138
|
+
# @return [Float]
|
139
|
+
|
135
140
|
# @!attribute [r] retry_interval
|
136
141
|
# @return [Integer]
|
137
142
|
|
@@ -147,6 +152,9 @@ module Mihari
|
|
147
152
|
# @!attribute [r] pagination_limit
|
148
153
|
# @return [Integer]
|
149
154
|
|
155
|
+
# @!attribute [r] parallel
|
156
|
+
# @return [Boolean]
|
157
|
+
|
150
158
|
# @!attribute [r] ignore_error
|
151
159
|
# @return [Boolean]
|
152
160
|
|
@@ -2,9 +2,11 @@
|
|
2
2
|
|
3
3
|
module Mihari
|
4
4
|
#
|
5
|
-
# Artifact
|
5
|
+
# (Artifact) Data Type
|
6
6
|
#
|
7
|
-
class
|
7
|
+
class DataType
|
8
|
+
include Dry::Monads[:try]
|
9
|
+
|
8
10
|
# @return [String]
|
9
11
|
attr_reader :data
|
10
12
|
|
@@ -24,26 +26,25 @@ module Mihari
|
|
24
26
|
|
25
27
|
# @return [Boolean]
|
26
28
|
def ip?
|
27
|
-
IPAddr
|
28
|
-
|
29
|
-
|
30
|
-
false
|
29
|
+
Try[IPAddr::InvalidAddressError] do
|
30
|
+
IPAddr.new(data).to_s == data
|
31
|
+
end.to_result.value_or(false)
|
31
32
|
end
|
32
33
|
|
33
34
|
# @return [Boolean]
|
34
35
|
def domain?
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
false
|
36
|
+
Try[Addressable::URI::InvalidURIError] do
|
37
|
+
uri = Addressable::URI.parse("http://#{data}")
|
38
|
+
uri.host == data && PublicSuffix.valid?(uri.host)
|
39
|
+
end.to_result.value_or(false)
|
39
40
|
end
|
40
41
|
|
41
42
|
# @return [Boolean]
|
42
43
|
def url?
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
false
|
44
|
+
Try[Addressable::URI::InvalidURIError] do
|
45
|
+
uri = Addressable::URI.parse(data)
|
46
|
+
uri.scheme && uri.host && uri.path && PublicSuffix.valid?(uri.host)
|
47
|
+
end.to_result.value_or(false)
|
47
48
|
end
|
48
49
|
|
49
50
|
# @return [Boolean]
|
@@ -53,38 +54,20 @@ module Mihari
|
|
53
54
|
|
54
55
|
# @return [String, nil]
|
55
56
|
def type
|
56
|
-
|
57
|
-
return
|
58
|
-
return "domain" if domain?
|
59
|
-
return "url" if url?
|
57
|
+
found = %i[hash? ip? domain? url? mail?].find { |method| send(method) if respond_to?(method) }
|
58
|
+
return nil if found.nil?
|
60
59
|
|
61
|
-
|
60
|
+
found[...-1].to_s
|
62
61
|
end
|
63
62
|
|
64
63
|
# @return [String, nil]
|
65
64
|
def detailed_type
|
66
|
-
|
67
|
-
return
|
68
|
-
return "sha256" if sha256?
|
69
|
-
return "sha512" if sha512?
|
65
|
+
found = %i[md5? sha1? sha256? sha512?].find { |method| send(method) if respond_to?(method) }
|
66
|
+
return found[...-1].to_s unless found.nil?
|
70
67
|
|
71
68
|
type
|
72
69
|
end
|
73
70
|
|
74
|
-
class << self
|
75
|
-
# @return [String, nil]
|
76
|
-
def type(data)
|
77
|
-
new(data).type
|
78
|
-
end
|
79
|
-
|
80
|
-
# @return [String, nil]
|
81
|
-
def detailed_type(data)
|
82
|
-
new(data).detailed_type
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
private
|
87
|
-
|
88
71
|
# @return [Boolean]
|
89
72
|
def md5?
|
90
73
|
data.match?(/^[A-Fa-f0-9]{32}$/)
|
@@ -104,5 +87,17 @@ module Mihari
|
|
104
87
|
def sha512?
|
105
88
|
data.match?(/^[A-Fa-f0-9]{128}$/)
|
106
89
|
end
|
90
|
+
|
91
|
+
class << self
|
92
|
+
# @return [String, nil]
|
93
|
+
def type(data)
|
94
|
+
new(data).type
|
95
|
+
end
|
96
|
+
|
97
|
+
# @return [String, nil]
|
98
|
+
def detailed_type(data)
|
99
|
+
new(data).detailed_type
|
100
|
+
end
|
101
|
+
end
|
107
102
|
end
|
108
103
|
end
|
data/lib/mihari/database.rb
CHANGED
@@ -111,6 +111,12 @@ class V5Schema < ActiveRecord::Migration[7.1]
|
|
111
111
|
end
|
112
112
|
end
|
113
113
|
|
114
|
+
class V61Schema < ActiveRecord::Migration[7.1]
|
115
|
+
def change
|
116
|
+
add_column :artifacts, :query, :string
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
114
120
|
def adapter
|
115
121
|
return "postgresql" if %w[postgresql postgres].include?(Mihari.config.database_url.scheme)
|
116
122
|
return "mysql2" if Mihari.config.database_url.scheme == "mysql2"
|
@@ -122,7 +128,7 @@ end
|
|
122
128
|
# @return [Array<ActiveRecord::Migration>] schemas
|
123
129
|
#
|
124
130
|
def schemas
|
125
|
-
[V5Schema]
|
131
|
+
[V5Schema, V61Schema]
|
126
132
|
end
|
127
133
|
|
128
134
|
module Mihari
|
@@ -148,7 +154,7 @@ module Mihari
|
|
148
154
|
|
149
155
|
case adapter
|
150
156
|
when "postgresql", "mysql2"
|
151
|
-
ActiveRecord::Base.establish_connection
|
157
|
+
ActiveRecord::Base.establish_connection Mihari.config.database_url.to_s
|
152
158
|
else
|
153
159
|
ActiveRecord::Base.establish_connection(
|
154
160
|
adapter: adapter,
|
@@ -156,8 +162,6 @@ module Mihari
|
|
156
162
|
)
|
157
163
|
end
|
158
164
|
ActiveRecord::Base.logger = Logger.new($stdout) if development_env?
|
159
|
-
rescue StandardError => e
|
160
|
-
Mihari.logger.error e
|
161
165
|
end
|
162
166
|
|
163
167
|
#
|
data/lib/mihari/emitters/misp.rb
CHANGED
@@ -6,7 +6,7 @@ require "slack-notifier"
|
|
6
6
|
module Mihari
|
7
7
|
module Emitters
|
8
8
|
class Attachment
|
9
|
-
|
9
|
+
prepend MemoWise
|
10
10
|
|
11
11
|
# @return [String]
|
12
12
|
attr_reader :data
|
@@ -76,7 +76,7 @@ module Mihari
|
|
76
76
|
"https://urlscan.io/domain/#{uri.hostname}"
|
77
77
|
end
|
78
78
|
end
|
79
|
-
|
79
|
+
memo_wise :_urlscan_link
|
80
80
|
|
81
81
|
# @return [String, nil]
|
82
82
|
def _vt_link
|
@@ -93,19 +93,19 @@ module Mihari
|
|
93
93
|
"https://www.virustotal.com/#/search/#{data}"
|
94
94
|
end
|
95
95
|
end
|
96
|
-
|
96
|
+
memo_wise :_vt_link
|
97
97
|
|
98
98
|
# @return [String, nil]
|
99
99
|
def _censys_link
|
100
100
|
(data_type == "ip") ? "https://search.censys.io/hosts/#{data}" : nil
|
101
101
|
end
|
102
|
-
|
102
|
+
memo_wise :_censys_link
|
103
103
|
|
104
104
|
# @return [String, nil]
|
105
105
|
def _shodan_link
|
106
106
|
(data_type == "ip") ? "https://www.shodan.io/host/#{data}" : nil
|
107
107
|
end
|
108
|
-
|
108
|
+
memo_wise :_shodan_link
|
109
109
|
|
110
110
|
# @return [String]
|
111
111
|
def sha256
|
@@ -66,12 +66,12 @@ module Mihari
|
|
66
66
|
end.first
|
67
67
|
end
|
68
68
|
|
69
|
-
private
|
70
|
-
|
71
69
|
def configuration_keys
|
72
70
|
%w[thehive_url thehive_api_key]
|
73
71
|
end
|
74
72
|
|
73
|
+
private
|
74
|
+
|
75
75
|
def client
|
76
76
|
@client ||= Clients::TheHive.new(url, api_key: api_key, api_version: normalized_api_version, timeout: timeout)
|
77
77
|
end
|
@@ -11,27 +11,10 @@ module Mihari
|
|
11
11
|
#
|
12
12
|
# @param [String] name
|
13
13
|
#
|
14
|
-
# @return [
|
14
|
+
# @return [Mihari::Structs::GooglePublicDNS::Response]
|
15
15
|
#
|
16
16
|
def call(name)
|
17
|
-
|
18
|
-
end
|
19
|
-
|
20
|
-
#
|
21
|
-
# Query Google Public DNS by resource type
|
22
|
-
#
|
23
|
-
# @param [String] name
|
24
|
-
# @param [String] resource_type
|
25
|
-
#
|
26
|
-
# @return [Mihari::Structs::GooglePublicDNS::Response, nil]
|
27
|
-
#
|
28
|
-
def query_by_type(name, resource_type)
|
29
|
-
url = "https://dns.google/resolve"
|
30
|
-
params = { name: name, type: resource_type }
|
31
|
-
res = http.get(url, params: params)
|
32
|
-
Structs::GooglePublicDNS::Response.from_dynamic! JSON.parse(res.body.to_s)
|
33
|
-
rescue HTTPError
|
34
|
-
nil
|
17
|
+
client.query_all name
|
35
18
|
end
|
36
19
|
|
37
20
|
class << self
|
@@ -45,8 +28,8 @@ module Mihari
|
|
45
28
|
|
46
29
|
private
|
47
30
|
|
48
|
-
def
|
49
|
-
|
31
|
+
def client
|
32
|
+
Clients::GooglePublicDNS.new
|
50
33
|
end
|
51
34
|
end
|
52
35
|
end
|
@@ -8,16 +8,11 @@ module Mihari
|
|
8
8
|
# Whois enricher
|
9
9
|
#
|
10
10
|
class Whois < Base
|
11
|
-
# @return [Hash]
|
12
|
-
attr_accessor :memo
|
13
|
-
|
14
11
|
#
|
15
12
|
# @param [Hash, nil] options
|
16
13
|
#
|
17
14
|
def initialize(options: nil)
|
18
15
|
super(options: options)
|
19
|
-
|
20
|
-
@memo = {}
|
21
16
|
end
|
22
17
|
|
23
18
|
#
|
@@ -28,16 +23,22 @@ module Mihari
|
|
28
23
|
# @return [Mihari::Models::WhoisRecord, nil]
|
29
24
|
#
|
30
25
|
def call(domain)
|
31
|
-
|
26
|
+
_call PublicSuffix.domain(domain)
|
27
|
+
end
|
32
28
|
|
33
|
-
|
34
|
-
return memo[domain].dup if memo.key?(domain)
|
29
|
+
private
|
35
30
|
|
31
|
+
#
|
32
|
+
# @param [String] domain
|
33
|
+
#
|
34
|
+
# @return [Mihari::Models::WhoisRecord, nil]
|
35
|
+
#
|
36
|
+
def _call(domain)
|
36
37
|
record = whois.lookup(domain)
|
37
38
|
parser = record.parser
|
38
39
|
return nil if parser.available?
|
39
40
|
|
40
|
-
|
41
|
+
Models::WhoisRecord.new(
|
41
42
|
domain: domain,
|
42
43
|
created_on: get_created_on(parser),
|
43
44
|
updated_on: get_updated_on(parser),
|
@@ -45,14 +46,8 @@ module Mihari
|
|
45
46
|
registrar: get_registrar(parser),
|
46
47
|
contacts: get_contacts(parser)
|
47
48
|
)
|
48
|
-
|
49
|
-
# set memo
|
50
|
-
memo[domain] = whois_record
|
51
|
-
|
52
|
-
whois_record
|
53
49
|
end
|
54
|
-
|
55
|
-
private
|
50
|
+
memo_wise :_call
|
56
51
|
|
57
52
|
#
|
58
53
|
# @return [::Whois::Client]
|
@@ -11,6 +11,7 @@ module Mihari
|
|
11
11
|
expose :data, documentation: { type: String, required: true }
|
12
12
|
expose :data_type, documentation: { type: String, required: true }, as: :dataType
|
13
13
|
expose :source, documentation: { type: String, required: true }
|
14
|
+
expose :query, documentation: { type: String, required: false }
|
14
15
|
expose :tags, documentation: { type: String, is_array: true }
|
15
16
|
end
|
16
17
|
|
@@ -6,7 +6,7 @@ module Mihari
|
|
6
6
|
# False positive mixins
|
7
7
|
#
|
8
8
|
module FalsePositive
|
9
|
-
|
9
|
+
prepend MemoWise
|
10
10
|
|
11
11
|
#
|
12
12
|
# Normalize a falsepositive value
|
@@ -22,7 +22,7 @@ module Mihari
|
|
22
22
|
value_without_slashes = value[1..-2]
|
23
23
|
Regexp.compile value_without_slashes.to_s
|
24
24
|
end
|
25
|
-
|
25
|
+
memo_wise :normalize_falsepositive
|
26
26
|
|
27
27
|
#
|
28
28
|
# Check whether a value is valid format as a disallowed data value
|
@@ -46,7 +46,7 @@ module Mihari
|
|
46
46
|
|
47
47
|
super(*args, **kwargs)
|
48
48
|
|
49
|
-
self.data_type =
|
49
|
+
self.data_type = DataType.type(data)
|
50
50
|
|
51
51
|
@tags = []
|
52
52
|
@rule_id = ""
|
@@ -158,13 +158,13 @@ module Mihari
|
|
158
158
|
# Enrich all the enrichable relationships of the artifact
|
159
159
|
#
|
160
160
|
def enrich_all
|
161
|
-
enrich_autonomous_system
|
161
|
+
enrich_autonomous_system ipinfo
|
162
162
|
enrich_dns
|
163
|
-
enrich_geolocation
|
164
|
-
enrich_reverse_dns
|
163
|
+
enrich_geolocation ipinfo
|
164
|
+
enrich_reverse_dns shodan
|
165
165
|
enrich_whois
|
166
|
-
enrich_ports
|
167
|
-
enrich_cpes
|
166
|
+
enrich_ports shodan
|
167
|
+
enrich_cpes shodan
|
168
168
|
end
|
169
169
|
|
170
170
|
ENRICH_METHODS_BY_ENRICHER = {
|
@@ -197,6 +197,14 @@ module Mihari
|
|
197
197
|
|
198
198
|
private
|
199
199
|
|
200
|
+
def ipinfo
|
201
|
+
@ipinfo ||= Enrichers::IPInfo.new
|
202
|
+
end
|
203
|
+
|
204
|
+
def shodan
|
205
|
+
@shodan ||= Enrichers::Shodan.new
|
206
|
+
end
|
207
|
+
|
200
208
|
def normalize_as_domain(url_or_domain)
|
201
209
|
return url_or_domain if data_type == "domain"
|
202
210
|
|