mihari 3.6.0 → 3.7.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitmodules +3 -0
- data/Steepfile +32 -0
- data/lib/mihari/analyzers/base.rb +7 -22
- data/lib/mihari/analyzers/binaryedge.rb +13 -0
- data/lib/mihari/analyzers/censys.rb +5 -0
- data/lib/mihari/analyzers/circl.rb +15 -0
- data/lib/mihari/analyzers/crtsh.rb +5 -0
- data/lib/mihari/analyzers/dnpedia.rb +5 -0
- data/lib/mihari/analyzers/dnstwister.rb +17 -0
- data/lib/mihari/analyzers/onyphe.rb +20 -4
- data/lib/mihari/analyzers/otx.rb +20 -0
- data/lib/mihari/analyzers/passivetotal.rb +25 -0
- data/lib/mihari/analyzers/pulsedive.rb +10 -0
- data/lib/mihari/analyzers/rule.rb +18 -0
- data/lib/mihari/analyzers/securitytrails.rb +25 -0
- data/lib/mihari/analyzers/shodan.rb +13 -0
- data/lib/mihari/analyzers/spyse.rb +20 -0
- data/lib/mihari/analyzers/urlscan.rb +10 -0
- data/lib/mihari/analyzers/virustotal.rb +20 -0
- data/lib/mihari/analyzers/zoomeye.rb +38 -0
- data/lib/mihari/database.rb +13 -0
- data/lib/mihari/emitters/base.rb +1 -1
- data/lib/mihari/emitters/misp.rb +38 -5
- data/lib/mihari/emitters/slack.rb +20 -2
- data/lib/mihari/emitters/the_hive.rb +16 -3
- data/lib/mihari/emitters/webhook.rb +18 -3
- data/lib/mihari/enrichers/base.rb +18 -0
- data/lib/mihari/enrichers/ipinfo.rb +49 -0
- data/lib/mihari/mixins/autonomous_system.rb +19 -0
- data/lib/mihari/mixins/disallowed_data_value.rb +1 -1
- data/lib/mihari/models/artifact.rb +42 -3
- data/lib/mihari/models/autonomous_system.rb +18 -1
- data/lib/mihari/models/dns.rb +2 -0
- data/lib/mihari/models/geolocation.rb +21 -1
- data/lib/mihari/models/reverse_dns.rb +2 -0
- data/lib/mihari/models/whois.rb +1 -1
- data/lib/mihari/status.rb +7 -2
- data/lib/mihari/structs/ipinfo.rb +39 -0
- data/lib/mihari/structs/onyphe.rb +2 -2
- data/lib/mihari/type_checker.rb +9 -9
- data/lib/mihari/version.rb +1 -1
- data/lib/mihari/web/controllers/artifacts_controller.rb +27 -1
- data/lib/mihari/web/controllers/ip_address_controller.rb +4 -19
- data/lib/mihari/web/public/index.html +1 -1
- data/lib/mihari/web/public/redoc-static.html +7 -6
- data/lib/mihari/web/public/static/js/app.06d5cf1c.js +36 -0
- data/lib/mihari/web/public/static/js/app.06d5cf1c.js.map +1 -0
- data/lib/mihari.rb +40 -26
- data/mihari.gemspec +7 -4
- data/sig/lib/mihari/analyzers/base.rbs +90 -0
- data/sig/lib/mihari/analyzers/basic.rbs +17 -0
- data/sig/lib/mihari/analyzers/binaryedge.rbs +25 -0
- data/sig/lib/mihari/analyzers/censys.rbs +38 -0
- data/sig/lib/mihari/analyzers/circl.rbs +29 -0
- data/sig/lib/mihari/analyzers/crtsh.rbs +19 -0
- data/sig/lib/mihari/analyzers/dnpedia.rbs +18 -0
- data/sig/lib/mihari/analyzers/dnstwister.rbs +27 -0
- data/sig/lib/mihari/analyzers/onyphe.rbs +33 -0
- data/sig/lib/mihari/analyzers/otx.rbs +33 -0
- data/sig/lib/mihari/analyzers/passivetotal.rbs +33 -0
- data/sig/lib/mihari/analyzers/pulsedive.rbs +27 -0
- data/sig/lib/mihari/analyzers/rule.rbs +68 -0
- data/sig/lib/mihari/analyzers/securitytrails.rbs +33 -0
- data/sig/lib/mihari/analyzers/shodan.rbs +33 -0
- data/sig/lib/mihari/analyzers/spyse.rbs +29 -0
- data/sig/lib/mihari/analyzers/urlscan.rbs +28 -0
- data/sig/lib/mihari/analyzers/virustotal.rbs +31 -0
- data/sig/lib/mihari/analyzers/zoomeye.rbs +33 -0
- data/sig/lib/mihari/cli/analyzer.rbs +39 -0
- data/sig/lib/mihari/cli/base.rbs +11 -0
- data/sig/lib/mihari/cli/init.rbs +7 -0
- data/sig/lib/mihari/cli/main.rbs +9 -0
- data/sig/lib/mihari/cli/mixins/utils.rbs +50 -0
- data/sig/lib/mihari/cli/validator.rbs +7 -0
- data/sig/lib/mihari/commands/binaryedge.rbs +7 -0
- data/sig/lib/mihari/commands/censys.rbs +7 -0
- data/sig/lib/mihari/commands/circl.rbs +7 -0
- data/sig/lib/mihari/commands/crtsh.rbs +7 -0
- data/sig/lib/mihari/commands/dnpedia.rbs +7 -0
- data/sig/lib/mihari/commands/dnstwister.rbs +7 -0
- data/sig/lib/mihari/commands/init.rbs +11 -0
- data/sig/lib/mihari/commands/json.rbs +7 -0
- data/sig/lib/mihari/commands/onyphe.rbs +7 -0
- data/sig/lib/mihari/commands/otx.rbs +7 -0
- data/sig/lib/mihari/commands/passivetotal.rbs +7 -0
- data/sig/lib/mihari/commands/pulsedive.rbs +7 -0
- data/sig/lib/mihari/commands/search.rbs +35 -0
- data/sig/lib/mihari/commands/securitytrails.rbs +7 -0
- data/sig/lib/mihari/commands/shodan.rbs +7 -0
- data/sig/lib/mihari/commands/spyse.rbs +7 -0
- data/sig/lib/mihari/commands/urlscan.rbs +7 -0
- data/sig/lib/mihari/commands/validator.rbs +11 -0
- data/sig/lib/mihari/commands/virustotal.rbs +7 -0
- data/sig/lib/mihari/commands/web.rbs +7 -0
- data/sig/lib/mihari/commands/zoomeye.rbs +7 -0
- data/sig/lib/mihari/constants.rbs +3 -0
- data/sig/lib/mihari/database.rbs +25 -0
- data/sig/lib/mihari/emitters/base.rbs +18 -0
- data/sig/lib/mihari/emitters/database.rbs +9 -0
- data/sig/lib/mihari/emitters/misp.rbs +28 -0
- data/sig/lib/mihari/emitters/slack.rbs +58 -0
- data/sig/lib/mihari/emitters/stdout.rbs +9 -0
- data/sig/lib/mihari/emitters/the_hive.rbs +24 -0
- data/sig/lib/mihari/emitters/webhook.rbs +20 -0
- data/sig/lib/mihari/enrichers/base.rbs +12 -0
- data/sig/lib/mihari/enrichers/ipinfo.rbs +16 -0
- data/sig/lib/mihari/errors.rbs +10 -0
- data/sig/lib/mihari/mixins/autonomous_system.rbs +14 -0
- data/sig/lib/mihari/mixins/configurable.rbs +26 -0
- data/sig/lib/mihari/mixins/configuration.rbs +45 -0
- data/sig/lib/mihari/mixins/disallowed_data_value.rbs +25 -0
- data/sig/lib/mihari/mixins/hash.rbs +14 -0
- data/sig/lib/mihari/mixins/refang.rbs +14 -0
- data/sig/lib/mihari/mixins/retriable.rbs +15 -0
- data/sig/lib/mihari/mixins/rule.rbs +41 -0
- data/sig/lib/mihari/models/alert.rbs +46 -0
- data/sig/lib/mihari/models/artifact.rbs +65 -0
- data/sig/lib/mihari/models/autonomous_system.rbs +14 -0
- data/sig/lib/mihari/models/dns.rbs +19 -0
- data/sig/lib/mihari/models/geolocation.rbs +15 -0
- data/sig/lib/mihari/models/reverse_dns.rbs +14 -0
- data/sig/lib/mihari/models/tag.rbs +5 -0
- data/sig/lib/mihari/models/tagging.rbs +4 -0
- data/sig/lib/mihari/models/whois.rbs +66 -0
- data/sig/lib/mihari/notifiers/base.rbs +18 -0
- data/sig/lib/mihari/notifiers/exception_notifier.rbs +75 -0
- data/sig/lib/mihari/notifiers/slack.rbs +50 -0
- data/sig/lib/mihari/status.rbs +25 -0
- data/sig/lib/mihari/structs/censys.rbs +50 -0
- data/sig/lib/mihari/structs/ipinfo.rbs +17 -0
- data/sig/lib/mihari/structs/onyphe.rbs +25 -0
- data/sig/lib/mihari/structs/shodan.rbs +28 -0
- data/sig/lib/mihari/type_checker.rbs +48 -0
- data/sig/lib/mihari/types.rbs +17 -0
- data/sig/lib/mihari/version.rbs +3 -0
- data/sig/lib/mihari/web/app.rbs +5 -0
- data/sig/lib/mihari.rbs +59 -0
- metadata +148 -10
@@ -6,7 +6,7 @@ require "net/ping"
|
|
6
6
|
module Mihari
|
7
7
|
module Emitters
|
8
8
|
class TheHive < Base
|
9
|
-
# @return [
|
9
|
+
# @return [Boolean]
|
10
10
|
def valid?
|
11
11
|
api_endpont? && api_key? && ping?
|
12
12
|
end
|
@@ -34,16 +34,29 @@ module Mihari
|
|
34
34
|
@api ||= Hachi::API.new(api_endpoint: Mihari.config.thehive_api_endpoint, api_key: Mihari.config.thehive_api_key)
|
35
35
|
end
|
36
36
|
|
37
|
-
#
|
37
|
+
#
|
38
|
+
# Check whether an API endpoint is set or not
|
39
|
+
#
|
40
|
+
# @return [Boolean]
|
41
|
+
#
|
38
42
|
def api_endpont?
|
39
43
|
!Mihari.config.thehive_api_endpoint.nil?
|
40
44
|
end
|
41
45
|
|
42
|
-
#
|
46
|
+
#
|
47
|
+
# Check whether an API key is set or not
|
48
|
+
#
|
49
|
+
# @return [Boolean]
|
50
|
+
# ]
|
43
51
|
def api_key?
|
44
52
|
!Mihari.config.thehive_api_key.nil?
|
45
53
|
end
|
46
54
|
|
55
|
+
#
|
56
|
+
# Check whether an API endpoint is reachable or not
|
57
|
+
#
|
58
|
+
# @return [Boolean]
|
59
|
+
#
|
47
60
|
def ping?
|
48
61
|
base_url = Mihari.config.thehive_api_endpoint
|
49
62
|
base_url = base_url.end_with?("/") ? base_url[0..-2] : base_url
|
@@ -7,7 +7,7 @@ require "uri"
|
|
7
7
|
module Mihari
|
8
8
|
module Emitters
|
9
9
|
class Webhook < Base
|
10
|
-
# @return [
|
10
|
+
# @return [Boolean]
|
11
11
|
def valid?
|
12
12
|
webhook_url?
|
13
13
|
end
|
@@ -24,7 +24,7 @@ module Mihari
|
|
24
24
|
tags: tags
|
25
25
|
}
|
26
26
|
|
27
|
-
if use_json_body
|
27
|
+
if use_json_body?
|
28
28
|
Net::HTTP.post(uri, data.to_json, "Content-Type" => "application/json")
|
29
29
|
else
|
30
30
|
Net::HTTP.post_form(uri, data)
|
@@ -37,15 +37,30 @@ module Mihari
|
|
37
37
|
%w[webhook_url]
|
38
38
|
end
|
39
39
|
|
40
|
+
#
|
41
|
+
# Webhook URL
|
42
|
+
#
|
43
|
+
# @return [String, nil]
|
44
|
+
#
|
40
45
|
def webhook_url
|
41
46
|
@webhook_url ||= Mihari.config.webhook_url
|
42
47
|
end
|
43
48
|
|
49
|
+
#
|
50
|
+
# Check whether a webhook URL is set or not
|
51
|
+
#
|
52
|
+
# @return [<Type>] <description>
|
53
|
+
#
|
44
54
|
def webhook_url?
|
45
55
|
!webhook_url.nil?
|
46
56
|
end
|
47
57
|
|
48
|
-
|
58
|
+
#
|
59
|
+
# Check whether to use JSON body or NOT
|
60
|
+
#
|
61
|
+
# @return [<Type>] <description>
|
62
|
+
#
|
63
|
+
def use_json_body?
|
49
64
|
@use_json_body ||= Mihari.config.webhook_use_json_body
|
50
65
|
end
|
51
66
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mihari
|
4
|
+
module Enrichers
|
5
|
+
class Base
|
6
|
+
include Mixins::Configurable
|
7
|
+
|
8
|
+
def self.inherited(child)
|
9
|
+
Mihari.enrichers << child
|
10
|
+
end
|
11
|
+
|
12
|
+
# @return [Boolean]
|
13
|
+
def valid?
|
14
|
+
raise NotImplementedError, "You must implement #{self.class}##{__method__}"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require "http"
|
2
|
+
require "json"
|
3
|
+
require "memist"
|
4
|
+
|
5
|
+
module Mihari
|
6
|
+
module Enrichers
|
7
|
+
class IPInfo < Base
|
8
|
+
# @return [Boolean]
|
9
|
+
def valid?
|
10
|
+
Mihari.config.ipinfo_api_key.nil?
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def configuration_keys
|
16
|
+
%w[ipinfo_api_key]
|
17
|
+
end
|
18
|
+
|
19
|
+
class << self
|
20
|
+
include Memist::Memoizable
|
21
|
+
|
22
|
+
#
|
23
|
+
# Query IPInfo
|
24
|
+
#
|
25
|
+
# @param [String] ip
|
26
|
+
#
|
27
|
+
# @return [Mihari::Structs::IPInfo::Response, nil]
|
28
|
+
#
|
29
|
+
def query(ip)
|
30
|
+
headers = {}
|
31
|
+
token = Mihari.config.ipinfo_api_key
|
32
|
+
unless token.nil?
|
33
|
+
headers[:authorization] = "Bearer #{token}"
|
34
|
+
end
|
35
|
+
|
36
|
+
begin
|
37
|
+
res = HTTP.headers(headers).get("https://ipinfo.io/#{ip}/json")
|
38
|
+
data = JSON.parse(res.body.to_s)
|
39
|
+
|
40
|
+
Structs::IPInfo::Response.from_dynamic! data
|
41
|
+
rescue HTTP::Error
|
42
|
+
nil
|
43
|
+
end
|
44
|
+
end
|
45
|
+
memoize :query
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Mihari
|
2
|
+
module Mixins
|
3
|
+
module AutonomousSystem
|
4
|
+
#
|
5
|
+
# Normalize ASN value
|
6
|
+
#
|
7
|
+
# @param [String, Integer] asn
|
8
|
+
#
|
9
|
+
# @return [Integer]
|
10
|
+
#
|
11
|
+
def normalize_asn(asn)
|
12
|
+
return asn if asn.is_a?(Integer)
|
13
|
+
return asn.to_i unless asn.start_with?("AS")
|
14
|
+
|
15
|
+
asn.delete_prefix("AS").to_i
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -16,6 +16,8 @@ end
|
|
16
16
|
|
17
17
|
module Mihari
|
18
18
|
class Artifact < ActiveRecord::Base
|
19
|
+
belongs_to :alert
|
20
|
+
|
19
21
|
has_one :autonomous_system, dependent: :destroy
|
20
22
|
has_one :geolocation, dependent: :destroy
|
21
23
|
has_one :whois_record, dependent: :destroy
|
@@ -80,6 +82,35 @@ module Mihari
|
|
80
82
|
self.reverse_dns_names = ReverseDnsName.build_by_ip(data)
|
81
83
|
end
|
82
84
|
|
85
|
+
#
|
86
|
+
# Enrich(add) geolocation
|
87
|
+
#
|
88
|
+
def enrich_geolocation
|
89
|
+
return unless can_enrich_geolocation?
|
90
|
+
|
91
|
+
self.geolocation = Geolocation.build_by_ip(data)
|
92
|
+
end
|
93
|
+
|
94
|
+
#
|
95
|
+
# Enrich(add) geolocation
|
96
|
+
#
|
97
|
+
def enrich_autonomous_system
|
98
|
+
return unless can_enrich_autonomous_system?
|
99
|
+
|
100
|
+
self.autonomous_system = AutonomousSystem.build_by_ip(data)
|
101
|
+
end
|
102
|
+
|
103
|
+
#
|
104
|
+
# Enrich all the enrichable relationships of the artifact
|
105
|
+
#
|
106
|
+
def enrich_all
|
107
|
+
enrich_autonomous_system
|
108
|
+
enrich_dns
|
109
|
+
enrich_geolocation
|
110
|
+
enrich_reverse_dns
|
111
|
+
enrich_whois
|
112
|
+
end
|
113
|
+
|
83
114
|
private
|
84
115
|
|
85
116
|
def normalize_as_domain(url_or_domain)
|
@@ -89,15 +120,23 @@ module Mihari
|
|
89
120
|
end
|
90
121
|
|
91
122
|
def can_enrich_whois?
|
92
|
-
%w[domain url].include?
|
123
|
+
%w[domain url].include?(data_type) && whois_record.nil?
|
93
124
|
end
|
94
125
|
|
95
126
|
def can_enrich_dns?
|
96
|
-
%w[domain url].include?
|
127
|
+
%w[domain url].include?(data_type) && dns_records.empty?
|
97
128
|
end
|
98
129
|
|
99
130
|
def can_enrich_revese_dns?
|
100
|
-
data_type == "ip"
|
131
|
+
data_type == "ip" && reverse_dns_names.empty?
|
132
|
+
end
|
133
|
+
|
134
|
+
def can_enrich_geolocation?
|
135
|
+
data_type == "ip" && geolocation.nil?
|
136
|
+
end
|
137
|
+
|
138
|
+
def can_enrich_autonomous_system?
|
139
|
+
data_type == "ip" && autonomous_system.nil?
|
101
140
|
end
|
102
141
|
end
|
103
142
|
end
|
@@ -4,6 +4,23 @@ require "active_record"
|
|
4
4
|
|
5
5
|
module Mihari
|
6
6
|
class AutonomousSystem < ActiveRecord::Base
|
7
|
-
|
7
|
+
belongs_to :artifact
|
8
|
+
|
9
|
+
class << self
|
10
|
+
#
|
11
|
+
# Build AS
|
12
|
+
#
|
13
|
+
# @param [String] ip
|
14
|
+
#
|
15
|
+
# @return [Mihari::AutonomousSystem, nil]
|
16
|
+
#
|
17
|
+
def build_by_ip(ip)
|
18
|
+
res = Enrichers::IPInfo.query(ip)
|
19
|
+
|
20
|
+
return nil if res.nil? || res.asn.nil?
|
21
|
+
|
22
|
+
new(asn: res.asn)
|
23
|
+
end
|
24
|
+
end
|
8
25
|
end
|
9
26
|
end
|
data/lib/mihari/models/dns.rb
CHANGED
@@ -1,9 +1,29 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "active_record"
|
4
|
+
require "normalize_country"
|
4
5
|
|
5
6
|
module Mihari
|
6
7
|
class Geolocation < ActiveRecord::Base
|
7
|
-
|
8
|
+
belongs_to :artifact
|
9
|
+
|
10
|
+
class << self
|
11
|
+
#
|
12
|
+
# Build Geolocation
|
13
|
+
#
|
14
|
+
# @param [String] ip
|
15
|
+
#
|
16
|
+
# @return [Mihari::Geolocation, nil]
|
17
|
+
#
|
18
|
+
def build_by_ip(ip)
|
19
|
+
res = Enrichers::IPInfo.query(ip)
|
20
|
+
|
21
|
+
unless res.nil?
|
22
|
+
return new(country: NormalizeCountry(res.country_code, to: :short), country_code: res.country_code)
|
23
|
+
end
|
24
|
+
|
25
|
+
nil
|
26
|
+
end
|
27
|
+
end
|
8
28
|
end
|
9
29
|
end
|
data/lib/mihari/models/whois.rb
CHANGED
data/lib/mihari/status.rb
CHANGED
@@ -18,7 +18,7 @@ module Mihari
|
|
18
18
|
# @return [Array<Hash>]
|
19
19
|
#
|
20
20
|
def statuses
|
21
|
-
(Mihari.analyzers + Mihari.emitters).map do |klass|
|
21
|
+
(Mihari.analyzers + Mihari.emitters + Mihari.enrichers).map do |klass|
|
22
22
|
name = klass.to_s.split("::").last.to_s
|
23
23
|
|
24
24
|
[name, build_status(klass)]
|
@@ -36,11 +36,16 @@ module Mihari
|
|
36
36
|
return nil if klass == Mihari::Analyzers::Rule
|
37
37
|
|
38
38
|
is_analyzer = klass.ancestors.include?(Mihari::Analyzers::Base)
|
39
|
+
is_emitter = klass.ancestors.include?(Mihari::Emitters::Base)
|
40
|
+
is_enricher = klass.ancestors.include?(Mihari::Enrichers::Base)
|
39
41
|
|
40
42
|
instance = is_analyzer ? klass.new("dummy") : klass.new
|
41
43
|
is_configured = instance.configured?
|
42
44
|
values = instance.configuration_values
|
43
|
-
|
45
|
+
|
46
|
+
type = "Analyzer"
|
47
|
+
type = "Emitter" if is_emitter
|
48
|
+
type = "Enricher" if is_enricher
|
44
49
|
|
45
50
|
values ? { is_configured: is_configured, values: values, type: type } : nil
|
46
51
|
rescue ArgumentError => _e
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require "json"
|
2
|
+
require "dry/struct"
|
3
|
+
|
4
|
+
module Mihari
|
5
|
+
module Structs
|
6
|
+
module IPInfo
|
7
|
+
class Response < Dry::Struct
|
8
|
+
attribute :ip, Types::String
|
9
|
+
attribute :hostname, Types::String.optional
|
10
|
+
attribute :loc, Types::String
|
11
|
+
attribute :country_code, Types::String
|
12
|
+
attribute :asn, Types::Integer.optional
|
13
|
+
|
14
|
+
class << self
|
15
|
+
include Mixins::AutonomousSystem
|
16
|
+
|
17
|
+
def from_dynamic!(d)
|
18
|
+
d = Types::Hash[d]
|
19
|
+
|
20
|
+
asn = nil
|
21
|
+
org = d["org"]
|
22
|
+
unless org.nil?
|
23
|
+
asn = org.split.first
|
24
|
+
asn = normalize_asn(asn)
|
25
|
+
end
|
26
|
+
|
27
|
+
new(
|
28
|
+
ip: d.fetch("ip"),
|
29
|
+
loc: d.fetch("loc"),
|
30
|
+
hostname: d["hostname"],
|
31
|
+
country_code: d.fetch("country"),
|
32
|
+
asn: asn
|
33
|
+
)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -6,7 +6,7 @@ module Mihari
|
|
6
6
|
module Onyphe
|
7
7
|
class Result < Dry::Struct
|
8
8
|
attribute :asn, Types::String
|
9
|
-
attribute :country_code, Types::String
|
9
|
+
attribute :country_code, Types::String.optional
|
10
10
|
attribute :ip, Types::String
|
11
11
|
|
12
12
|
def self.from_dynamic!(d)
|
@@ -15,7 +15,7 @@ module Mihari
|
|
15
15
|
asn: d.fetch("asn"),
|
16
16
|
ip: d.fetch("ip"),
|
17
17
|
# Onyphe's country = 2-letter country code
|
18
|
-
country_code: d
|
18
|
+
country_code: d["country"]
|
19
19
|
)
|
20
20
|
end
|
21
21
|
end
|
data/lib/mihari/type_checker.rb
CHANGED
@@ -18,12 +18,12 @@ module Mihari
|
|
18
18
|
raise ArgumentError if data.is_a?(Hash)
|
19
19
|
end
|
20
20
|
|
21
|
-
# @return [
|
21
|
+
# @return [Boolean]
|
22
22
|
def hash?
|
23
23
|
md5? || sha1? || sha256? || sha512?
|
24
24
|
end
|
25
25
|
|
26
|
-
# @return [
|
26
|
+
# @return [Boolean]
|
27
27
|
def ip?
|
28
28
|
IPAddr.new data
|
29
29
|
true
|
@@ -31,7 +31,7 @@ module Mihari
|
|
31
31
|
false
|
32
32
|
end
|
33
33
|
|
34
|
-
# @return [
|
34
|
+
# @return [Boolean]
|
35
35
|
def domain?
|
36
36
|
uri = Addressable::URI.parse("http://#{data}")
|
37
37
|
uri.host == data && PublicSuffix.valid?(uri.host)
|
@@ -39,7 +39,7 @@ module Mihari
|
|
39
39
|
false
|
40
40
|
end
|
41
41
|
|
42
|
-
# @return [
|
42
|
+
# @return [Boolean]
|
43
43
|
def url?
|
44
44
|
uri = Addressable::URI.parse(data)
|
45
45
|
uri.scheme && uri.host && uri.path && PublicSuffix.valid?(uri.host)
|
@@ -47,7 +47,7 @@ module Mihari
|
|
47
47
|
false
|
48
48
|
end
|
49
49
|
|
50
|
-
# @return [
|
50
|
+
# @return [Boolean]
|
51
51
|
def mail?
|
52
52
|
EmailAddress.valid? data, host_validation: :syntax
|
53
53
|
end
|
@@ -83,22 +83,22 @@ module Mihari
|
|
83
83
|
|
84
84
|
private
|
85
85
|
|
86
|
-
# @return [
|
86
|
+
# @return [Boolean]
|
87
87
|
def md5?
|
88
88
|
data.match?(/^[A-Fa-f0-9]{32}$/)
|
89
89
|
end
|
90
90
|
|
91
|
-
# @return [
|
91
|
+
# @return [Boolean]
|
92
92
|
def sha1?
|
93
93
|
data.match?(/^[A-Fa-f0-9]{40}$/)
|
94
94
|
end
|
95
95
|
|
96
|
-
# @return [
|
96
|
+
# @return [Boolean]
|
97
97
|
def sha256?
|
98
98
|
data.match?(/^[A-Fa-f0-9]{64}$/)
|
99
99
|
end
|
100
100
|
|
101
|
-
# @return [
|
101
|
+
# @return [Boolean]
|
102
102
|
def sha512?
|
103
103
|
data.match?(/^[A-Fa-f0-9]{128}$/)
|
104
104
|
end
|