mihari 5.1.0 → 5.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/mihari/analyzers/binaryedge.rb +9 -7
- data/lib/mihari/analyzers/censys.rb +3 -5
- data/lib/mihari/analyzers/circl.rb +4 -6
- data/lib/mihari/analyzers/crtsh.rb +6 -7
- data/lib/mihari/analyzers/dnpedia.rb +3 -7
- data/lib/mihari/analyzers/dnstwister.rb +3 -5
- data/lib/mihari/analyzers/feed.rb +12 -10
- data/lib/mihari/analyzers/greynoise.rb +3 -5
- data/lib/mihari/analyzers/onyphe.rb +3 -4
- data/lib/mihari/analyzers/otx.rb +1 -3
- data/lib/mihari/analyzers/passivetotal.rb +5 -7
- data/lib/mihari/analyzers/pulsedive.rb +5 -7
- data/lib/mihari/analyzers/shodan.rb +3 -9
- data/lib/mihari/analyzers/urlscan.rb +7 -6
- data/lib/mihari/analyzers/virustotal.rb +4 -6
- data/lib/mihari/analyzers/virustotal_intelligence.rb +4 -5
- data/lib/mihari/analyzers/zoomeye.rb +4 -10
- data/lib/mihari/clients/base.rb +53 -0
- data/lib/mihari/clients/binaryedge.rb +33 -0
- data/lib/mihari/clients/censys.rb +42 -0
- data/lib/mihari/clients/circl.rb +59 -0
- data/lib/mihari/clients/crtsh.rb +31 -0
- data/lib/mihari/clients/dnpedia.rb +64 -0
- data/lib/mihari/clients/dnstwister.rb +40 -0
- data/lib/mihari/clients/greynoise.rb +29 -0
- data/lib/mihari/clients/misp.rb +24 -0
- data/lib/mihari/clients/onyphe.rb +23 -0
- data/lib/mihari/clients/otx.rb +29 -0
- data/lib/mihari/clients/passivetotal.rb +65 -0
- data/lib/mihari/clients/publsedive.rb +39 -0
- data/lib/mihari/clients/shodan.rb +30 -0
- data/lib/mihari/clients/the_hive.rb +28 -0
- data/lib/mihari/clients/urlscan.rb +31 -0
- data/lib/mihari/clients/virustotal.rb +56 -0
- data/lib/mihari/clients/zoomeye.rb +68 -0
- data/lib/mihari/emitters/misp.rb +13 -20
- data/lib/mihari/emitters/the_hive.rb +3 -5
- data/lib/mihari/emitters/webhook.rb +2 -2
- data/lib/mihari/feed/reader.rb +14 -11
- data/lib/mihari/http.rb +29 -21
- data/lib/mihari/mixins/retriable.rb +3 -1
- data/lib/mihari/schemas/analyzer.rb +5 -4
- data/lib/mihari/version.rb +1 -1
- data/lib/mihari.rb +21 -0
- data/mihari.gemspec +13 -20
- metadata +51 -244
- data/lib/mihari/analyzers/clients/otx.rb +0 -36
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e19317302956178dc4302543d81a0920018aa384595f91c69dd70110086d575a
|
4
|
+
data.tar.gz: 80d6314c2df13a4a28ec71a0d4b358e74ab0ee9778d818658a997c1fd821f062
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b54bffc456bc114a2a8b52e5acbcc3f30d7571124fc9431fbda209bb57910eabe7950d86c50ef750c41d5df604a5aa08c9affb25d434db8a4f53d85ba8ae4921
|
7
|
+
data.tar.gz: 4bce535d8d6d2573102b0197984854b84628a08ab37855c2a7f7fb1574b701e6b4ca816d3b23b3719d7cde0b7de89753af3b386d43af39e422c7c06b1d65448c
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "binaryedge"
|
4
|
-
|
5
3
|
module Mihari
|
6
4
|
module Analyzers
|
7
5
|
class BinaryEdge < Base
|
@@ -44,8 +42,8 @@ module Mihari
|
|
44
42
|
# @return [Hash]
|
45
43
|
#
|
46
44
|
def search_with_page(query, page: 1)
|
47
|
-
|
48
|
-
rescue
|
45
|
+
client.search(query, page: page)
|
46
|
+
rescue UnsuccessfulStatusCodeError => e
|
49
47
|
raise RetryableError, e if e.message.include?("Request time limit exceeded")
|
50
48
|
|
51
49
|
raise e
|
@@ -58,7 +56,7 @@ module Mihari
|
|
58
56
|
#
|
59
57
|
def search
|
60
58
|
responses = []
|
61
|
-
(1..
|
59
|
+
(1..500).each do |page|
|
62
60
|
res = search_with_page(query, page: page)
|
63
61
|
total = res["total"].to_i
|
64
62
|
|
@@ -75,8 +73,12 @@ module Mihari
|
|
75
73
|
%w[binaryedge_api_key]
|
76
74
|
end
|
77
75
|
|
78
|
-
|
79
|
-
|
76
|
+
#
|
77
|
+
#
|
78
|
+
# @return [Mihari::Clients::BinaryEdge]
|
79
|
+
#
|
80
|
+
def client
|
81
|
+
@client ||= Clients::BinaryEdge.new(api_key: api_key)
|
80
82
|
end
|
81
83
|
end
|
82
84
|
end
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "censysx"
|
4
|
-
|
5
3
|
module Mihari
|
6
4
|
module Analyzers
|
7
5
|
class Censys < Base
|
@@ -42,7 +40,7 @@ module Mihari
|
|
42
40
|
|
43
41
|
cursor = nil
|
44
42
|
loop do
|
45
|
-
response =
|
43
|
+
response = client.search(query, cursor: cursor)
|
46
44
|
response = Structs::Censys::Response.from_dynamic!(response)
|
47
45
|
|
48
46
|
artifacts << response_to_artifacts(response)
|
@@ -106,8 +104,8 @@ module Mihari
|
|
106
104
|
%w[censys_id censys_secret]
|
107
105
|
end
|
108
106
|
|
109
|
-
def
|
110
|
-
@
|
107
|
+
def client
|
108
|
+
@client ||= Clients::Censys.new(id: id, secret: secret)
|
111
109
|
end
|
112
110
|
|
113
111
|
def id?
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "passive_circl"
|
4
|
-
|
5
3
|
module Mihari
|
6
4
|
module Analyzers
|
7
5
|
class CIRCL < Base
|
@@ -42,8 +40,8 @@ module Mihari
|
|
42
40
|
%w[circl_passive_password circl_passive_username]
|
43
41
|
end
|
44
42
|
|
45
|
-
def
|
46
|
-
@
|
43
|
+
def client
|
44
|
+
@client ||= Clients::CIRCL.new(username: username, password: password)
|
47
45
|
end
|
48
46
|
|
49
47
|
#
|
@@ -68,7 +66,7 @@ module Mihari
|
|
68
66
|
# @return [Array<String>]
|
69
67
|
#
|
70
68
|
def passive_dns_search
|
71
|
-
results =
|
69
|
+
results = client.dns_query(@query)
|
72
70
|
results.filter_map do |result|
|
73
71
|
type = result["rrtype"]
|
74
72
|
(type == "A") ? result["rdata"] : nil
|
@@ -81,7 +79,7 @@ module Mihari
|
|
81
79
|
# @return [Array<String>]
|
82
80
|
#
|
83
81
|
def passive_ssl_search
|
84
|
-
result =
|
82
|
+
result = client.ssl_cquery(@query)
|
85
83
|
seen = result["seen"] || []
|
86
84
|
seen.uniq
|
87
85
|
end
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "crtsh"
|
4
|
-
|
5
3
|
module Mihari
|
6
4
|
module Analyzers
|
7
5
|
class Crtsh < Base
|
@@ -21,8 +19,11 @@ module Mihari
|
|
21
19
|
|
22
20
|
private
|
23
21
|
|
24
|
-
|
25
|
-
|
22
|
+
#
|
23
|
+
# @return [Mihari::Clients::Crtsh]
|
24
|
+
#
|
25
|
+
def client
|
26
|
+
@client ||= Mihari::Clients::Crtsh.new
|
26
27
|
end
|
27
28
|
|
28
29
|
#
|
@@ -32,9 +33,7 @@ module Mihari
|
|
32
33
|
#
|
33
34
|
def search
|
34
35
|
exclude = exclude_expired ? "expired" : nil
|
35
|
-
|
36
|
-
rescue ::Crtsh::Error => _e
|
37
|
-
[]
|
36
|
+
client.search(query, exclude: exclude)
|
38
37
|
end
|
39
38
|
end
|
40
39
|
end
|
@@ -1,22 +1,18 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "dnpedia"
|
4
|
-
|
5
3
|
module Mihari
|
6
4
|
module Analyzers
|
7
5
|
class DNPedia < Base
|
8
6
|
param :query
|
9
7
|
|
10
|
-
option :tags, default: proc { [] }
|
11
|
-
|
12
8
|
def artifacts
|
13
9
|
search || []
|
14
10
|
end
|
15
11
|
|
16
12
|
private
|
17
13
|
|
18
|
-
def
|
19
|
-
@
|
14
|
+
def client
|
15
|
+
@client ||= Clients::DNPedia.new
|
20
16
|
end
|
21
17
|
|
22
18
|
#
|
@@ -25,7 +21,7 @@ module Mihari
|
|
25
21
|
# @return [Array<Mihari::Artifact>]
|
26
22
|
#
|
27
23
|
def search
|
28
|
-
res =
|
24
|
+
res = client.search(query)
|
29
25
|
rows = res["rows"] || []
|
30
26
|
rows.map do |row|
|
31
27
|
data = [row["name"], row["zoneid"]].join(".")
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "dnstwister"
|
4
|
-
|
5
3
|
module Mihari
|
6
4
|
module Analyzers
|
7
5
|
class DNSTwister < Base
|
@@ -35,8 +33,8 @@ module Mihari
|
|
35
33
|
type == "domain"
|
36
34
|
end
|
37
35
|
|
38
|
-
def
|
39
|
-
@
|
36
|
+
def client
|
37
|
+
@client ||= Clients::DNSTwister.new
|
40
38
|
end
|
41
39
|
|
42
40
|
#
|
@@ -61,7 +59,7 @@ module Mihari
|
|
61
59
|
def search
|
62
60
|
raise InvalidInputError, "#{query}(type: #{type || "unknown"}) is not supported." unless valid_type?
|
63
61
|
|
64
|
-
res =
|
62
|
+
res = client.fuzz(query)
|
65
63
|
fuzzy_domains = res["fuzzy_domains"] || []
|
66
64
|
domains = fuzzy_domains.map { |domain| domain["domain"] }
|
67
65
|
Parallel.map(domains) do |domain|
|
@@ -8,26 +8,28 @@ module Mihari
|
|
8
8
|
class Feed < Base
|
9
9
|
param :query
|
10
10
|
|
11
|
-
option :
|
12
|
-
option :
|
13
|
-
option :
|
14
|
-
option :
|
11
|
+
option :method, default: proc { "GET" }
|
12
|
+
option :headers, default: proc { {} }
|
13
|
+
option :params, default: proc {}
|
14
|
+
option :json, default: proc {}
|
15
|
+
option :data, default: proc {}
|
15
16
|
|
16
17
|
option :selector, default: proc { "" }
|
17
18
|
|
18
19
|
def artifacts
|
19
|
-
Mihari::Feed::Parser.new(
|
20
|
+
Mihari::Feed::Parser.new(results).parse selector
|
20
21
|
end
|
21
22
|
|
22
23
|
private
|
23
24
|
|
24
|
-
def
|
25
|
+
def results
|
25
26
|
reader = Mihari::Feed::Reader.new(
|
26
27
|
query,
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
28
|
+
method: method,
|
29
|
+
headers: headers,
|
30
|
+
params: params,
|
31
|
+
json: json,
|
32
|
+
data: data
|
31
33
|
)
|
32
34
|
reader.read
|
33
35
|
end
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "greynoise"
|
4
|
-
|
5
3
|
module Mihari
|
6
4
|
module Analyzers
|
7
5
|
class GreyNoise < Base
|
@@ -31,8 +29,8 @@ module Mihari
|
|
31
29
|
%w[greynoise_api_key]
|
32
30
|
end
|
33
31
|
|
34
|
-
def
|
35
|
-
@
|
32
|
+
def client
|
33
|
+
@client ||= Clients::GreyNoise.new(api_key: api_key)
|
36
34
|
end
|
37
35
|
|
38
36
|
#
|
@@ -41,7 +39,7 @@ module Mihari
|
|
41
39
|
# @return [Hash]
|
42
40
|
#
|
43
41
|
def search
|
44
|
-
|
42
|
+
client.gnql_search(query, size: PAGE_SIZE)
|
45
43
|
end
|
46
44
|
|
47
45
|
#
|
@@ -1,6 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "onyphe"
|
4
3
|
require "normalize_country"
|
5
4
|
|
6
5
|
module Mihari
|
@@ -37,8 +36,8 @@ module Mihari
|
|
37
36
|
%w[onyphe_api_key]
|
38
37
|
end
|
39
38
|
|
40
|
-
def
|
41
|
-
@
|
39
|
+
def client
|
40
|
+
@client ||= Clients::Onyphe.new(api_key: api_key)
|
42
41
|
end
|
43
42
|
|
44
43
|
#
|
@@ -50,7 +49,7 @@ module Mihari
|
|
50
49
|
# @return [Structs::Onyphe::Response]
|
51
50
|
#
|
52
51
|
def search_with_page(query, page: 1)
|
53
|
-
res =
|
52
|
+
res = client.datascan(query, page: page)
|
54
53
|
Structs::Onyphe::Response.from_dynamic!(res)
|
55
54
|
end
|
56
55
|
|
data/lib/mihari/analyzers/otx.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "mihari/analyzers/clients/otx"
|
4
|
-
|
5
3
|
module Mihari
|
6
4
|
module Analyzers
|
7
5
|
class OTX < Base
|
@@ -35,7 +33,7 @@ module Mihari
|
|
35
33
|
end
|
36
34
|
|
37
35
|
def client
|
38
|
-
@client ||= Mihari::
|
36
|
+
@client ||= Mihari::Clients::OTX.new(api_key: api_key)
|
39
37
|
end
|
40
38
|
|
41
39
|
#
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "passivetotal"
|
4
|
-
|
5
3
|
module Mihari
|
6
4
|
module Analyzers
|
7
5
|
class PassiveTotal < Base
|
@@ -42,8 +40,8 @@ module Mihari
|
|
42
40
|
%w[passivetotal_username passivetotal_api_key]
|
43
41
|
end
|
44
42
|
|
45
|
-
def
|
46
|
-
@
|
43
|
+
def client
|
44
|
+
@client ||= Clients::PassiveTotal.new(username: username, api_key: api_key)
|
47
45
|
end
|
48
46
|
|
49
47
|
#
|
@@ -79,7 +77,7 @@ module Mihari
|
|
79
77
|
# @return [Array<String>]
|
80
78
|
#
|
81
79
|
def passive_dns_search
|
82
|
-
res =
|
80
|
+
res = client.passive_dns_search(query)
|
83
81
|
res["results"] || []
|
84
82
|
end
|
85
83
|
|
@@ -89,7 +87,7 @@ module Mihari
|
|
89
87
|
# @return [Array<Mihari::Artifact>]
|
90
88
|
#
|
91
89
|
def reverse_whois_search
|
92
|
-
res =
|
90
|
+
res = client.reverse_whois_search(query: query, field: "email")
|
93
91
|
results = res["results"] || []
|
94
92
|
results.map do |result|
|
95
93
|
data = result["domain"]
|
@@ -103,7 +101,7 @@ module Mihari
|
|
103
101
|
# @return [Array<Mihari::Artifact>]
|
104
102
|
#
|
105
103
|
def ssl_search
|
106
|
-
res =
|
104
|
+
res = client.ssl_search(query)
|
107
105
|
results = res["results"] || []
|
108
106
|
results.map do |result|
|
109
107
|
data = result["ipAddresses"]
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "pulsedive"
|
4
|
-
|
5
3
|
module Mihari
|
6
4
|
module Analyzers
|
7
5
|
class Pulsedive < Base
|
@@ -34,8 +32,8 @@ module Mihari
|
|
34
32
|
%w[pulsedive_api_key]
|
35
33
|
end
|
36
34
|
|
37
|
-
def
|
38
|
-
@
|
35
|
+
def client
|
36
|
+
@client ||= Clients::PulseDive.new(api_key: api_key)
|
39
37
|
end
|
40
38
|
|
41
39
|
#
|
@@ -55,12 +53,12 @@ module Mihari
|
|
55
53
|
def search
|
56
54
|
raise InvalidInputError, "#{query}(type: #{type || "unknown"}) is not supported." unless valid_type?
|
57
55
|
|
58
|
-
indicator =
|
56
|
+
indicator = client.get_indicator(query)
|
59
57
|
iid = indicator["iid"]
|
60
58
|
|
61
|
-
properties =
|
59
|
+
properties = client.get_properties(iid)
|
62
60
|
(properties["dns"] || []).filter_map do |property|
|
63
|
-
if [
|
61
|
+
if %w[A PTR].include?(property["name"])
|
64
62
|
nil
|
65
63
|
else
|
66
64
|
data = property["value"]
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "shodan"
|
4
|
-
|
5
3
|
module Mihari
|
6
4
|
module Analyzers
|
7
5
|
class Shodan < Base
|
@@ -37,8 +35,8 @@ module Mihari
|
|
37
35
|
%w[shodan_api_key]
|
38
36
|
end
|
39
37
|
|
40
|
-
def
|
41
|
-
@
|
38
|
+
def client
|
39
|
+
@client ||= Clients::Shodan.new(api_key: api_key)
|
42
40
|
end
|
43
41
|
|
44
42
|
#
|
@@ -50,11 +48,7 @@ module Mihari
|
|
50
48
|
# @return [Hash]
|
51
49
|
#
|
52
50
|
def search_with_page(query, page: 1)
|
53
|
-
|
54
|
-
rescue ::Shodan::Error => e
|
55
|
-
raise RetryableError, e if e.message.include?("request timed out")
|
56
|
-
|
57
|
-
raise e
|
51
|
+
client.search(query, page: page)
|
58
52
|
end
|
59
53
|
|
60
54
|
#
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "urlscan"
|
4
|
-
|
5
3
|
module Mihari
|
6
4
|
module Analyzers
|
7
5
|
class Urlscan < Base
|
@@ -20,7 +18,10 @@ module Mihari
|
|
20
18
|
def initialize(*args, **kwargs)
|
21
19
|
super
|
22
20
|
|
23
|
-
|
21
|
+
unless valid_alllowed_data_types?
|
22
|
+
raise InvalidInputError,
|
23
|
+
"allowed_data_types should be any of url, domain and ip."
|
24
|
+
end
|
24
25
|
|
25
26
|
@api_key = kwargs[:api_key] || Mihari.config.urlscan_api_key
|
26
27
|
end
|
@@ -44,8 +45,8 @@ module Mihari
|
|
44
45
|
%w[urlscan_api_key]
|
45
46
|
end
|
46
47
|
|
47
|
-
def
|
48
|
-
@
|
48
|
+
def client
|
49
|
+
@client ||= Clients::UrlScan.new(api_key: api_key)
|
49
50
|
end
|
50
51
|
|
51
52
|
#
|
@@ -54,7 +55,7 @@ module Mihari
|
|
54
55
|
# @return [Structs::Urlscan::Response]
|
55
56
|
#
|
56
57
|
def search_with_search_after(search_after: nil)
|
57
|
-
res =
|
58
|
+
res = client.search(query, size: SIZE, search_after: search_after)
|
58
59
|
Structs::Urlscan::Response.from_dynamic! res
|
59
60
|
end
|
60
61
|
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "virustotal"
|
4
|
-
|
5
3
|
module Mihari
|
6
4
|
module Analyzers
|
7
5
|
class VirusTotal < Base
|
@@ -33,8 +31,8 @@ module Mihari
|
|
33
31
|
%w[virustotal_api_key]
|
34
32
|
end
|
35
33
|
|
36
|
-
def
|
37
|
-
@
|
34
|
+
def client
|
35
|
+
@client = Clients::VirusTotal.new(api_key: api_key)
|
38
36
|
end
|
39
37
|
|
40
38
|
#
|
@@ -68,7 +66,7 @@ module Mihari
|
|
68
66
|
# @return [Array<Mihari::Artifact>]
|
69
67
|
#
|
70
68
|
def domain_search
|
71
|
-
res =
|
69
|
+
res = client.domain_search(query)
|
72
70
|
|
73
71
|
data = res["data"] || []
|
74
72
|
data.filter_map do |item|
|
@@ -83,7 +81,7 @@ module Mihari
|
|
83
81
|
# @return [Array<Mihari::Artifact>]
|
84
82
|
#
|
85
83
|
def ip_search
|
86
|
-
res =
|
84
|
+
res = client.ip_search(query)
|
87
85
|
|
88
86
|
data = res["data"] || []
|
89
87
|
data.filter_map do |item|
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "virustotal"
|
4
|
-
|
5
3
|
module Mihari
|
6
4
|
module Analyzers
|
7
5
|
class VirusTotalIntelligence < Base
|
@@ -40,8 +38,8 @@ module Mihari
|
|
40
38
|
#
|
41
39
|
# @return [::VirusTotal::API]
|
42
40
|
#
|
43
|
-
def
|
44
|
-
@
|
41
|
+
def client
|
42
|
+
@client = Clients::VirusTotal.new(api_key: api_key)
|
45
43
|
end
|
46
44
|
|
47
45
|
#
|
@@ -54,7 +52,8 @@ module Mihari
|
|
54
52
|
responses = []
|
55
53
|
|
56
54
|
loop do
|
57
|
-
response = Structs::VirusTotalIntelligence::Response.from_dynamic!(
|
55
|
+
response = Structs::VirusTotalIntelligence::Response.from_dynamic!(client.intel_search(query,
|
56
|
+
cursor: cursor))
|
58
57
|
responses << response
|
59
58
|
|
60
59
|
break if response.meta.cursor.nil?
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "zoomeye"
|
4
|
-
|
5
3
|
module Mihari
|
6
4
|
module Analyzers
|
7
5
|
class ZoomEye < Base
|
@@ -48,8 +46,8 @@ module Mihari
|
|
48
46
|
%w[zoomeye_api_key]
|
49
47
|
end
|
50
48
|
|
51
|
-
def
|
52
|
-
@
|
49
|
+
def client
|
50
|
+
@client ||= Clients::ZoomEye.new(api_key: api_key)
|
53
51
|
end
|
54
52
|
|
55
53
|
#
|
@@ -83,9 +81,7 @@ module Mihari
|
|
83
81
|
# @return [Hash, nil]
|
84
82
|
#
|
85
83
|
def _host_search(query, page: 1)
|
86
|
-
|
87
|
-
rescue ::ZoomEye::Error => _e
|
88
|
-
nil
|
84
|
+
client.host_search(query, page: page)
|
89
85
|
end
|
90
86
|
|
91
87
|
#
|
@@ -118,9 +114,7 @@ module Mihari
|
|
118
114
|
# @return [Hash, nil]
|
119
115
|
#
|
120
116
|
def _web_search(query, page: 1)
|
121
|
-
|
122
|
-
rescue ::ZoomEye::Error => _e
|
123
|
-
nil
|
117
|
+
client.web_search(query, page: page)
|
124
118
|
end
|
125
119
|
|
126
120
|
#
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mihari
|
4
|
+
module Clients
|
5
|
+
class Base
|
6
|
+
# @return [String]
|
7
|
+
attr_reader :base_url
|
8
|
+
|
9
|
+
# @return [Hash]
|
10
|
+
attr_reader :headers
|
11
|
+
|
12
|
+
#
|
13
|
+
# @param [String] base_url
|
14
|
+
# @param [Hash] headers
|
15
|
+
#
|
16
|
+
def initialize(base_url, headers: {})
|
17
|
+
@base_url = base_url
|
18
|
+
@headers = headers || {}
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
#
|
24
|
+
# @param [String] path
|
25
|
+
#
|
26
|
+
# @return [String]
|
27
|
+
#
|
28
|
+
def url_for(path)
|
29
|
+
base_url + path
|
30
|
+
end
|
31
|
+
|
32
|
+
#
|
33
|
+
# @param [String] path
|
34
|
+
# @param [Hashk, nil] params
|
35
|
+
#
|
36
|
+
# @return [String] <description>
|
37
|
+
#
|
38
|
+
def get(path, params: nil)
|
39
|
+
HTTP.get(url_for(path), headers: headers, params: params)
|
40
|
+
end
|
41
|
+
|
42
|
+
#
|
43
|
+
# @param [String] path
|
44
|
+
# @param [Hash, nil] json
|
45
|
+
#
|
46
|
+
# @return [String] <description>
|
47
|
+
#
|
48
|
+
def post(path, json: {})
|
49
|
+
HTTP.post(url_for(path), headers: headers, json: json)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mihari
|
4
|
+
module Clients
|
5
|
+
class BinaryEdge < Base
|
6
|
+
def initialize(base_url = "https://api.binaryedge.io/v2", api_key:, headers: {})
|
7
|
+
raise(ArgumentError, "'api_key' argument is required") unless api_key
|
8
|
+
|
9
|
+
headers["x-key"] = api_key
|
10
|
+
|
11
|
+
super(base_url, headers: headers)
|
12
|
+
end
|
13
|
+
|
14
|
+
#
|
15
|
+
# @param [String] query String used to query our data
|
16
|
+
# @param [Integer] page Default 1, Maximum: 500
|
17
|
+
# @param [Integer, nil] only_ips If selected, only output IP addresses, ports and protocols.
|
18
|
+
#
|
19
|
+
# @return [Hash]
|
20
|
+
#
|
21
|
+
def search(query, page: 1, only_ips: nil)
|
22
|
+
params = {
|
23
|
+
query: query,
|
24
|
+
page: page,
|
25
|
+
only_ips: only_ips
|
26
|
+
}.compact
|
27
|
+
|
28
|
+
res = get("/query/search", params: params)
|
29
|
+
JSON.parse(res.body.to_s)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|