mihari 5.2.4 → 5.3.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/.gitignore +4 -1
- data/README.md +0 -10
- data/Rakefile +7 -1
- data/build_frontend.sh +1 -1
- data/frontend/.eslintrc.cjs +22 -0
- data/frontend/.gitignore +18 -12
- data/frontend/.prettierrc.json +8 -0
- data/frontend/env.d.ts +5 -0
- data/frontend/package-lock.json +5095 -9661
- data/frontend/package.json +34 -24
- data/frontend/src/App.vue +5 -5
- data/frontend/src/api-helper.ts +38 -40
- data/frontend/src/api.ts +40 -40
- data/frontend/src/components/ErrorMessage.vue +8 -8
- data/frontend/src/components/Loading.vue +3 -3
- data/frontend/src/components/Navbar.vue +10 -27
- data/frontend/src/components/Pagination.vue +35 -42
- data/frontend/src/components/alert/Alert.vue +21 -26
- data/frontend/src/components/alert/Alerts.vue +23 -25
- data/frontend/src/components/alert/AlertsWithPagination.vue +34 -34
- data/frontend/src/components/alert/AlertsWrapper.vue +42 -49
- data/frontend/src/components/alert/Form.vue +39 -40
- data/frontend/src/components/artifact/AS.vue +7 -7
- data/frontend/src/components/artifact/Artifact.vue +66 -83
- data/frontend/src/components/artifact/ArtifactTag.vue +21 -27
- data/frontend/src/components/artifact/ArtifactTags.vue +8 -8
- data/frontend/src/components/artifact/ArtifactWrapper.vue +22 -25
- data/frontend/src/components/artifact/CPEs.vue +6 -6
- data/frontend/src/components/artifact/DnsRecords.vue +9 -9
- data/frontend/src/components/artifact/Ports.vue +6 -6
- data/frontend/src/components/artifact/ReverseDnsNames.vue +7 -7
- data/frontend/src/components/artifact/Tags.vue +6 -6
- data/frontend/src/components/artifact/WhoisRecord.vue +7 -9
- data/frontend/src/components/config/Configs.vue +7 -10
- data/frontend/src/components/config/ConfigsWrapper.vue +14 -20
- data/frontend/src/components/link/Link.vue +7 -7
- data/frontend/src/components/link/Links.vue +16 -21
- data/frontend/src/components/rule/EditRule.vue +22 -22
- data/frontend/src/components/rule/EditRuleWrapper.vue +22 -28
- data/frontend/src/components/rule/Form.vue +28 -28
- data/frontend/src/components/rule/InputForm.vue +31 -25
- data/frontend/src/components/rule/NewRule.vue +18 -18
- data/frontend/src/components/rule/Rule.vue +25 -27
- data/frontend/src/components/rule/RuleWrapper.vue +24 -31
- data/frontend/src/components/rule/Rules.vue +26 -30
- data/frontend/src/components/rule/RulesWrapper.vue +39 -42
- data/frontend/src/components/rule/YAML.vue +19 -22
- data/frontend/src/components/tag/Tag.vue +24 -32
- data/frontend/src/components/tag/Tags.vue +11 -11
- data/frontend/src/countries.ts +23 -23
- data/frontend/src/index.ts +9 -12
- data/frontend/src/links/anyrun.ts +10 -10
- data/frontend/src/links/base.ts +3 -3
- data/frontend/src/links/censys.ts +10 -10
- data/frontend/src/links/crtsh.ts +10 -10
- data/frontend/src/links/dnslytics.ts +18 -18
- data/frontend/src/links/greynoise.ts +10 -10
- data/frontend/src/links/index.ts +15 -15
- data/frontend/src/links/intezer.ts +10 -10
- data/frontend/src/links/otx.ts +14 -14
- data/frontend/src/links/securitytrails.ts +15 -15
- data/frontend/src/links/shodan.ts +10 -10
- data/frontend/src/links/urlscan.ts +19 -19
- data/frontend/src/links/virustotal.ts +27 -27
- data/frontend/src/main.ts +8 -8
- data/frontend/src/router/index.ts +20 -20
- data/frontend/src/rule.ts +6 -6
- data/frontend/src/shims-vue.d.ts +2 -2
- data/frontend/src/types.ts +91 -91
- data/frontend/src/utils.ts +23 -29
- data/frontend/src/views/Alerts.vue +7 -7
- data/frontend/src/views/Artifact.vue +17 -17
- data/frontend/src/views/Configs.vue +7 -7
- data/frontend/src/views/EditRule.vue +17 -17
- data/frontend/src/views/NewRule.vue +10 -10
- data/frontend/src/views/Rule.vue +17 -17
- data/frontend/src/views/Rules.vue +7 -7
- data/frontend/tests/utils.spec.ts +9 -0
- data/frontend/tsconfig.app.json +21 -0
- data/frontend/tsconfig.json +10 -36
- data/frontend/tsconfig.node.json +13 -0
- data/frontend/tsconfig.vitest.json +12 -0
- data/frontend/vite.config.ts +24 -0
- data/frontend/vitest.config.ts +21 -0
- data/lefthook.yml +4 -2
- data/lib/mihari/analyzers/base.rb +48 -14
- data/lib/mihari/analyzers/binaryedge.rb +10 -15
- data/lib/mihari/analyzers/censys.rb +12 -15
- data/lib/mihari/analyzers/circl.rb +10 -10
- data/lib/mihari/analyzers/crtsh.rb +10 -6
- data/lib/mihari/analyzers/dnstwister.rb +6 -8
- data/lib/mihari/analyzers/feed.rb +21 -10
- data/lib/mihari/analyzers/greynoise.rb +10 -20
- data/lib/mihari/analyzers/onyphe.rb +9 -14
- data/lib/mihari/analyzers/otx.rb +8 -9
- data/lib/mihari/analyzers/passivetotal.rb +10 -10
- data/lib/mihari/analyzers/pulsedive.rb +21 -31
- data/lib/mihari/analyzers/securitytrails.rb +8 -6
- data/lib/mihari/analyzers/shodan.rb +8 -13
- data/lib/mihari/analyzers/urlscan.rb +15 -20
- data/lib/mihari/analyzers/virustotal.rb +16 -26
- data/lib/mihari/analyzers/virustotal_intelligence.rb +11 -17
- data/lib/mihari/analyzers/zoomeye.rb +12 -17
- data/lib/mihari/config.rb +133 -0
- data/lib/mihari/constants.rb +3 -0
- data/lib/mihari/emitters/slack.rb +13 -3
- data/lib/mihari/errors.rb +1 -1
- data/lib/mihari/http.rb +2 -3
- data/lib/mihari/schemas/analyzer.rb +2 -0
- data/lib/mihari/type_checker.rb +6 -6
- data/lib/mihari/version.rb +1 -1
- data/lib/mihari/web/endpoints/configs.rb +5 -1
- data/lib/mihari/web/public/assets/{index-eed1bcd8.css → index-2ba8f0a6.css} +1 -1
- data/lib/mihari/web/public/assets/{index-ac4e5ffa.js → index-71285b15.js} +16 -16
- data/lib/mihari/web/public/index.html +2 -2
- data/lib/mihari/web/public/redoc-static.html +388 -2193
- data/lib/mihari.rb +9 -59
- data/mihari.gemspec +8 -8
- metadata +24 -62
- data/frontend/.browserslistrc +0 -3
- data/frontend/.eslintrc.js +0 -33
- data/frontend/babel.config.js +0 -3
- data/frontend/jest.config.js +0 -9
- data/frontend/tests/unit/utils.spec.ts +0 -7
- data/frontend/vite.config.js +0 -24
|
@@ -5,8 +5,6 @@ module Mihari
|
|
|
5
5
|
class CIRCL < Base
|
|
6
6
|
include Mixins::Refang
|
|
7
7
|
|
|
8
|
-
param :query
|
|
9
|
-
|
|
10
8
|
# @return [String, nil]
|
|
11
9
|
attr_reader :type
|
|
12
10
|
|
|
@@ -16,17 +14,19 @@ module Mihari
|
|
|
16
14
|
# @return [String, nil]
|
|
17
15
|
attr_reader :password
|
|
18
16
|
|
|
19
|
-
#
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
17
|
+
#
|
|
18
|
+
# @param [String] query
|
|
19
|
+
# @param [Hash, nil] options
|
|
20
|
+
# @param [String, nil] username
|
|
21
|
+
# @param [String, nil] password
|
|
22
|
+
#
|
|
23
|
+
def initialize(query, options: nil, username: nil, password: nil)
|
|
24
|
+
super(refang(query), options: options)
|
|
24
25
|
|
|
25
|
-
@query = refang(query)
|
|
26
26
|
@type = TypeChecker.type(query)
|
|
27
27
|
|
|
28
|
-
@username =
|
|
29
|
-
@password =
|
|
28
|
+
@username = username || Mihari.config.circl_passive_username
|
|
29
|
+
@password = password || Mihari.config.circl_passive_password
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
def artifacts
|
|
@@ -3,15 +3,19 @@
|
|
|
3
3
|
module Mihari
|
|
4
4
|
module Analyzers
|
|
5
5
|
class Crtsh < Base
|
|
6
|
-
param :query
|
|
7
|
-
|
|
8
|
-
option :exclude_expired, default: proc { true }
|
|
9
|
-
|
|
10
6
|
# @return [Boolean]
|
|
11
7
|
attr_reader :exclude_expired
|
|
12
8
|
|
|
13
|
-
#
|
|
14
|
-
|
|
9
|
+
#
|
|
10
|
+
# @param [String] query
|
|
11
|
+
# @param [Hash, nil] options
|
|
12
|
+
# @param [Bool] exclude_expired
|
|
13
|
+
#
|
|
14
|
+
def initialize(query, options: nil, exclude_expired: true)
|
|
15
|
+
super(query, options: options)
|
|
16
|
+
|
|
17
|
+
@exclude_expired = exclude_expired
|
|
18
|
+
end
|
|
15
19
|
|
|
16
20
|
def artifacts
|
|
17
21
|
results = search
|
|
@@ -5,18 +5,16 @@ module Mihari
|
|
|
5
5
|
class DNSTwister < Base
|
|
6
6
|
include Mixins::Refang
|
|
7
7
|
|
|
8
|
-
param :query
|
|
9
|
-
|
|
10
8
|
# @return [String]
|
|
11
9
|
attr_reader :type
|
|
12
10
|
|
|
13
|
-
#
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
11
|
+
#
|
|
12
|
+
# @param [String] query
|
|
13
|
+
# @param [Hash, nil] options
|
|
14
|
+
#
|
|
15
|
+
def initialize(query, options: nil)
|
|
16
|
+
super(refang(query), options: options)
|
|
18
17
|
|
|
19
|
-
@query = refang(query)
|
|
20
18
|
@type = TypeChecker.type(query)
|
|
21
19
|
end
|
|
22
20
|
|
|
@@ -6,16 +6,6 @@ require "mihari/feed/parser"
|
|
|
6
6
|
module Mihari
|
|
7
7
|
module Analyzers
|
|
8
8
|
class Feed < Base
|
|
9
|
-
param :query
|
|
10
|
-
|
|
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 {}
|
|
16
|
-
|
|
17
|
-
option :selector, default: proc { "" }
|
|
18
|
-
|
|
19
9
|
# @return [Hash, nil]
|
|
20
10
|
attr_reader :data
|
|
21
11
|
|
|
@@ -37,6 +27,27 @@ module Mihari
|
|
|
37
27
|
# @return [String]
|
|
38
28
|
attr_reader :query
|
|
39
29
|
|
|
30
|
+
#
|
|
31
|
+
# @param [String] query
|
|
32
|
+
# @param [Hash, nil] options
|
|
33
|
+
# @param [String] method
|
|
34
|
+
# @param [Hash] headers
|
|
35
|
+
# @param [Hash] params
|
|
36
|
+
# @param [Hash] json
|
|
37
|
+
# @param [Hash] data
|
|
38
|
+
# @param [String] selector
|
|
39
|
+
#
|
|
40
|
+
def initialize(query, options: nil, method: "GET", headers: {}, params: {}, json: {}, data: {}, selector: "")
|
|
41
|
+
super(query, options: options)
|
|
42
|
+
|
|
43
|
+
@method = method
|
|
44
|
+
@headers = headers
|
|
45
|
+
@params = params
|
|
46
|
+
@json = json
|
|
47
|
+
@data = data
|
|
48
|
+
@selector = selector
|
|
49
|
+
end
|
|
50
|
+
|
|
40
51
|
def artifacts
|
|
41
52
|
Mihari::Feed::Parser.new(results).parse selector
|
|
42
53
|
end
|
|
@@ -3,29 +3,28 @@
|
|
|
3
3
|
module Mihari
|
|
4
4
|
module Analyzers
|
|
5
5
|
class GreyNoise < Base
|
|
6
|
-
|
|
6
|
+
PAGE_SIZE = 10_000
|
|
7
7
|
|
|
8
8
|
# @return [String, nil]
|
|
9
9
|
attr_reader :api_key
|
|
10
10
|
|
|
11
|
-
#
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
#
|
|
12
|
+
# @param [String] query
|
|
13
|
+
# @param [Hash, nil] options
|
|
14
|
+
# @param [String, nil] api_key
|
|
15
|
+
#
|
|
16
|
+
def initialize(query, options: nil, api_key: nil)
|
|
17
|
+
super(query, options: options)
|
|
16
18
|
|
|
17
|
-
@api_key =
|
|
19
|
+
@api_key = api_key || Mihari.config.greynoise_api_key
|
|
18
20
|
end
|
|
19
21
|
|
|
20
22
|
def artifacts
|
|
21
|
-
|
|
22
|
-
res.to_artifacts
|
|
23
|
+
client.gnql_search(query, size: PAGE_SIZE).to_artifacts
|
|
23
24
|
end
|
|
24
25
|
|
|
25
26
|
private
|
|
26
27
|
|
|
27
|
-
PAGE_SIZE = 10_000
|
|
28
|
-
|
|
29
28
|
def configuration_keys
|
|
30
29
|
%w[greynoise_api_key]
|
|
31
30
|
end
|
|
@@ -33,15 +32,6 @@ module Mihari
|
|
|
33
32
|
def client
|
|
34
33
|
@client ||= Clients::GreyNoise.new(api_key: api_key)
|
|
35
34
|
end
|
|
36
|
-
|
|
37
|
-
#
|
|
38
|
-
# Search
|
|
39
|
-
#
|
|
40
|
-
# @return [Hash]
|
|
41
|
-
#
|
|
42
|
-
def search
|
|
43
|
-
client.gnql_search(query, size: PAGE_SIZE)
|
|
44
|
-
end
|
|
45
35
|
end
|
|
46
36
|
end
|
|
47
37
|
end
|
|
@@ -5,23 +5,18 @@ require "normalize_country"
|
|
|
5
5
|
module Mihari
|
|
6
6
|
module Analyzers
|
|
7
7
|
class Onyphe < Base
|
|
8
|
-
param :query
|
|
9
|
-
|
|
10
|
-
option :interval, default: proc { 0 }
|
|
11
|
-
|
|
12
8
|
# @return [String, nil]
|
|
13
9
|
attr_reader :api_key
|
|
14
10
|
|
|
15
|
-
#
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
# @
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
super(*args, **kwargs)
|
|
11
|
+
#
|
|
12
|
+
# @param [String] query
|
|
13
|
+
# @param [Hash, nil] options
|
|
14
|
+
# @param [String, nil] api_key
|
|
15
|
+
#
|
|
16
|
+
def initialize(query, options: nil, api_key: nil)
|
|
17
|
+
super(query, options: options)
|
|
23
18
|
|
|
24
|
-
@api_key =
|
|
19
|
+
@api_key = api_key || Mihari.config.onyphe_api_key
|
|
25
20
|
end
|
|
26
21
|
|
|
27
22
|
def artifacts
|
|
@@ -70,7 +65,7 @@ module Mihari
|
|
|
70
65
|
break if total <= page * PAGE_SIZE
|
|
71
66
|
|
|
72
67
|
# sleep #{interval} seconds to avoid the rate limitation (if it is set)
|
|
73
|
-
sleep interval
|
|
68
|
+
sleep(interval) if interval
|
|
74
69
|
end
|
|
75
70
|
responses
|
|
76
71
|
end
|
data/lib/mihari/analyzers/otx.rb
CHANGED
|
@@ -5,24 +5,23 @@ module Mihari
|
|
|
5
5
|
class OTX < Base
|
|
6
6
|
include Mixins::Refang
|
|
7
7
|
|
|
8
|
-
param :query
|
|
9
|
-
|
|
10
8
|
# @return [String, nil]
|
|
11
9
|
attr_reader :type
|
|
12
10
|
|
|
13
11
|
# @return [String, nil]
|
|
14
12
|
attr_reader :api_key
|
|
15
13
|
|
|
16
|
-
#
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
14
|
+
#
|
|
15
|
+
# @param [String] query
|
|
16
|
+
# @param [Hash, nil] options
|
|
17
|
+
# @param [String, nil] api_key
|
|
18
|
+
#
|
|
19
|
+
def initialize(query, options: nil, api_key: nil)
|
|
20
|
+
super(refang(query), options: options)
|
|
21
21
|
|
|
22
|
-
@query = refang(query)
|
|
23
22
|
@type = TypeChecker.type(query)
|
|
24
23
|
|
|
25
|
-
@api_key =
|
|
24
|
+
@api_key = api_key || Mihari.config.otx_api_key
|
|
26
25
|
end
|
|
27
26
|
|
|
28
27
|
def artifacts
|
|
@@ -5,8 +5,6 @@ module Mihari
|
|
|
5
5
|
class PassiveTotal < Base
|
|
6
6
|
include Mixins::Refang
|
|
7
7
|
|
|
8
|
-
param :query
|
|
9
|
-
|
|
10
8
|
# @return [String, nil]
|
|
11
9
|
attr_reader :type
|
|
12
10
|
|
|
@@ -16,17 +14,19 @@ module Mihari
|
|
|
16
14
|
# @return [String, nil]
|
|
17
15
|
attr_reader :api_key
|
|
18
16
|
|
|
19
|
-
#
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
17
|
+
#
|
|
18
|
+
# @param [String] query
|
|
19
|
+
# @param [Hash, nil] options
|
|
20
|
+
# @param [String, nil] api_key
|
|
21
|
+
# @param [String, nil] username
|
|
22
|
+
#
|
|
23
|
+
def initialize(query, options: nil, api_key: nil, username: nil)
|
|
24
|
+
super(refang(query), options: options)
|
|
24
25
|
|
|
25
|
-
@query = refang(query)
|
|
26
26
|
@type = TypeChecker.type(query)
|
|
27
27
|
|
|
28
|
-
@username =
|
|
29
|
-
@api_key =
|
|
28
|
+
@username = username || Mihari.config.passivetotal_username
|
|
29
|
+
@api_key = api_key || Mihari.config.passivetotal_api_key
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
def artifacts
|
|
@@ -5,28 +5,39 @@ module Mihari
|
|
|
5
5
|
class Pulsedive < Base
|
|
6
6
|
include Mixins::Refang
|
|
7
7
|
|
|
8
|
-
param :query
|
|
9
|
-
|
|
10
8
|
# @return [String, nil]
|
|
11
9
|
attr_reader :type
|
|
12
10
|
|
|
13
11
|
# @return [String, nil]
|
|
14
12
|
attr_reader :api_key
|
|
15
13
|
|
|
16
|
-
#
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
14
|
+
#
|
|
15
|
+
# @param [String] query
|
|
16
|
+
# @param [Hash, nil] options
|
|
17
|
+
# @param [String, nil] api_key
|
|
18
|
+
#
|
|
19
|
+
def initialize(query, options: nil, api_key: nil)
|
|
20
|
+
super(refang(query), options: options)
|
|
21
21
|
|
|
22
|
-
@query = refang(query)
|
|
23
22
|
@type = TypeChecker.type(query)
|
|
24
23
|
|
|
25
|
-
@api_key =
|
|
24
|
+
@api_key = api_key || Mihari.config.pulsedive_api_key
|
|
26
25
|
end
|
|
27
26
|
|
|
28
27
|
def artifacts
|
|
29
|
-
|
|
28
|
+
raise InvalidInputError, "#{query}(type: #{type || "unknown"}) is not supported." unless valid_type?
|
|
29
|
+
|
|
30
|
+
indicator = client.get_indicator(query)
|
|
31
|
+
iid = indicator["iid"]
|
|
32
|
+
properties = client.get_properties(iid)
|
|
33
|
+
(properties["dns"] || []).filter_map do |property|
|
|
34
|
+
if %w[A PTR].include?(property["name"])
|
|
35
|
+
nil
|
|
36
|
+
else
|
|
37
|
+
data = property["value"]
|
|
38
|
+
Artifact.new(data: data, source: source, metadata: property)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
30
41
|
end
|
|
31
42
|
|
|
32
43
|
private
|
|
@@ -47,27 +58,6 @@ module Mihari
|
|
|
47
58
|
def valid_type?
|
|
48
59
|
%w[ip domain].include? type
|
|
49
60
|
end
|
|
50
|
-
|
|
51
|
-
#
|
|
52
|
-
# Search
|
|
53
|
-
#
|
|
54
|
-
# @return [Array<Mihari::Artifact>]
|
|
55
|
-
#
|
|
56
|
-
def search
|
|
57
|
-
raise InvalidInputError, "#{query}(type: #{type || "unknown"}) is not supported." unless valid_type?
|
|
58
|
-
|
|
59
|
-
indicator = client.get_indicator(query)
|
|
60
|
-
iid = indicator["iid"]
|
|
61
|
-
properties = client.get_properties(iid)
|
|
62
|
-
(properties["dns"] || []).filter_map do |property|
|
|
63
|
-
if %w[A PTR].include?(property["name"])
|
|
64
|
-
nil
|
|
65
|
-
else
|
|
66
|
-
data = property["value"]
|
|
67
|
-
Artifact.new(data: data, source: source, metadata: property)
|
|
68
|
-
end
|
|
69
|
-
end
|
|
70
|
-
end
|
|
71
61
|
end
|
|
72
62
|
end
|
|
73
63
|
end
|
|
@@ -5,8 +5,6 @@ module Mihari
|
|
|
5
5
|
class SecurityTrails < Base
|
|
6
6
|
include Mixins::Refang
|
|
7
7
|
|
|
8
|
-
param :query
|
|
9
|
-
|
|
10
8
|
# @return [String, nil]
|
|
11
9
|
attr_reader :type
|
|
12
10
|
|
|
@@ -16,13 +14,17 @@ module Mihari
|
|
|
16
14
|
# @return [String]
|
|
17
15
|
attr_reader :query
|
|
18
16
|
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
#
|
|
18
|
+
# @param [String] query
|
|
19
|
+
# @param [Hash, nil] options
|
|
20
|
+
# @param [String, nil] api_key
|
|
21
|
+
#
|
|
22
|
+
def initialize(query, options: nil, api_key: nil)
|
|
23
|
+
super(refang(query), options: options)
|
|
21
24
|
|
|
22
|
-
@query = refang(query)
|
|
23
25
|
@type = TypeChecker.type(query)
|
|
24
26
|
|
|
25
|
-
@api_key =
|
|
27
|
+
@api_key = api_key || Mihari.config.securitytrails_api_key
|
|
26
28
|
end
|
|
27
29
|
|
|
28
30
|
def artifacts
|
|
@@ -3,23 +3,18 @@
|
|
|
3
3
|
module Mihari
|
|
4
4
|
module Analyzers
|
|
5
5
|
class Shodan < Base
|
|
6
|
-
param :query
|
|
7
|
-
|
|
8
|
-
option :interval, default: proc { 0 }
|
|
9
|
-
|
|
10
6
|
# @return [String, nil]
|
|
11
7
|
attr_reader :api_key
|
|
12
8
|
|
|
13
|
-
#
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
# @
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
super(*args, **kwargs)
|
|
9
|
+
#
|
|
10
|
+
# @param [String] query
|
|
11
|
+
# @param [Hash, nil] options
|
|
12
|
+
# @param [String, nil] api_key
|
|
13
|
+
#
|
|
14
|
+
def initialize(query, options: nil, api_key: nil)
|
|
15
|
+
super(query, options: options)
|
|
21
16
|
|
|
22
|
-
@api_key =
|
|
17
|
+
@api_key = api_key || Mihari.config.shodan_api_key
|
|
23
18
|
end
|
|
24
19
|
|
|
25
20
|
def artifacts
|
|
@@ -3,35 +3,30 @@
|
|
|
3
3
|
module Mihari
|
|
4
4
|
module Analyzers
|
|
5
5
|
class Urlscan < Base
|
|
6
|
-
param :query
|
|
7
|
-
|
|
8
|
-
option :allowed_data_types, default: proc { SUPPORTED_DATA_TYPES }
|
|
9
|
-
|
|
10
|
-
option :interval, default: proc { 0 }
|
|
11
|
-
|
|
12
6
|
SUPPORTED_DATA_TYPES = %w[url domain ip].freeze
|
|
13
7
|
SIZE = 1000
|
|
14
8
|
|
|
15
9
|
# @return [String, nil]
|
|
16
10
|
attr_reader :api_key
|
|
17
11
|
|
|
18
|
-
# @return [String]
|
|
19
|
-
attr_reader :query
|
|
20
|
-
|
|
21
|
-
# @return [Integer]
|
|
22
|
-
attr_reader :interval
|
|
23
|
-
|
|
24
|
-
# @return [String]
|
|
12
|
+
# @return [Array<String>]
|
|
25
13
|
attr_reader :allowed_data_types
|
|
26
14
|
|
|
27
|
-
|
|
28
|
-
|
|
15
|
+
#
|
|
16
|
+
# @param [String] query
|
|
17
|
+
# @param [Hash, nil] options
|
|
18
|
+
# @param [String, nil] api_key
|
|
19
|
+
# @param [Array<String>] allowed_data_types
|
|
20
|
+
#
|
|
21
|
+
def initialize(query, options: nil, api_key: nil, allowed_data_types: SUPPORTED_DATA_TYPES)
|
|
22
|
+
super(query, options: options)
|
|
29
23
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
24
|
+
@api_key = api_key || Mihari.config.urlscan_api_key
|
|
25
|
+
@allowed_data_types = allowed_data_types
|
|
26
|
+
|
|
27
|
+
return if valid_allowed_data_types?
|
|
33
28
|
|
|
34
|
-
|
|
29
|
+
raise InvalidInputError, "allowed_data_types should be any of url, domain and ip."
|
|
35
30
|
end
|
|
36
31
|
|
|
37
32
|
def artifacts
|
|
@@ -82,7 +77,7 @@ module Mihari
|
|
|
82
77
|
search_after = res.results.last.sort.join(",")
|
|
83
78
|
|
|
84
79
|
# sleep #{interval} seconds to avoid the rate limitation (if it is set)
|
|
85
|
-
sleep interval
|
|
80
|
+
sleep(interval) if interval
|
|
86
81
|
end
|
|
87
82
|
|
|
88
83
|
responses
|
|
@@ -5,28 +5,34 @@ module Mihari
|
|
|
5
5
|
class VirusTotal < Base
|
|
6
6
|
include Mixins::Refang
|
|
7
7
|
|
|
8
|
-
param :query
|
|
9
|
-
|
|
10
8
|
# @return [String]
|
|
11
9
|
attr_reader :type
|
|
12
10
|
|
|
13
11
|
# @return [String, nil]
|
|
14
12
|
attr_reader :api_key
|
|
15
13
|
|
|
16
|
-
#
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
14
|
+
#
|
|
15
|
+
# @param [String] query
|
|
16
|
+
# @param [Hash, nil] options
|
|
17
|
+
# @param [String, nil] api_key
|
|
18
|
+
#
|
|
19
|
+
def initialize(query, options: nil, api_key: nil)
|
|
20
|
+
super(refang(query), options: options)
|
|
21
21
|
|
|
22
|
-
@query = refang(query)
|
|
23
22
|
@type = TypeChecker.type(query)
|
|
24
23
|
|
|
25
|
-
@api_key =
|
|
24
|
+
@api_key = api_key || Mihari.config.virustotal_api_key
|
|
26
25
|
end
|
|
27
26
|
|
|
28
27
|
def artifacts
|
|
29
|
-
|
|
28
|
+
case type
|
|
29
|
+
when "domain"
|
|
30
|
+
domain_search
|
|
31
|
+
when "ip"
|
|
32
|
+
ip_search
|
|
33
|
+
else
|
|
34
|
+
raise InvalidInputError, "#{query}(type: #{type || "unknown"}) is not supported." unless valid_type?
|
|
35
|
+
end
|
|
30
36
|
end
|
|
31
37
|
|
|
32
38
|
private
|
|
@@ -48,22 +54,6 @@ module Mihari
|
|
|
48
54
|
%w[ip domain].include? type
|
|
49
55
|
end
|
|
50
56
|
|
|
51
|
-
#
|
|
52
|
-
# Search
|
|
53
|
-
#
|
|
54
|
-
# @return [Array<Mihari::Artifact>]
|
|
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
57
|
#
|
|
68
58
|
# Domain search
|
|
69
59
|
#
|
|
@@ -3,25 +3,18 @@
|
|
|
3
3
|
module Mihari
|
|
4
4
|
module Analyzers
|
|
5
5
|
class VirusTotalIntelligence < Base
|
|
6
|
-
param :query
|
|
7
|
-
|
|
8
|
-
option :interval, default: proc { 0 }
|
|
9
|
-
|
|
10
6
|
# @return [String, nil]
|
|
11
7
|
attr_reader :api_key
|
|
12
8
|
|
|
13
|
-
#
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
# @
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
super
|
|
21
|
-
|
|
22
|
-
@query = query
|
|
9
|
+
#
|
|
10
|
+
# @param [String] query
|
|
11
|
+
# @param [Hash, nll] options
|
|
12
|
+
# @param [String, nil] api_key
|
|
13
|
+
#
|
|
14
|
+
def initialize(query, options: nil, api_key: nil)
|
|
15
|
+
super(query, options: options)
|
|
23
16
|
|
|
24
|
-
@api_key =
|
|
17
|
+
@api_key = api_key || Mihari.config.virustotal_api_key
|
|
25
18
|
end
|
|
26
19
|
|
|
27
20
|
def artifacts
|
|
@@ -53,13 +46,14 @@ module Mihari
|
|
|
53
46
|
responses = []
|
|
54
47
|
|
|
55
48
|
loop do
|
|
56
|
-
response = Structs::VirusTotalIntelligence::Response.from_dynamic!(client.intel_search(query,
|
|
49
|
+
response = Structs::VirusTotalIntelligence::Response.from_dynamic!(client.intel_search(query,
|
|
50
|
+
cursor: cursor))
|
|
57
51
|
responses << response
|
|
58
52
|
break if response.meta.cursor.nil?
|
|
59
53
|
|
|
60
54
|
cursor = response.meta.cursor
|
|
61
55
|
# sleep #{interval} seconds to avoid the rate limitation (if it is set)
|
|
62
|
-
sleep interval
|
|
56
|
+
sleep(interval) if interval
|
|
63
57
|
end
|
|
64
58
|
|
|
65
59
|
responses
|
|
@@ -3,28 +3,23 @@
|
|
|
3
3
|
module Mihari
|
|
4
4
|
module Analyzers
|
|
5
5
|
class ZoomEye < Base
|
|
6
|
-
param :query
|
|
7
|
-
|
|
8
|
-
option :type, default: proc { "host" }
|
|
9
|
-
|
|
10
|
-
option :interval, default: proc { 0 }
|
|
11
|
-
|
|
12
6
|
# @return [String, nil]
|
|
13
7
|
attr_reader :api_key
|
|
14
8
|
|
|
15
|
-
# @return [String]
|
|
16
|
-
attr_reader :query
|
|
17
|
-
|
|
18
9
|
# @return [String]
|
|
19
10
|
attr_reader :type
|
|
20
11
|
|
|
21
|
-
#
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
12
|
+
#
|
|
13
|
+
# @param [String] query
|
|
14
|
+
# @param [Hash, nil] options
|
|
15
|
+
# @param [String, nil] api_key
|
|
16
|
+
# @param [String] type
|
|
17
|
+
#
|
|
18
|
+
def initialize(query, options: nil, api_key: nil, type: "host")
|
|
19
|
+
super(query, options: options)
|
|
26
20
|
|
|
27
|
-
@
|
|
21
|
+
@type = type
|
|
22
|
+
@api_key = api_key || Mihari.config.zoomeye_api_key
|
|
28
23
|
end
|
|
29
24
|
|
|
30
25
|
def artifacts
|
|
@@ -109,7 +104,7 @@ module Mihari
|
|
|
109
104
|
break if total <= page * PAGE_SIZE
|
|
110
105
|
|
|
111
106
|
# sleep #{interval} seconds to avoid the rate limitation (if it is set)
|
|
112
|
-
sleep interval
|
|
107
|
+
sleep(interval) if interval
|
|
113
108
|
end
|
|
114
109
|
convert_responses responses.compact
|
|
115
110
|
end
|
|
@@ -142,7 +137,7 @@ module Mihari
|
|
|
142
137
|
break if total <= page * PAGE_SIZE
|
|
143
138
|
|
|
144
139
|
# sleep #{interval} seconds to avoid the rate limitation (if it is set)
|
|
145
|
-
sleep interval
|
|
140
|
+
sleep(interval) if interval
|
|
146
141
|
end
|
|
147
142
|
convert_responses responses.compact
|
|
148
143
|
end
|