mihari 4.6.1 → 4.7.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/lib/mihari/analyzers/rule.rb +17 -0
- 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/http.rb +2 -2
- data/lib/mihari/models/artifact.rb +30 -0
- data/lib/mihari/models/dns.rb +5 -21
- 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/google_public_dns.rb +42 -0
- data/lib/mihari/structs/rule.rb +2 -1
- data/lib/mihari/types.rb +7 -0
- data/lib/mihari/version.rb +1 -1
- data/lib/mihari.rb +3 -0
- data/mihari.gemspec +5 -5
- data/sig/lib/mihari/enrichers/google_public_dns.rbs +18 -0
- data/sig/lib/mihari/structs/google_public_dns.rbs +21 -0
- metadata +18 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '091892853042ab3f1010c89b943eb2a885370da2d619016f3f3cd9dcb59e80cf'
|
4
|
+
data.tar.gz: 119ccbb407a49c741a4bf6c7cfafc7cd99855c3af950af9d0f1dc3735fc24672
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5364837634a6cde1b370db5613e745f05b40bf7321a5b7fcc4a2c7d32b1d395fa45e4472ef2a5f9f28d664f0b45e31d0554acec7bb641a21ce179ebf70bf9317
|
7
|
+
data.tar.gz: 57ca2f920db2da9e8c9a10f59aa81984dff0a81f0073ba839c351f3fe5e7979358ce44d87f48adcffd7df1bf7268bab178fec82731f72d62c24aa9ce04eed026
|
@@ -51,6 +51,7 @@ module Mihari
|
|
51
51
|
option :disallowed_data_values, default: proc { [] }
|
52
52
|
|
53
53
|
option :emitters, optional: true
|
54
|
+
option :enrichers, optional: true
|
54
55
|
|
55
56
|
attr_reader :source
|
56
57
|
|
@@ -60,6 +61,7 @@ module Mihari
|
|
60
61
|
@source = id
|
61
62
|
|
62
63
|
@emitters = emitters || DEFAULT_EMITTERS
|
64
|
+
@enrichers = enrichers || DEFAULT_ENRICHERS
|
63
65
|
|
64
66
|
validate_analyzer_configurations
|
65
67
|
end
|
@@ -112,6 +114,21 @@ module Mihari
|
|
112
114
|
end
|
113
115
|
end
|
114
116
|
|
117
|
+
#
|
118
|
+
# Enriched artifacts
|
119
|
+
#
|
120
|
+
# @return [Array<Mihari::Artifact>]
|
121
|
+
#
|
122
|
+
def enriched_artifacts
|
123
|
+
@enriched_artifacts ||= Parallel.map(unique_artifacts) do |artifact|
|
124
|
+
enrichers.each do |enricher|
|
125
|
+
artifact.enrich_by_enricher(enricher[:enricher])
|
126
|
+
end
|
127
|
+
|
128
|
+
artifact
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
115
132
|
#
|
116
133
|
# Normalized disallowed data values
|
117
134
|
#
|
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/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
|
|
@@ -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
|
data/lib/mihari/models/whois.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "whois-parser"
|
4
|
-
|
5
3
|
module Mihari
|
6
4
|
class WhoisRecord < ActiveRecord::Base
|
7
5
|
belongs_to :artifact
|
@@ -17,100 +15,7 @@ module Mihari
|
|
17
15
|
# @return [WhoisRecord, nil]
|
18
16
|
#
|
19
17
|
def build_by_domain(domain)
|
20
|
-
|
21
|
-
|
22
|
-
# check memo
|
23
|
-
if @memo.key?(domain)
|
24
|
-
whois_record = @memo[domain]
|
25
|
-
# return clone of the record
|
26
|
-
return whois_record.dup
|
27
|
-
end
|
28
|
-
|
29
|
-
record = Whois.whois(domain)
|
30
|
-
parser = record.parser
|
31
|
-
|
32
|
-
return nil if parser.available?
|
33
|
-
|
34
|
-
whois_record = new(
|
35
|
-
domain: domain,
|
36
|
-
created_on: get_created_on(parser),
|
37
|
-
updated_on: get_updated_on(parser),
|
38
|
-
expires_on: get_expires_on(parser),
|
39
|
-
registrar: get_registrar(parser),
|
40
|
-
contacts: get_contacts(parser)
|
41
|
-
)
|
42
|
-
# set memo
|
43
|
-
@memo[domain] = whois_record
|
44
|
-
whois_record
|
45
|
-
rescue Whois::Error, Whois::ParserError, Timeout::Error
|
46
|
-
nil
|
47
|
-
end
|
48
|
-
|
49
|
-
private
|
50
|
-
|
51
|
-
#
|
52
|
-
# Get created_on
|
53
|
-
#
|
54
|
-
# @param [::Whois::Parser:] parser
|
55
|
-
#
|
56
|
-
# @return [Date, nil]
|
57
|
-
#
|
58
|
-
def get_created_on(parser)
|
59
|
-
parser.created_on
|
60
|
-
rescue ::Whois::AttributeNotImplemented
|
61
|
-
nil
|
62
|
-
end
|
63
|
-
|
64
|
-
#
|
65
|
-
# Get updated_on
|
66
|
-
#
|
67
|
-
# @param [::Whois::Parser:] parser
|
68
|
-
#
|
69
|
-
# @return [Date, nil]
|
70
|
-
#
|
71
|
-
def get_updated_on(parser)
|
72
|
-
parser.updated_on
|
73
|
-
rescue ::Whois::AttributeNotImplemented
|
74
|
-
nil
|
75
|
-
end
|
76
|
-
|
77
|
-
#
|
78
|
-
# Get expires_on
|
79
|
-
#
|
80
|
-
# @param [::Whois::Parser:] parser
|
81
|
-
#
|
82
|
-
# @return [Date, nil]
|
83
|
-
#
|
84
|
-
def get_expires_on(parser)
|
85
|
-
parser.expires_on
|
86
|
-
rescue ::Whois::AttributeNotImplemented
|
87
|
-
nil
|
88
|
-
end
|
89
|
-
|
90
|
-
#
|
91
|
-
# Get registrar
|
92
|
-
#
|
93
|
-
# @param [::Whois::Parser:] parser
|
94
|
-
#
|
95
|
-
# @return [Hash, nil]
|
96
|
-
#
|
97
|
-
def get_registrar(parser)
|
98
|
-
parser.registrar&.to_h
|
99
|
-
rescue ::Whois::AttributeNotImplemented
|
100
|
-
nil
|
101
|
-
end
|
102
|
-
|
103
|
-
#
|
104
|
-
# Get contacts
|
105
|
-
#
|
106
|
-
# @param [::Whois::Parser:] parser
|
107
|
-
#
|
108
|
-
# @return [Array[Hash], nil]
|
109
|
-
#
|
110
|
-
def get_contacts(parser)
|
111
|
-
parser.contacts.map(&:to_h)
|
112
|
-
rescue ::Whois::AttributeNotImplemented
|
113
|
-
nil
|
18
|
+
Enrichers::Whois.query domain
|
114
19
|
end
|
115
20
|
end
|
116
21
|
end
|
data/lib/mihari/schemas/rule.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require "mihari/schemas/analyzer"
|
4
4
|
require "mihari/schemas/emitter"
|
5
|
+
require "mihari/schemas/enricher"
|
5
6
|
|
6
7
|
module Mihari
|
7
8
|
module Schemas
|
@@ -20,6 +21,8 @@ module Mihari
|
|
20
21
|
|
21
22
|
optional(:emitters).value(:array).each { Emitter | MISP | TheHive | Slack | HTTP }
|
22
23
|
|
24
|
+
optional(:enrichers).value(:array).each(Enricher)
|
25
|
+
|
23
26
|
optional(:allowed_data_types).value(array[Types::DataTypes]).default(ALLOWED_DATA_TYPES)
|
24
27
|
optional(:disallowed_data_values).value(array[:string]).default([])
|
25
28
|
|
@@ -35,6 +38,9 @@ module Mihari
|
|
35
38
|
emitters = h[:emitters]
|
36
39
|
h[:emitters] = emitters || DEFAULT_EMITTERS
|
37
40
|
|
41
|
+
enrichers = h[:enrichers]
|
42
|
+
h[:enrichers] = enrichers || DEFAULT_ENRICHERS
|
43
|
+
|
38
44
|
h
|
39
45
|
end
|
40
46
|
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mihari
|
4
|
+
module Structs
|
5
|
+
module GooglePublicDNS
|
6
|
+
INT_TYPE_TO_TYPE = {
|
7
|
+
1 => "A",
|
8
|
+
2 => "NS",
|
9
|
+
5 => "CNAME",
|
10
|
+
16 => "TXT",
|
11
|
+
28 => "AAAA"
|
12
|
+
}
|
13
|
+
|
14
|
+
class Answer < Dry::Struct
|
15
|
+
attribute :name, Types::String
|
16
|
+
attribute :data, Types::String
|
17
|
+
attribute :resource_type, Types::String
|
18
|
+
|
19
|
+
def self.from_dynamic!(d)
|
20
|
+
d = Types::Hash[d]
|
21
|
+
resource_type = INT_TYPE_TO_TYPE[d.fetch("type")]
|
22
|
+
new(
|
23
|
+
name: d.fetch("name"),
|
24
|
+
data: d.fetch("data"),
|
25
|
+
resource_type: resource_type
|
26
|
+
)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class Response < Dry::Struct
|
31
|
+
attribute :answers, Types.Array(Answer)
|
32
|
+
|
33
|
+
def self.from_dynamic!(d)
|
34
|
+
d = Types::Hash[d]
|
35
|
+
new(
|
36
|
+
answers: d.fetch("Answer", []).map { |x| Answer.from_dynamic!(x) }
|
37
|
+
)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/mihari/structs/rule.rb
CHANGED
@@ -88,7 +88,7 @@ module Mihari
|
|
88
88
|
|
89
89
|
raise RuleValidationError, error_messages.join("\n") if errors?
|
90
90
|
|
91
|
-
raise RuleValidationError, "Something wrong with queries or
|
91
|
+
raise RuleValidationError, "Something wrong with queries, emitters or enrichers." unless @no_method_error.nil?
|
92
92
|
end
|
93
93
|
|
94
94
|
def [](key)
|
@@ -150,6 +150,7 @@ module Mihari
|
|
150
150
|
allowed_data_types: self[:allowed_data_types],
|
151
151
|
disallowed_data_values: self[:disallowed_data_values],
|
152
152
|
emitters: self[:emitters],
|
153
|
+
enrichers: self[:enrichers],
|
153
154
|
id: id
|
154
155
|
)
|
155
156
|
analyzer.ignore_old_artifacts = self[:ignore_old_artifacts]
|
data/lib/mihari/types.rb
CHANGED
data/lib/mihari/version.rb
CHANGED
data/lib/mihari.rb
CHANGED
@@ -173,6 +173,7 @@ require "mihari/types"
|
|
173
173
|
# Structs
|
174
174
|
require "mihari/structs/alert"
|
175
175
|
require "mihari/structs/censys"
|
176
|
+
require "mihari/structs/google_public_dns"
|
176
177
|
require "mihari/structs/greynoise"
|
177
178
|
require "mihari/structs/ipinfo"
|
178
179
|
require "mihari/structs/onyphe"
|
@@ -189,8 +190,10 @@ require "mihari/schemas/rule"
|
|
189
190
|
|
190
191
|
# Enrichers
|
191
192
|
require "mihari/enrichers/base"
|
193
|
+
require "mihari/enrichers/google_public_dns"
|
192
194
|
require "mihari/enrichers/ipinfo"
|
193
195
|
require "mihari/enrichers/shodan"
|
196
|
+
require "mihari/enrichers/whois"
|
194
197
|
|
195
198
|
# Models
|
196
199
|
require "mihari/models/alert"
|
data/mihari.gemspec
CHANGED
@@ -29,7 +29,7 @@ Gem::Specification.new do |spec|
|
|
29
29
|
|
30
30
|
spec.add_development_dependency "bundler", "~> 2.3"
|
31
31
|
spec.add_development_dependency "coveralls_reborn", "~> 0.24"
|
32
|
-
spec.add_development_dependency "fakefs", "~> 1.
|
32
|
+
spec.add_development_dependency "fakefs", "~> 1.5"
|
33
33
|
spec.add_development_dependency "mysql2", "~> 0.5"
|
34
34
|
spec.add_development_dependency "overcommit", "~> 0.59"
|
35
35
|
spec.add_development_dependency "pg", "~> 1.3"
|
@@ -40,7 +40,7 @@ Gem::Specification.new do |spec|
|
|
40
40
|
spec.add_development_dependency "rspec", "~> 3.11"
|
41
41
|
spec.add_development_dependency "simplecov-lcov", "~> 0.8.0"
|
42
42
|
spec.add_development_dependency "standard", "~> 1.12"
|
43
|
-
spec.add_development_dependency "steep", "~> 0
|
43
|
+
spec.add_development_dependency "steep", "~> 1.0"
|
44
44
|
spec.add_development_dependency "timecop", "~> 0.9"
|
45
45
|
spec.add_development_dependency "vcr", "~> 6.1"
|
46
46
|
spec.add_development_dependency "webmock", "~> 3.14"
|
@@ -58,9 +58,9 @@ Gem::Specification.new do |spec|
|
|
58
58
|
spec.add_dependency "dry-container", "0.9.0"
|
59
59
|
spec.add_dependency "dry-files", "0.1.0"
|
60
60
|
spec.add_dependency "dry-initializer", "3.1.1"
|
61
|
-
spec.add_dependency "dry-schema", "1.9.
|
61
|
+
spec.add_dependency "dry-schema", "1.9.2"
|
62
62
|
spec.add_dependency "dry-struct", "1.4.0"
|
63
|
-
spec.add_dependency "dry-validation", "1.8.
|
63
|
+
spec.add_dependency "dry-validation", "1.8.1"
|
64
64
|
spec.add_dependency "email_address", "0.2.3"
|
65
65
|
spec.add_dependency "grape", "1.6.2"
|
66
66
|
spec.add_dependency "grape-entity", "0.10.1"
|
@@ -84,7 +84,7 @@ Gem::Specification.new do |spec|
|
|
84
84
|
spec.add_dependency "public_suffix", "4.0.7"
|
85
85
|
spec.add_dependency "pulsedive", "0.1.5"
|
86
86
|
spec.add_dependency "puma", "5.6.4"
|
87
|
-
spec.add_dependency "rack", "2.2.3"
|
87
|
+
spec.add_dependency "rack", "2.2.3.1"
|
88
88
|
spec.add_dependency "rack-contrib", "2.3.0"
|
89
89
|
spec.add_dependency "rack-cors", "1.1.1"
|
90
90
|
spec.add_dependency "securitytrails", "1.0.0"
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Mihari
|
2
|
+
module Enrichers
|
3
|
+
class GooglePublicDNS < Base
|
4
|
+
# @return [Boolean]
|
5
|
+
def valid?: () -> true
|
6
|
+
|
7
|
+
#
|
8
|
+
# Query Google Public DNS
|
9
|
+
#
|
10
|
+
# @param [String] name
|
11
|
+
# @param [String] resource_type
|
12
|
+
#
|
13
|
+
# @return [Mihari::Structs::Shodan::GooglePublicDNS::Response, nil]
|
14
|
+
#
|
15
|
+
def self.query: (String name, String resource_type) -> Mihari::Structs::Shodan::GooglePublicDNS::Response?
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Mihari
|
2
|
+
module Structs
|
3
|
+
module GooglePublicDNS
|
4
|
+
INT_TYPE_TO_TYPE: { 1 => "A", 2 => "NS", 5 => "CNAME", 16 => "TXT", 28 => "AAAA" }
|
5
|
+
|
6
|
+
class Answer < Dry::Struct
|
7
|
+
attr_reader name: String
|
8
|
+
attr_reader data: String
|
9
|
+
attr_reader resource_type: String
|
10
|
+
|
11
|
+
def self.from_dynamic!: (Hash[(String | Symbol), untyped] d) -> Mihari::Structs::GooglePublicDNS::Answer
|
12
|
+
end
|
13
|
+
|
14
|
+
class Response < Dry::Struct
|
15
|
+
attr_reader answers: Array[Mihari::Structs::GooglePublicDNS::Answer]
|
16
|
+
|
17
|
+
def self.from_dynamic!: (Hash[(String | Symbol), untyped] d) -> Mihari::Structs::GooglePublicDNS::Response
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mihari
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.
|
4
|
+
version: 4.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Manabu Niseki
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-05
|
11
|
+
date: 2022-06-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -44,14 +44,14 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '1.
|
47
|
+
version: '1.5'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '1.
|
54
|
+
version: '1.5'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: mysql2
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -198,14 +198,14 @@ dependencies:
|
|
198
198
|
requirements:
|
199
199
|
- - "~>"
|
200
200
|
- !ruby/object:Gem::Version
|
201
|
-
version: '0
|
201
|
+
version: '1.0'
|
202
202
|
type: :development
|
203
203
|
prerelease: false
|
204
204
|
version_requirements: !ruby/object:Gem::Requirement
|
205
205
|
requirements:
|
206
206
|
- - "~>"
|
207
207
|
- !ruby/object:Gem::Version
|
208
|
-
version: '0
|
208
|
+
version: '1.0'
|
209
209
|
- !ruby/object:Gem::Dependency
|
210
210
|
name: timecop
|
211
211
|
requirement: !ruby/object:Gem::Requirement
|
@@ -436,14 +436,14 @@ dependencies:
|
|
436
436
|
requirements:
|
437
437
|
- - '='
|
438
438
|
- !ruby/object:Gem::Version
|
439
|
-
version: 1.9.
|
439
|
+
version: 1.9.2
|
440
440
|
type: :runtime
|
441
441
|
prerelease: false
|
442
442
|
version_requirements: !ruby/object:Gem::Requirement
|
443
443
|
requirements:
|
444
444
|
- - '='
|
445
445
|
- !ruby/object:Gem::Version
|
446
|
-
version: 1.9.
|
446
|
+
version: 1.9.2
|
447
447
|
- !ruby/object:Gem::Dependency
|
448
448
|
name: dry-struct
|
449
449
|
requirement: !ruby/object:Gem::Requirement
|
@@ -464,14 +464,14 @@ dependencies:
|
|
464
464
|
requirements:
|
465
465
|
- - '='
|
466
466
|
- !ruby/object:Gem::Version
|
467
|
-
version: 1.8.
|
467
|
+
version: 1.8.1
|
468
468
|
type: :runtime
|
469
469
|
prerelease: false
|
470
470
|
version_requirements: !ruby/object:Gem::Requirement
|
471
471
|
requirements:
|
472
472
|
- - '='
|
473
473
|
- !ruby/object:Gem::Version
|
474
|
-
version: 1.8.
|
474
|
+
version: 1.8.1
|
475
475
|
- !ruby/object:Gem::Dependency
|
476
476
|
name: email_address
|
477
477
|
requirement: !ruby/object:Gem::Requirement
|
@@ -800,14 +800,14 @@ dependencies:
|
|
800
800
|
requirements:
|
801
801
|
- - '='
|
802
802
|
- !ruby/object:Gem::Version
|
803
|
-
version: 2.2.3
|
803
|
+
version: 2.2.3.1
|
804
804
|
type: :runtime
|
805
805
|
prerelease: false
|
806
806
|
version_requirements: !ruby/object:Gem::Requirement
|
807
807
|
requirements:
|
808
808
|
- - '='
|
809
809
|
- !ruby/object:Gem::Version
|
810
|
-
version: 2.2.3
|
810
|
+
version: 2.2.3.1
|
811
811
|
- !ruby/object:Gem::Dependency
|
812
812
|
name: rack-contrib
|
813
813
|
requirement: !ruby/object:Gem::Requirement
|
@@ -1110,8 +1110,10 @@ files:
|
|
1110
1110
|
- lib/mihari/emitters/the_hive.rb
|
1111
1111
|
- lib/mihari/emitters/webhook.rb
|
1112
1112
|
- lib/mihari/enrichers/base.rb
|
1113
|
+
- lib/mihari/enrichers/google_public_dns.rb
|
1113
1114
|
- lib/mihari/enrichers/ipinfo.rb
|
1114
1115
|
- lib/mihari/enrichers/shodan.rb
|
1116
|
+
- lib/mihari/enrichers/whois.rb
|
1115
1117
|
- lib/mihari/entities/alert.rb
|
1116
1118
|
- lib/mihari/entities/artifact.rb
|
1117
1119
|
- lib/mihari/entities/autonomous_system.rb
|
@@ -1153,11 +1155,13 @@ files:
|
|
1153
1155
|
- lib/mihari/models/whois.rb
|
1154
1156
|
- lib/mihari/schemas/analyzer.rb
|
1155
1157
|
- lib/mihari/schemas/emitter.rb
|
1158
|
+
- lib/mihari/schemas/enricher.rb
|
1156
1159
|
- lib/mihari/schemas/macros.rb
|
1157
1160
|
- lib/mihari/schemas/rule.rb
|
1158
1161
|
- lib/mihari/status.rb
|
1159
1162
|
- lib/mihari/structs/alert.rb
|
1160
1163
|
- lib/mihari/structs/censys.rb
|
1164
|
+
- lib/mihari/structs/google_public_dns.rb
|
1161
1165
|
- lib/mihari/structs/greynoise.rb
|
1162
1166
|
- lib/mihari/structs/ipinfo.rb
|
1163
1167
|
- lib/mihari/structs/onyphe.rb
|
@@ -1243,6 +1247,7 @@ files:
|
|
1243
1247
|
- sig/lib/mihari/emitters/the_hive.rbs
|
1244
1248
|
- sig/lib/mihari/emitters/webhook.rbs
|
1245
1249
|
- sig/lib/mihari/enrichers/base.rbs
|
1250
|
+
- sig/lib/mihari/enrichers/google_public_dns.rbs
|
1246
1251
|
- sig/lib/mihari/enrichers/ipinfo.rbs
|
1247
1252
|
- sig/lib/mihari/errors.rbs
|
1248
1253
|
- sig/lib/mihari/feed/parser.rbs
|
@@ -1272,6 +1277,7 @@ files:
|
|
1272
1277
|
- sig/lib/mihari/status.rbs
|
1273
1278
|
- sig/lib/mihari/structs/alert.rbs
|
1274
1279
|
- sig/lib/mihari/structs/censys.rbs
|
1280
|
+
- sig/lib/mihari/structs/google_public_dns.rbs
|
1275
1281
|
- sig/lib/mihari/structs/greynoise.rbs
|
1276
1282
|
- sig/lib/mihari/structs/ipinfo.rbs
|
1277
1283
|
- sig/lib/mihari/structs/onyphe.rbs
|