mihari 4.6.1 → 4.7.2
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/lib/mihari/analyzers/clients/otx.rb +36 -0
- data/lib/mihari/analyzers/otx.rb +19 -11
- data/lib/mihari/analyzers/rule.rb +17 -1
- data/lib/mihari/commands/init.rb +25 -2
- data/lib/mihari/commands/search.rb +2 -7
- data/lib/mihari/commands/validator.rb +10 -5
- data/lib/mihari/constants.rb +2 -0
- data/lib/mihari/enrichers/google_public_dns.rb +36 -0
- data/lib/mihari/enrichers/whois.rb +126 -0
- data/lib/mihari/errors.rb +2 -0
- data/lib/mihari/http.rb +2 -2
- data/lib/mihari/models/alert.rb +6 -1
- data/lib/mihari/models/artifact.rb +30 -0
- data/lib/mihari/models/dns.rb +5 -21
- data/lib/mihari/models/geolocation.rb +2 -4
- data/lib/mihari/models/port.rb +1 -1
- data/lib/mihari/models/rule.rb +7 -2
- data/lib/mihari/models/whois.rb +1 -96
- data/lib/mihari/schemas/enricher.rb +9 -0
- data/lib/mihari/schemas/rule.rb +6 -0
- data/lib/mihari/structs/filters.rb +71 -0
- data/lib/mihari/structs/google_public_dns.rb +42 -0
- data/lib/mihari/structs/ipinfo.rb +4 -4
- data/lib/mihari/structs/rule.rb +187 -137
- data/lib/mihari/types.rb +7 -0
- data/lib/mihari/version.rb +1 -1
- data/lib/mihari/web/endpoints/alerts.rb +1 -1
- data/lib/mihari/web/endpoints/rules.rb +13 -5
- data/lib/mihari/web/public/index.html +1 -1
- data/lib/mihari/web/public/redoc-static.html +796 -763
- data/lib/mihari/web/public/static/css/chunk-vendors.5013d549.css +7 -0
- data/lib/mihari/web/public/static/js/app.3ac3bd7a.js +2 -0
- data/lib/mihari/web/public/static/js/app.3ac3bd7a.js.map +1 -0
- data/lib/mihari/web/public/static/js/{chunk-vendors.dde2116c.js → chunk-vendors.37b7208e.js} +6 -6
- data/lib/mihari/web/public/static/js/chunk-vendors.37b7208e.js.map +1 -0
- data/lib/mihari.rb +4 -2
- data/mihari.gemspec +8 -9
- data/sig/lib/mihari/cli/base.rbs +0 -2
- data/sig/lib/mihari/enrichers/google_public_dns.rbs +18 -0
- data/sig/lib/mihari/models/alert.rbs +3 -3
- data/sig/lib/mihari/models/rule.rbs +2 -2
- data/sig/lib/mihari/structs/filters.rbs +40 -0
- data/sig/lib/mihari/structs/google_public_dns.rbs +21 -0
- data/sig/lib/mihari/structs/ipinfo.rbs +2 -2
- data/sig/lib/mihari/structs/rule.rbs +36 -43
- metadata +32 -45
- data/lib/mihari/mixins/rule.rb +0 -84
- data/lib/mihari/structs/alert.rb +0 -44
- data/lib/mihari/web/public/static/css/chunk-vendors.06251949.css +0 -7
- data/lib/mihari/web/public/static/js/app-legacy.9d5c9c3d.js +0 -2
- data/lib/mihari/web/public/static/js/app-legacy.9d5c9c3d.js.map +0 -1
- data/lib/mihari/web/public/static/js/app.823b5af7.js +0 -2
- data/lib/mihari/web/public/static/js/app.823b5af7.js.map +0 -1
- data/lib/mihari/web/public/static/js/chunk-vendors-legacy.b110c129.js +0 -25
- data/lib/mihari/web/public/static/js/chunk-vendors-legacy.b110c129.js.map +0 -1
- data/lib/mihari/web/public/static/js/chunk-vendors.dde2116c.js.map +0 -1
- data/sig/lib/mihari/mixins/rule.rbs +0 -36
- data/sig/lib/mihari/structs/alert.rbs +0 -27
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7eeecbacefc194f5d2e9356fe8f17884c358b45bb3b7ccbd83a47aa3567ae1f6
|
4
|
+
data.tar.gz: d99abc5ef4368bf1a23a48cf0f15a64a33d3539313a624d489887e86a8cc564c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e0347f1c03a949d7e3c85cb9a615247c41bea2a0ac8288f0e3c7a8f9bd5d93ad8f952c99f3b595bf19997fe10e32490898b58a858f63f402a6082344f68cdb87
|
7
|
+
data.tar.gz: a507cfb86593c602ba46ef59f279a17ed1a34e433c8e34898a872048306733d26fb1a6546f1ae96605d524ccd80c3c3a0487ab4b4ad66219c0e3a63215ce8c6e
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mihari
|
4
|
+
module Analyzers
|
5
|
+
module Clients
|
6
|
+
class OTX
|
7
|
+
attr_reader :api_key
|
8
|
+
|
9
|
+
def initialize(api_key)
|
10
|
+
@api_key = api_key
|
11
|
+
end
|
12
|
+
|
13
|
+
def query_by_ip(ip)
|
14
|
+
get "https://otx.alienvault.com/api/v1/indicators/IPv4/#{ip}/passive_dns"
|
15
|
+
end
|
16
|
+
|
17
|
+
def query_by_domain(domain)
|
18
|
+
get "https://otx.alienvault.com/api/v1/indicators/domain/#{domain}/passive_dns"
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def headers
|
24
|
+
{ "x-otx-api-key": api_key }
|
25
|
+
end
|
26
|
+
|
27
|
+
def get(url)
|
28
|
+
res = HTTP.get(url, headers: headers)
|
29
|
+
JSON.parse(res.body.to_s)
|
30
|
+
rescue HTTPError
|
31
|
+
nil
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/mihari/analyzers/otx.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "
|
3
|
+
require "mihari/analyzers/clients/otx"
|
4
4
|
|
5
5
|
module Mihari
|
6
6
|
module Analyzers
|
@@ -34,12 +34,8 @@ module Mihari
|
|
34
34
|
%w[otx_api_key]
|
35
35
|
end
|
36
36
|
|
37
|
-
def
|
38
|
-
@
|
39
|
-
end
|
40
|
-
|
41
|
-
def ip_client
|
42
|
-
@ip_client ||= ::OTX::IP.new(api_key)
|
37
|
+
def client
|
38
|
+
@client ||= Mihari::Analyzers::Clients::OTX.new(api_key)
|
43
39
|
end
|
44
40
|
|
45
41
|
#
|
@@ -73,9 +69,15 @@ module Mihari
|
|
73
69
|
# @return [Array<String>]
|
74
70
|
#
|
75
71
|
def domain_search
|
76
|
-
|
72
|
+
res = client.query_by_domain(query)
|
73
|
+
return [] if res.nil?
|
74
|
+
|
75
|
+
records = res["passive_dns"] || []
|
77
76
|
records.filter_map do |record|
|
78
|
-
|
77
|
+
record_type = record["record_type"]
|
78
|
+
address = record["address"]
|
79
|
+
|
80
|
+
address if record_type == "A"
|
79
81
|
end.uniq
|
80
82
|
end
|
81
83
|
|
@@ -85,9 +87,15 @@ module Mihari
|
|
85
87
|
# @return [Array<String>]
|
86
88
|
#
|
87
89
|
def ip_search
|
88
|
-
|
90
|
+
res = client.query_by_ip(query)
|
91
|
+
return [] if res.nil?
|
92
|
+
|
93
|
+
records = res["passive_dns"] || []
|
89
94
|
records.filter_map do |record|
|
90
|
-
|
95
|
+
record_type = record["record_type"]
|
96
|
+
hostname = record["hostname"]
|
97
|
+
|
98
|
+
hostname if record_type == "A"
|
91
99
|
end.uniq
|
92
100
|
end
|
93
101
|
end
|
@@ -39,7 +39,6 @@ module Mihari
|
|
39
39
|
|
40
40
|
class Rule < Base
|
41
41
|
include Mixins::DisallowedDataValue
|
42
|
-
include Mixins::Rule
|
43
42
|
|
44
43
|
option :title
|
45
44
|
option :description
|
@@ -51,6 +50,7 @@ module Mihari
|
|
51
50
|
option :disallowed_data_values, default: proc { [] }
|
52
51
|
|
53
52
|
option :emitters, optional: true
|
53
|
+
option :enrichers, optional: true
|
54
54
|
|
55
55
|
attr_reader :source
|
56
56
|
|
@@ -60,6 +60,7 @@ module Mihari
|
|
60
60
|
@source = id
|
61
61
|
|
62
62
|
@emitters = emitters || DEFAULT_EMITTERS
|
63
|
+
@enrichers = enrichers || DEFAULT_ENRICHERS
|
63
64
|
|
64
65
|
validate_analyzer_configurations
|
65
66
|
end
|
@@ -112,6 +113,21 @@ module Mihari
|
|
112
113
|
end
|
113
114
|
end
|
114
115
|
|
116
|
+
#
|
117
|
+
# Enriched artifacts
|
118
|
+
#
|
119
|
+
# @return [Array<Mihari::Artifact>]
|
120
|
+
#
|
121
|
+
def enriched_artifacts
|
122
|
+
@enriched_artifacts ||= Parallel.map(unique_artifacts) do |artifact|
|
123
|
+
enrichers.each do |enricher|
|
124
|
+
artifact.enrich_by_enricher(enricher[:enricher])
|
125
|
+
end
|
126
|
+
|
127
|
+
artifact
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
115
131
|
#
|
116
132
|
# Normalized disallowed data values
|
117
133
|
#
|
data/lib/mihari/commands/init.rb
CHANGED
@@ -3,8 +3,6 @@
|
|
3
3
|
module Mihari
|
4
4
|
module Commands
|
5
5
|
module Initialization
|
6
|
-
include Mixins::Rule
|
7
|
-
|
8
6
|
def self.included(thor)
|
9
7
|
thor.class_eval do
|
10
8
|
desc "rule", "Create a rule file"
|
@@ -21,6 +19,31 @@ module Mihari
|
|
21
19
|
|
22
20
|
Mihari.logger.info "The rule file is initialized as #{filename}."
|
23
21
|
end
|
22
|
+
|
23
|
+
no_commands do
|
24
|
+
#
|
25
|
+
# Returns a template for rule
|
26
|
+
#
|
27
|
+
# @return [String] A template for rule
|
28
|
+
#
|
29
|
+
def rule_template
|
30
|
+
rule = Structs::Rule.from_path_or_id File.expand_path("../templates/rule.yml.erb", __dir__)
|
31
|
+
rule.yaml
|
32
|
+
end
|
33
|
+
|
34
|
+
#
|
35
|
+
# Create (blank) rule file
|
36
|
+
#
|
37
|
+
# @param [String] filename
|
38
|
+
# @param [Dry::Files] files
|
39
|
+
# @param [String] template
|
40
|
+
#
|
41
|
+
# @return [nil]
|
42
|
+
#
|
43
|
+
def initialize_rule_yaml(filename, files = Dry::Files.new, template: rule_template)
|
44
|
+
files.write(filename, template)
|
45
|
+
end
|
46
|
+
end
|
24
47
|
end
|
25
48
|
end
|
26
49
|
end
|
@@ -4,7 +4,6 @@ module Mihari
|
|
4
4
|
module Commands
|
5
5
|
module Search
|
6
6
|
include Mixins::Database
|
7
|
-
include Mixins::Rule
|
8
7
|
include Mixins::ErrorNotification
|
9
8
|
|
10
9
|
def self.included(thor)
|
@@ -12,14 +11,10 @@ module Mihari
|
|
12
11
|
desc "search [RULE]", "Search by a rule"
|
13
12
|
method_option :yes, type: :boolean, aliases: "-y", desc: "yes to overwrite the rule in the database"
|
14
13
|
def search_by_rule(path_or_id)
|
15
|
-
rule =
|
14
|
+
rule = Structs::Rule.from_path_or_id path_or_id
|
16
15
|
|
17
16
|
# validate
|
18
|
-
|
19
|
-
validate_rule! rule
|
20
|
-
rescue RuleValidationError => e
|
21
|
-
raise e
|
22
|
-
end
|
17
|
+
rule.validate!
|
23
18
|
|
24
19
|
# check update
|
25
20
|
id = rule.id
|
@@ -3,16 +3,21 @@
|
|
3
3
|
module Mihari
|
4
4
|
module Commands
|
5
5
|
module Validator
|
6
|
-
include Mixins::Rule
|
7
|
-
|
8
6
|
def self.included(thor)
|
9
7
|
thor.class_eval do
|
10
|
-
desc "rule [PATH]", "Validate
|
8
|
+
desc "rule [PATH]", "Validate rule file format"
|
9
|
+
#
|
10
|
+
# Validate format of a rule
|
11
|
+
#
|
12
|
+
# @param [String] path
|
13
|
+
#
|
14
|
+
# @return [nil]
|
15
|
+
#
|
11
16
|
def rule(path)
|
12
|
-
rule =
|
17
|
+
rule = Structs::Rule.from_path_or_id(path)
|
13
18
|
|
14
19
|
begin
|
15
|
-
|
20
|
+
rule.validate!
|
16
21
|
Mihari.logger.info "Valid format. The input is parsed as the following:\n#{rule.data.to_yaml}"
|
17
22
|
rescue RuleValidationError
|
18
23
|
nil
|
data/lib/mihari/constants.rb
CHANGED
@@ -4,4 +4,6 @@ module Mihari
|
|
4
4
|
ALLOWED_DATA_TYPES = ["hash", "ip", "domain", "url", "mail"].freeze
|
5
5
|
|
6
6
|
DEFAULT_EMITTERS = ["database", "misp", "slack", "the_hive", "webhook"].map { |name| { emitter: name } }.freeze
|
7
|
+
|
8
|
+
DEFAULT_ENRICHERS = ["whois", "ipinfo", "shodan", "google_public_dns"].map { |name| { enricher: name } }.freeze
|
7
9
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "net/https"
|
4
|
+
|
5
|
+
module Mihari
|
6
|
+
module Enrichers
|
7
|
+
class GooglePublicDNS < Base
|
8
|
+
# @return [Boolean]
|
9
|
+
def valid?
|
10
|
+
true
|
11
|
+
end
|
12
|
+
|
13
|
+
class << self
|
14
|
+
#
|
15
|
+
# Query Google Public DNS
|
16
|
+
#
|
17
|
+
# @param [String] name
|
18
|
+
# @param [String] resource_type
|
19
|
+
#
|
20
|
+
# @return [Mihari::Structs::Shodan::GooglePublicDNS::Response, nil]
|
21
|
+
#
|
22
|
+
def query(name, resource_type)
|
23
|
+
url = "https://dns.google/resolve"
|
24
|
+
params = { name: name, type: resource_type }
|
25
|
+
res = HTTP.get(url, params: params)
|
26
|
+
|
27
|
+
data = JSON.parse(res.body.to_s)
|
28
|
+
|
29
|
+
Structs::GooglePublicDNS::Response.from_dynamic! data
|
30
|
+
rescue HTTPError
|
31
|
+
nil
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "whois-parser"
|
4
|
+
|
5
|
+
module Mihari
|
6
|
+
module Enrichers
|
7
|
+
class Whois < Base
|
8
|
+
@memo = {}
|
9
|
+
|
10
|
+
# @return [Boolean]
|
11
|
+
def valid?
|
12
|
+
true
|
13
|
+
end
|
14
|
+
|
15
|
+
class << self
|
16
|
+
#
|
17
|
+
# Query IAIA Whois API
|
18
|
+
#
|
19
|
+
# @param [String] name
|
20
|
+
#
|
21
|
+
# @return [Mihari::WhoisRecord, nil]
|
22
|
+
#
|
23
|
+
def query(domain)
|
24
|
+
domain = PublicSuffix.domain(domain)
|
25
|
+
|
26
|
+
# check memo
|
27
|
+
if @memo.key?(domain)
|
28
|
+
whois_record = @memo[domain]
|
29
|
+
# return clone of the record
|
30
|
+
return whois_record.dup
|
31
|
+
end
|
32
|
+
|
33
|
+
record = ::Whois.whois(domain)
|
34
|
+
parser = record.parser
|
35
|
+
|
36
|
+
return nil if parser.available?
|
37
|
+
|
38
|
+
whois_record = WhoisRecord.new(
|
39
|
+
domain: domain,
|
40
|
+
created_on: get_created_on(parser),
|
41
|
+
updated_on: get_updated_on(parser),
|
42
|
+
expires_on: get_expires_on(parser),
|
43
|
+
registrar: get_registrar(parser),
|
44
|
+
contacts: get_contacts(parser)
|
45
|
+
)
|
46
|
+
# set memo
|
47
|
+
@memo[domain] = whois_record
|
48
|
+
whois_record
|
49
|
+
rescue ::Whois::Error, ::Whois::ParserError, Timeout::Error
|
50
|
+
nil
|
51
|
+
end
|
52
|
+
|
53
|
+
def reset_cache
|
54
|
+
@memo = {}
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
#
|
60
|
+
# Get created_on
|
61
|
+
#
|
62
|
+
# @param [::Whois::Parser:] parser
|
63
|
+
#
|
64
|
+
# @return [Date, nil]
|
65
|
+
#
|
66
|
+
def get_created_on(parser)
|
67
|
+
parser.created_on
|
68
|
+
rescue ::Whois::AttributeNotImplemented
|
69
|
+
nil
|
70
|
+
end
|
71
|
+
|
72
|
+
#
|
73
|
+
# Get updated_on
|
74
|
+
#
|
75
|
+
# @param [::Whois::Parser:] parser
|
76
|
+
#
|
77
|
+
# @return [Date, nil]
|
78
|
+
#
|
79
|
+
def get_updated_on(parser)
|
80
|
+
parser.updated_on
|
81
|
+
rescue ::Whois::AttributeNotImplemented
|
82
|
+
nil
|
83
|
+
end
|
84
|
+
|
85
|
+
#
|
86
|
+
# Get expires_on
|
87
|
+
#
|
88
|
+
# @param [::Whois::Parser:] parser
|
89
|
+
#
|
90
|
+
# @return [Date, nil]
|
91
|
+
#
|
92
|
+
def get_expires_on(parser)
|
93
|
+
parser.expires_on
|
94
|
+
rescue ::Whois::AttributeNotImplemented
|
95
|
+
nil
|
96
|
+
end
|
97
|
+
|
98
|
+
#
|
99
|
+
# Get registrar
|
100
|
+
#
|
101
|
+
# @param [::Whois::Parser:] parser
|
102
|
+
#
|
103
|
+
# @return [Hash, nil]
|
104
|
+
#
|
105
|
+
def get_registrar(parser)
|
106
|
+
parser.registrar&.to_h
|
107
|
+
rescue ::Whois::AttributeNotImplemented
|
108
|
+
nil
|
109
|
+
end
|
110
|
+
|
111
|
+
#
|
112
|
+
# Get contacts
|
113
|
+
#
|
114
|
+
# @param [::Whois::Parser:] parser
|
115
|
+
#
|
116
|
+
# @return [Array[Hash], nil]
|
117
|
+
#
|
118
|
+
def get_contacts(parser)
|
119
|
+
parser.contacts.map(&:to_h)
|
120
|
+
rescue ::Whois::AttributeNotImplemented
|
121
|
+
nil
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
data/lib/mihari/errors.rb
CHANGED
data/lib/mihari/http.rb
CHANGED
@@ -44,8 +44,8 @@ module Mihari
|
|
44
44
|
end
|
45
45
|
|
46
46
|
class << self
|
47
|
-
def get(uri, headers: {},
|
48
|
-
client = new(uri, headers: headers, payload:
|
47
|
+
def get(uri, headers: {}, params: {})
|
48
|
+
client = new(uri, headers: headers, payload: params)
|
49
49
|
client.get
|
50
50
|
end
|
51
51
|
|
data/lib/mihari/models/alert.rb
CHANGED
@@ -12,7 +12,7 @@ module Mihari
|
|
12
12
|
#
|
13
13
|
# Search alerts
|
14
14
|
#
|
15
|
-
# @param [Structs::Alert::SearchFilterWithPagination] filter
|
15
|
+
# @param [Structs::Filters::Alert::SearchFilterWithPagination] filter
|
16
16
|
#
|
17
17
|
# @return [Array<Alert>]
|
18
18
|
#
|
@@ -58,6 +58,11 @@ module Mihari
|
|
58
58
|
|
59
59
|
private
|
60
60
|
|
61
|
+
#
|
62
|
+
# @param [Structs::Filters::Alert::SearchFilter] filter
|
63
|
+
#
|
64
|
+
# @return [Mihari::Alert]
|
65
|
+
#
|
61
66
|
def build_relation(filter)
|
62
67
|
artifact_ids = []
|
63
68
|
artifact = Artifact.includes(:autonomous_system, :dns_records, :reverse_dns_names)
|
@@ -135,6 +135,36 @@ module Mihari
|
|
135
135
|
enrich_cpes
|
136
136
|
end
|
137
137
|
|
138
|
+
ENRICH_METHODS_BY_ENRICHER = {
|
139
|
+
whois: [
|
140
|
+
:enrich_whois
|
141
|
+
],
|
142
|
+
ipinfo: [
|
143
|
+
:enrich_autonomous_system,
|
144
|
+
:enrich_geolocation
|
145
|
+
],
|
146
|
+
shodan: [
|
147
|
+
:enrich_ports,
|
148
|
+
:enrich_cpes,
|
149
|
+
:enrich_reverse_dns
|
150
|
+
],
|
151
|
+
google_public_dns: [
|
152
|
+
:enrich_dns
|
153
|
+
]
|
154
|
+
}.freeze
|
155
|
+
|
156
|
+
#
|
157
|
+
# Enrich by name of enricher
|
158
|
+
#
|
159
|
+
# @param [String] enricher
|
160
|
+
#
|
161
|
+
def enrich_by_enricher(enricher)
|
162
|
+
methods = ENRICH_METHODS_BY_ENRICHER[enricher.downcase.to_sym] || []
|
163
|
+
methods.each do |method|
|
164
|
+
send(method) if respond_to?(method)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
138
168
|
private
|
139
169
|
|
140
170
|
def normalize_as_domain(url_or_domain)
|
data/lib/mihari/models/dns.rb
CHANGED
@@ -13,14 +13,7 @@ module Mihari
|
|
13
13
|
# @return [Array<Mihari::DnsRecord>]
|
14
14
|
#
|
15
15
|
def build_by_domain(domain)
|
16
|
-
resource_types = [
|
17
|
-
Resolv::DNS::Resource::IN::A,
|
18
|
-
Resolv::DNS::Resource::IN::AAAA,
|
19
|
-
Resolv::DNS::Resource::IN::CNAME,
|
20
|
-
Resolv::DNS::Resource::IN::TXT,
|
21
|
-
Resolv::DNS::Resource::IN::NS
|
22
|
-
]
|
23
|
-
|
16
|
+
resource_types = %w[A AAAA CNAME TXT NS]
|
24
17
|
resource_types.map do |resource_type|
|
25
18
|
get_values domain, resource_type
|
26
19
|
rescue Resolv::ResolvError
|
@@ -31,20 +24,11 @@ module Mihari
|
|
31
24
|
private
|
32
25
|
|
33
26
|
def get_values(domain, resource_type)
|
34
|
-
|
35
|
-
|
27
|
+
response = Enrichers::GooglePublicDNS.query(domain, resource_type)
|
28
|
+
answers = response.answers || []
|
36
29
|
|
37
|
-
|
38
|
-
|
39
|
-
if resource.respond_to?(:address)
|
40
|
-
new(resource: resource_name, value: resource.address.to_s)
|
41
|
-
# CNAME, NS
|
42
|
-
elsif resource.respond_to?(:name)
|
43
|
-
new(resource: resource_name, value: resource.name.to_s)
|
44
|
-
# TXT
|
45
|
-
elsif resource.respond_to?(:data)
|
46
|
-
new(resource: resource_name, value: resource.data.to_s)
|
47
|
-
end
|
30
|
+
answers.filter_map do |answer|
|
31
|
+
new(resource: answer.resource_type, value: answer.data)
|
48
32
|
end
|
49
33
|
end
|
50
34
|
end
|
@@ -17,11 +17,9 @@ module Mihari
|
|
17
17
|
def build_by_ip(ip)
|
18
18
|
res = Enrichers::IPInfo.query(ip)
|
19
19
|
|
20
|
-
|
21
|
-
return new(country: NormalizeCountry(res.country_code, to: :short), country_code: res.country_code)
|
22
|
-
end
|
20
|
+
return nil if res&.country_code.nil?
|
23
21
|
|
24
|
-
|
22
|
+
new(country: NormalizeCountry(res.country_code, to: :short), country_code: res.country_code)
|
25
23
|
end
|
26
24
|
end
|
27
25
|
end
|
data/lib/mihari/models/port.rb
CHANGED
data/lib/mihari/models/rule.rb
CHANGED
@@ -28,7 +28,7 @@ module Mihari
|
|
28
28
|
#
|
29
29
|
# Search rules
|
30
30
|
#
|
31
|
-
# @param [Structs::Rule::SearchFilterWithPagination] filter
|
31
|
+
# @param [Structs::Filters::Rule::SearchFilterWithPagination] filter
|
32
32
|
#
|
33
33
|
# @return [Array<Rule>]
|
34
34
|
#
|
@@ -51,7 +51,7 @@ module Mihari
|
|
51
51
|
#
|
52
52
|
# Count alerts
|
53
53
|
#
|
54
|
-
# @param [Structs::Rule::SearchFilterWithPagination] filter
|
54
|
+
# @param [Structs::Filters::Rule::SearchFilterWithPagination] filter
|
55
55
|
#
|
56
56
|
# @return [Integer]
|
57
57
|
#
|
@@ -62,6 +62,11 @@ module Mihari
|
|
62
62
|
|
63
63
|
private
|
64
64
|
|
65
|
+
#
|
66
|
+
# @param [Structs::Filters::Rule::SearchFilter] filter
|
67
|
+
#
|
68
|
+
# @return [Mihari::Rule]
|
69
|
+
#
|
65
70
|
def build_relation(filter)
|
66
71
|
relation = self
|
67
72
|
relation = relation.includes(alerts: :tags)
|