mihari 5.1.2 → 5.1.3
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/censys.rb +6 -15
- data/lib/mihari/analyzers/circl.rb +8 -17
- data/lib/mihari/analyzers/dnstwister.rb +8 -17
- data/lib/mihari/analyzers/otx.rb +8 -17
- data/lib/mihari/analyzers/passivetotal.rb +10 -19
- data/lib/mihari/analyzers/pulsedive.rb +0 -1
- data/lib/mihari/analyzers/securitytrails.rb +10 -19
- data/lib/mihari/analyzers/shodan.rb +0 -11
- data/lib/mihari/analyzers/urlscan.rb +3 -4
- data/lib/mihari/analyzers/virustotal_intelligence.rb +1 -4
- data/lib/mihari/clients/misp.rb +2 -0
- data/lib/mihari/http.rb +14 -18
- data/lib/mihari/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dd278975834369b3274b38b590f12d4f2fed97d7626363ff3cfbc9845195b386
|
4
|
+
data.tar.gz: 864ee1deae0bdb0390d9e330eb76c993860c37189dce0d23c9793b012f338275
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 258731713400cb40f6da8f24e6ce0213b883eeff98a22a16a88c84568633ad02ad3e18f4e70e6faea428a29bdcdc257b6ec3c86ebea7979065ec2e42ab445c47
|
7
|
+
data.tar.gz: 6c8beea0c3f4aa42f8fb8217a05c6256a6a8ea10daceb05d05ed2884d8b53c86195c765fa70cf35ea19c41d959fd6df114fa2b609893e828def028f5b16b5fc4
|
@@ -27,21 +27,6 @@ module Mihari
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def artifacts
|
30
|
-
search
|
31
|
-
end
|
32
|
-
|
33
|
-
def configured?
|
34
|
-
configuration_keys.all? { |key| Mihari.config.send(key) } || (id? && secret?)
|
35
|
-
end
|
36
|
-
|
37
|
-
private
|
38
|
-
|
39
|
-
#
|
40
|
-
# Search
|
41
|
-
#
|
42
|
-
# @return [Array<String>]
|
43
|
-
#
|
44
|
-
def search
|
45
30
|
artifacts = []
|
46
31
|
|
47
32
|
cursor = nil
|
@@ -58,6 +43,12 @@ module Mihari
|
|
58
43
|
artifacts.flatten.uniq(&:data)
|
59
44
|
end
|
60
45
|
|
46
|
+
def configured?
|
47
|
+
configuration_keys.all? { |key| Mihari.config.send(key) } || (id? && secret?)
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
61
52
|
def configuration_keys
|
62
53
|
%w[censys_id censys_secret]
|
63
54
|
end
|
@@ -30,7 +30,14 @@ module Mihari
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def artifacts
|
33
|
-
|
33
|
+
case type
|
34
|
+
when "domain"
|
35
|
+
passive_dns_search
|
36
|
+
when "hash"
|
37
|
+
passive_ssl_search
|
38
|
+
else
|
39
|
+
raise InvalidInputError, "#{@query}(type: #{@type || "unknown"}) is not supported."
|
40
|
+
end
|
34
41
|
end
|
35
42
|
|
36
43
|
def configured?
|
@@ -47,22 +54,6 @@ module Mihari
|
|
47
54
|
@client ||= Clients::CIRCL.new(username: username, password: password)
|
48
55
|
end
|
49
56
|
|
50
|
-
#
|
51
|
-
# Passive DNS/SSL search
|
52
|
-
#
|
53
|
-
# @return [Array<String>]
|
54
|
-
#
|
55
|
-
def search
|
56
|
-
case @type
|
57
|
-
when "domain"
|
58
|
-
passive_dns_search
|
59
|
-
when "hash"
|
60
|
-
passive_ssl_search
|
61
|
-
else
|
62
|
-
raise InvalidInputError, "#{@query}(type: #{@type || "unknown"}) is not supported."
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
57
|
#
|
67
58
|
# Passive DNS search
|
68
59
|
#
|
@@ -21,7 +21,14 @@ module Mihari
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def artifacts
|
24
|
-
|
24
|
+
raise InvalidInputError, "#{query}(type: #{type || "unknown"}) is not supported." unless valid_type?
|
25
|
+
|
26
|
+
res = client.fuzz(query)
|
27
|
+
fuzzy_domains = res["fuzzy_domains"] || []
|
28
|
+
domains = fuzzy_domains.map { |domain| domain["domain"] }
|
29
|
+
Parallel.map(domains) do |domain|
|
30
|
+
resolvable?(domain) ? domain : nil
|
31
|
+
end.compact
|
25
32
|
end
|
26
33
|
|
27
34
|
private
|
@@ -52,22 +59,6 @@ module Mihari
|
|
52
59
|
rescue Resolv::ResolvError => _e
|
53
60
|
false
|
54
61
|
end
|
55
|
-
|
56
|
-
#
|
57
|
-
# Search
|
58
|
-
#
|
59
|
-
# @return [Array<String>]
|
60
|
-
#
|
61
|
-
def search
|
62
|
-
raise InvalidInputError, "#{query}(type: #{type || "unknown"}) is not supported." unless valid_type?
|
63
|
-
|
64
|
-
res = client.fuzz(query)
|
65
|
-
fuzzy_domains = res["fuzzy_domains"] || []
|
66
|
-
domains = fuzzy_domains.map { |domain| domain["domain"] }
|
67
|
-
Parallel.map(domains) do |domain|
|
68
|
-
resolvable?(domain) ? domain : nil
|
69
|
-
end.compact
|
70
|
-
end
|
71
62
|
end
|
72
63
|
end
|
73
64
|
end
|
data/lib/mihari/analyzers/otx.rb
CHANGED
@@ -26,7 +26,14 @@ module Mihari
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def artifacts
|
29
|
-
|
29
|
+
case type
|
30
|
+
when "domain"
|
31
|
+
domain_search
|
32
|
+
when "ip"
|
33
|
+
ip_search
|
34
|
+
else
|
35
|
+
raise InvalidInputError, "#{query}(type: #{type || "unknown"}) is not supported." unless valid_type?
|
36
|
+
end
|
30
37
|
end
|
31
38
|
|
32
39
|
private
|
@@ -48,22 +55,6 @@ module Mihari
|
|
48
55
|
%w[ip domain].include? type
|
49
56
|
end
|
50
57
|
|
51
|
-
#
|
52
|
-
# IP/domain search
|
53
|
-
#
|
54
|
-
# @return [Array<String>]
|
55
|
-
#
|
56
|
-
def search
|
57
|
-
case type
|
58
|
-
when "domain"
|
59
|
-
domain_search
|
60
|
-
when "ip"
|
61
|
-
ip_search
|
62
|
-
else
|
63
|
-
raise InvalidInputError, "#{query}(type: #{type || "unknown"}) is not supported." unless valid_type?
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
58
|
#
|
68
59
|
# Domain search
|
69
60
|
#
|
@@ -30,7 +30,16 @@ module Mihari
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def artifacts
|
33
|
-
|
33
|
+
case type
|
34
|
+
when "domain", "ip"
|
35
|
+
passive_dns_search
|
36
|
+
when "mail"
|
37
|
+
reverse_whois_search
|
38
|
+
when "hash"
|
39
|
+
ssl_search
|
40
|
+
else
|
41
|
+
raise InvalidInputError, "#{query}(type: #{type || "unknown"}) is not supported." unless valid_type?
|
42
|
+
end
|
34
43
|
end
|
35
44
|
|
36
45
|
def configured?
|
@@ -56,24 +65,6 @@ module Mihari
|
|
56
65
|
%w[ip domain mail hash].include? type
|
57
66
|
end
|
58
67
|
|
59
|
-
#
|
60
|
-
# Passive DNS/SSL, reverse whois search
|
61
|
-
#
|
62
|
-
# @return [Array<String>]
|
63
|
-
#
|
64
|
-
def search
|
65
|
-
case type
|
66
|
-
when "domain", "ip"
|
67
|
-
passive_dns_search
|
68
|
-
when "mail"
|
69
|
-
reverse_whois_search
|
70
|
-
when "hash"
|
71
|
-
ssl_search
|
72
|
-
else
|
73
|
-
raise InvalidInputError, "#{query}(type: #{type || "unknown"}) is not supported." unless valid_type?
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
68
|
#
|
78
69
|
# Passive DNS search
|
79
70
|
#
|
@@ -26,7 +26,16 @@ module Mihari
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def artifacts
|
29
|
-
|
29
|
+
case type
|
30
|
+
when "domain"
|
31
|
+
domain_search
|
32
|
+
when "ip"
|
33
|
+
ip_search
|
34
|
+
when "mail"
|
35
|
+
mail_search
|
36
|
+
else
|
37
|
+
raise InvalidInputError, "#{query}(type: #{type || "unknown"}) is not supported." unless valid_type?
|
38
|
+
end
|
30
39
|
end
|
31
40
|
|
32
41
|
private
|
@@ -48,24 +57,6 @@ module Mihari
|
|
48
57
|
%w[ip domain mail].include? type
|
49
58
|
end
|
50
59
|
|
51
|
-
#
|
52
|
-
# IP/domain/mail search
|
53
|
-
#
|
54
|
-
# @return [Array<String>, Array<Mihari::Artifact>]
|
55
|
-
#
|
56
|
-
def search
|
57
|
-
case type
|
58
|
-
when "domain"
|
59
|
-
domain_search
|
60
|
-
when "ip"
|
61
|
-
ip_search
|
62
|
-
when "mail"
|
63
|
-
mail_search
|
64
|
-
else
|
65
|
-
raise InvalidInputError, "#{query}(type: #{type || "unknown"}) is not supported." unless valid_type?
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
60
|
#
|
70
61
|
# Domain search
|
71
62
|
#
|
@@ -73,17 +73,6 @@ module Mihari
|
|
73
73
|
end
|
74
74
|
responses
|
75
75
|
end
|
76
|
-
|
77
|
-
#
|
78
|
-
# Build an artifact from a Shodan search API response
|
79
|
-
#
|
80
|
-
# @param [Structs::Shodan::Match] match
|
81
|
-
# @param [Array<Structs::Shodan::Match>] matches
|
82
|
-
#
|
83
|
-
# @return [Artifact]
|
84
|
-
#
|
85
|
-
def build_artifact(match, matches)
|
86
|
-
end
|
87
76
|
end
|
88
77
|
end
|
89
78
|
end
|
@@ -27,9 +27,8 @@ module Mihari
|
|
27
27
|
def initialize(*args, **kwargs)
|
28
28
|
super
|
29
29
|
|
30
|
-
unless
|
31
|
-
raise InvalidInputError,
|
32
|
-
"allowed_data_types should be any of url, domain and ip."
|
30
|
+
unless valid_allowed_data_types?
|
31
|
+
raise InvalidInputError, "allowed_data_types should be any of url, domain and ip."
|
33
32
|
end
|
34
33
|
|
35
34
|
@api_key = kwargs[:api_key] || Mihari.config.urlscan_api_key
|
@@ -97,7 +96,7 @@ module Mihari
|
|
97
96
|
#
|
98
97
|
# @return [Boolean]
|
99
98
|
#
|
100
|
-
def
|
99
|
+
def valid_allowed_data_types?
|
101
100
|
allowed_data_types.all? { |type| SUPPORTED_DATA_TYPES.include? type }
|
102
101
|
end
|
103
102
|
end
|
@@ -58,14 +58,11 @@ module Mihari
|
|
58
58
|
responses = []
|
59
59
|
|
60
60
|
loop do
|
61
|
-
response = Structs::VirusTotalIntelligence::Response.from_dynamic!(client.intel_search(query,
|
62
|
-
cursor: cursor))
|
61
|
+
response = Structs::VirusTotalIntelligence::Response.from_dynamic!(client.intel_search(query, cursor: cursor))
|
63
62
|
responses << response
|
64
|
-
|
65
63
|
break if response.meta.cursor.nil?
|
66
64
|
|
67
65
|
cursor = response.meta.cursor
|
68
|
-
|
69
66
|
# sleep #{interval} seconds to avoid the rate limitation (if it is set)
|
70
67
|
sleep interval
|
71
68
|
end
|
data/lib/mihari/clients/misp.rb
CHANGED
data/lib/mihari/http.rb
CHANGED
@@ -4,7 +4,7 @@ require "insensitive_hash"
|
|
4
4
|
|
5
5
|
module Mihari
|
6
6
|
class HTTP
|
7
|
-
# @return [
|
7
|
+
# @return [URI]
|
8
8
|
attr_reader :url
|
9
9
|
|
10
10
|
# @return [Hash]
|
@@ -26,12 +26,12 @@ module Mihari
|
|
26
26
|
new_url = url.deep_dup
|
27
27
|
new_url.query = Addressable::URI.form_encode(params) unless (params || {}).empty?
|
28
28
|
|
29
|
-
get = Net::HTTP::Get.new(new_url)
|
29
|
+
get = Net::HTTP::Get.new(new_url, headers)
|
30
30
|
request get
|
31
31
|
end
|
32
32
|
|
33
33
|
#
|
34
|
-
# Make a POST
|
34
|
+
# Make a POST request
|
35
35
|
#
|
36
36
|
# @param [Hash, nil] params
|
37
37
|
# @param [Hash, nil] json
|
@@ -43,10 +43,17 @@ module Mihari
|
|
43
43
|
new_url = url.deep_dup
|
44
44
|
new_url.query = Addressable::URI.form_encode(params) unless (params || {}).empty?
|
45
45
|
|
46
|
-
post = Net::HTTP::Post.new(new_url)
|
46
|
+
post = Net::HTTP::Post.new(new_url, headers)
|
47
47
|
|
48
|
-
|
49
|
-
|
48
|
+
if json
|
49
|
+
post.body = JSON.generate(json) if json
|
50
|
+
post.content_type = "application/json"
|
51
|
+
end
|
52
|
+
|
53
|
+
if data
|
54
|
+
post.set_form_data(data) if data
|
55
|
+
post.content_type = "application/x-www-form-urlencoded"
|
56
|
+
end
|
50
57
|
|
51
58
|
request post
|
52
59
|
end
|
@@ -65,10 +72,6 @@ module Mihari
|
|
65
72
|
|
66
73
|
private
|
67
74
|
|
68
|
-
def content_type
|
69
|
-
headers["content-type"] || "application/json"
|
70
|
-
end
|
71
|
-
|
72
75
|
#
|
73
76
|
# Get options for HTTP request
|
74
77
|
#
|
@@ -89,16 +92,9 @@ module Mihari
|
|
89
92
|
#
|
90
93
|
def request(req)
|
91
94
|
Net::HTTP.start(url.host, url.port, https_options) do |http|
|
92
|
-
# set headers
|
93
|
-
headers.each do |k, v|
|
94
|
-
req[k] = v
|
95
|
-
end
|
96
|
-
|
97
95
|
res = http.request(req)
|
98
|
-
|
99
96
|
unless res.is_a?(Net::HTTPSuccess)
|
100
|
-
code
|
101
|
-
raise UnsuccessfulStatusCodeError, "Unsuccessful response code returned: #{code}"
|
97
|
+
raise UnsuccessfulStatusCodeError, "Unsuccessful response code returned: #{res.code}"
|
102
98
|
end
|
103
99
|
|
104
100
|
res
|
data/lib/mihari/version.rb
CHANGED
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: 5.1.
|
4
|
+
version: 5.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Manabu Niseki
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-03-
|
11
|
+
date: 2023-03-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -994,7 +994,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
994
994
|
- !ruby/object:Gem::Version
|
995
995
|
version: '0'
|
996
996
|
requirements: []
|
997
|
-
rubygems_version: 3.
|
997
|
+
rubygems_version: 3.4.1
|
998
998
|
signing_key:
|
999
999
|
specification_version: 4
|
1000
1000
|
summary: A framework for continuous OSINT based threat hunting
|