mihari 4.3.0 → 4.4.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/binaryedge.rb +10 -1
- data/lib/mihari/analyzers/censys.rb +26 -1
- data/lib/mihari/analyzers/circl.rb +23 -1
- data/lib/mihari/analyzers/greynoise.rb +10 -1
- data/lib/mihari/analyzers/onyphe.rb +10 -1
- data/lib/mihari/analyzers/otx.rb +8 -2
- data/lib/mihari/analyzers/passivetotal.rb +25 -3
- data/lib/mihari/analyzers/pulsedive.rb +7 -1
- data/lib/mihari/analyzers/securitytrails.rb +7 -1
- data/lib/mihari/analyzers/shodan.rb +10 -1
- data/lib/mihari/analyzers/spyse.rb +10 -1
- data/lib/mihari/analyzers/urlscan.rb +6 -1
- data/lib/mihari/analyzers/virustotal.rb +7 -2
- data/lib/mihari/analyzers/virustotal_intelligence.rb +6 -1
- data/lib/mihari/analyzers/zoomeye.rb +16 -2
- data/lib/mihari/cli/main.rb +2 -0
- data/lib/mihari/commands/search.rb +14 -0
- data/lib/mihari/commands/version.rb +18 -0
- data/lib/mihari/database.rb +10 -2
- data/lib/mihari/emitters/misp.rb +14 -8
- data/lib/mihari/emitters/slack.rb +20 -28
- data/lib/mihari/emitters/the_hive.rb +18 -6
- data/lib/mihari/entities/rule.rb +1 -12
- data/lib/mihari/errors.rb +2 -0
- data/lib/mihari/mixins/configurable.rb +12 -1
- data/lib/mihari/mixins/rule.rb +16 -19
- data/lib/mihari/models/artifact.rb +7 -2
- data/lib/mihari/models/rule.rb +12 -3
- data/lib/mihari/schemas/analyzer.rb +89 -10
- data/lib/mihari/schemas/emitter.rb +35 -0
- data/lib/mihari/schemas/rule.rb +5 -62
- data/lib/mihari/structs/rule.rb +33 -5
- data/lib/mihari/types.rb +0 -25
- data/lib/mihari/version.rb +1 -1
- data/lib/mihari/web/endpoints/rules.rb +20 -3
- data/lib/mihari/web/public/index.html +1 -1
- data/lib/mihari/web/public/redoc-static.html +11 -11
- data/lib/mihari/web/public/static/css/app.de5845d8.css +1 -0
- data/lib/mihari/web/public/static/css/chunk-vendors.da2a7bfc.css +7 -0
- data/lib/mihari/web/public/static/js/app-legacy.f550d6ae.js +2 -0
- data/lib/mihari/web/public/static/js/app-legacy.f550d6ae.js.map +1 -0
- data/lib/mihari/web/public/static/js/app.40749592.js +2 -0
- data/lib/mihari/web/public/static/js/app.40749592.js.map +1 -0
- data/lib/mihari/web/public/static/js/chunk-vendors-legacy.d6b76c57.js +25 -0
- data/lib/mihari/web/public/static/js/chunk-vendors-legacy.d6b76c57.js.map +1 -0
- data/lib/mihari/web/public/static/js/chunk-vendors.3bdbaffb.js +31 -0
- data/lib/mihari/web/public/static/js/chunk-vendors.3bdbaffb.js.map +1 -0
- data/mihari.gemspec +2 -2
- data/sig/lib/mihari/analyzers/binaryedge.rbs +2 -0
- data/sig/lib/mihari/analyzers/censys.rbs +4 -0
- data/sig/lib/mihari/analyzers/circl.rbs +5 -1
- data/sig/lib/mihari/analyzers/onyphe.rbs +2 -0
- data/sig/lib/mihari/analyzers/otx.rbs +3 -1
- data/sig/lib/mihari/analyzers/passivetotal.rbs +5 -1
- data/sig/lib/mihari/analyzers/pulsedive.rbs +3 -1
- data/sig/lib/mihari/analyzers/securitytrails.rbs +3 -1
- data/sig/lib/mihari/analyzers/shodan.rbs +2 -0
- data/sig/lib/mihari/analyzers/spyse.rbs +3 -1
- data/sig/lib/mihari/analyzers/urlscan.rbs +2 -0
- data/sig/lib/mihari/analyzers/virustotal.rbs +3 -1
- data/sig/lib/mihari/analyzers/virustotal_intelligence.rbs +2 -0
- data/sig/lib/mihari/analyzers/zoomeye.rbs +3 -1
- data/sig/lib/mihari/emitters/misp.rbs +6 -0
- data/sig/lib/mihari/emitters/slack.rbs +8 -20
- data/sig/lib/mihari/emitters/the_hive.rbs +4 -0
- data/sig/lib/mihari/mixins/configurable.rbs +4 -0
- data/sig/lib/mihari/mixins/rule.rbs +2 -0
- data/sig/lib/mihari/models/rule.rbs +3 -0
- data/sig/lib/mihari/structs/rule.rbs +5 -1
- metadata +18 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 44f680c0a24d2b66c8f13c8abe14994138231a4099b975d94a917f105561329c
|
4
|
+
data.tar.gz: b9da29828c04ad6151bb748f17c3518875b90208f728e4f1be9e0f716acd5368
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ddccc9e9b10822bc93bb595f837a327c6459c51799ad95483014173c7d911405fd7fcd869f435a7404af585ccfa21ddfcd1ae922a94096a850eda52c4886627b
|
7
|
+
data.tar.gz: 8962eb94f57de019a7dd1040132d315482dbf3668a36ae4f61da46f31994c3bac0df47142fdbe998b80603cdcce86de0c7bb276eb2335e48d25820eebc94dee8
|
@@ -9,6 +9,15 @@ module Mihari
|
|
9
9
|
|
10
10
|
option :interval, default: proc { 0 }
|
11
11
|
|
12
|
+
# @return [String, nil]
|
13
|
+
attr_reader :api_key
|
14
|
+
|
15
|
+
def initialize(*args, **kwargs)
|
16
|
+
super(*args, **kwargs)
|
17
|
+
|
18
|
+
@api_key = kwargs[:api_key] || Mihari.config.binaryedge_api_key
|
19
|
+
end
|
20
|
+
|
12
21
|
def artifacts
|
13
22
|
results = search
|
14
23
|
return [] unless results || results.empty?
|
@@ -67,7 +76,7 @@ module Mihari
|
|
67
76
|
end
|
68
77
|
|
69
78
|
def api
|
70
|
-
@api ||= ::BinaryEdge::API.new(
|
79
|
+
@api ||= ::BinaryEdge::API.new(api_key)
|
71
80
|
end
|
72
81
|
end
|
73
82
|
end
|
@@ -9,10 +9,27 @@ module Mihari
|
|
9
9
|
|
10
10
|
option :interval, default: proc { 0 }
|
11
11
|
|
12
|
+
# @return [String, nil]
|
13
|
+
attr_reader :id
|
14
|
+
|
15
|
+
# @return [String, nil]
|
16
|
+
attr_reader :secret
|
17
|
+
|
18
|
+
def initialize(*args, **kwargs)
|
19
|
+
super(*args, **kwargs)
|
20
|
+
|
21
|
+
@id = kwargs[:id] || Mihari.config.censys_id
|
22
|
+
@secret = kwargs[:secret] || Mihari.config.censys_secret
|
23
|
+
end
|
24
|
+
|
12
25
|
def artifacts
|
13
26
|
search
|
14
27
|
end
|
15
28
|
|
29
|
+
def configured?
|
30
|
+
configuration_keys.all? { |key| Mihari.config.send(key) } || (id? && secret?)
|
31
|
+
end
|
32
|
+
|
16
33
|
private
|
17
34
|
|
18
35
|
#
|
@@ -85,7 +102,15 @@ module Mihari
|
|
85
102
|
end
|
86
103
|
|
87
104
|
def api
|
88
|
-
@api ||= ::Censys::API.new(
|
105
|
+
@api ||= ::Censys::API.new(id, secret)
|
106
|
+
end
|
107
|
+
|
108
|
+
def id?
|
109
|
+
!id.nil?
|
110
|
+
end
|
111
|
+
|
112
|
+
def secret?
|
113
|
+
!secret.nil?
|
89
114
|
end
|
90
115
|
end
|
91
116
|
end
|
@@ -9,19 +9,33 @@ module Mihari
|
|
9
9
|
|
10
10
|
param :query
|
11
11
|
|
12
|
+
# @return [String, nil]
|
12
13
|
attr_reader :type
|
13
14
|
|
15
|
+
# @return [String, nil]
|
16
|
+
attr_reader :username
|
17
|
+
|
18
|
+
# @return [String, nil]
|
19
|
+
attr_reader :password
|
20
|
+
|
14
21
|
def initialize(*args, **kwargs)
|
15
22
|
super
|
16
23
|
|
17
24
|
@query = refang(query)
|
18
25
|
@type = TypeChecker.type(query)
|
26
|
+
|
27
|
+
@username = kwargs[:username] || Mihari.config.circl_passive_username
|
28
|
+
@password = kwargs[:password] || Mihari.config.circl_passive_password
|
19
29
|
end
|
20
30
|
|
21
31
|
def artifacts
|
22
32
|
search || []
|
23
33
|
end
|
24
34
|
|
35
|
+
def configured?
|
36
|
+
configuration_keys.all? { |key| Mihari.config.send(key) } || (username? && password?)
|
37
|
+
end
|
38
|
+
|
25
39
|
private
|
26
40
|
|
27
41
|
def configuration_keys
|
@@ -29,7 +43,7 @@ module Mihari
|
|
29
43
|
end
|
30
44
|
|
31
45
|
def api
|
32
|
-
@api ||= ::PassiveCIRCL::API.new(username:
|
46
|
+
@api ||= ::PassiveCIRCL::API.new(username: username, password: password)
|
33
47
|
end
|
34
48
|
|
35
49
|
#
|
@@ -71,6 +85,14 @@ module Mihari
|
|
71
85
|
seen = result["seen"] || []
|
72
86
|
seen.uniq
|
73
87
|
end
|
88
|
+
|
89
|
+
def username?
|
90
|
+
!username.nil?
|
91
|
+
end
|
92
|
+
|
93
|
+
def password?
|
94
|
+
!password.nil?
|
95
|
+
end
|
74
96
|
end
|
75
97
|
end
|
76
98
|
end
|
@@ -7,6 +7,15 @@ module Mihari
|
|
7
7
|
class GreyNoise < Base
|
8
8
|
param :query
|
9
9
|
|
10
|
+
# @return [String, nil]
|
11
|
+
attr_reader :api_key
|
12
|
+
|
13
|
+
def initialize(*args, **kwargs)
|
14
|
+
super(*args, **kwargs)
|
15
|
+
|
16
|
+
@api_key = kwargs[:api_key] || Mihari.config.greynoise_api_key
|
17
|
+
end
|
18
|
+
|
10
19
|
def artifacts
|
11
20
|
res = Structs::GreyNoise::Response.from_dynamic!(search)
|
12
21
|
res.data.map do |datum|
|
@@ -23,7 +32,7 @@ module Mihari
|
|
23
32
|
end
|
24
33
|
|
25
34
|
def api
|
26
|
-
@api ||= ::GreyNoise::API.new(key:
|
35
|
+
@api ||= ::GreyNoise::API.new(key: api_key)
|
27
36
|
end
|
28
37
|
|
29
38
|
#
|
@@ -10,6 +10,15 @@ module Mihari
|
|
10
10
|
|
11
11
|
option :interval, default: proc { 0 }
|
12
12
|
|
13
|
+
# @return [String, nil]
|
14
|
+
attr_reader :api_key
|
15
|
+
|
16
|
+
def initialize(*args, **kwargs)
|
17
|
+
super(*args, **kwargs)
|
18
|
+
|
19
|
+
@api_key = kwargs[:api_key] || Mihari.config.onyphe_api_key
|
20
|
+
end
|
21
|
+
|
13
22
|
def artifacts
|
14
23
|
responses = search
|
15
24
|
return [] unless responses
|
@@ -29,7 +38,7 @@ module Mihari
|
|
29
38
|
end
|
30
39
|
|
31
40
|
def api
|
32
|
-
@api ||= ::Onyphe::API.new(
|
41
|
+
@api ||= ::Onyphe::API.new(api_key)
|
33
42
|
end
|
34
43
|
|
35
44
|
#
|
data/lib/mihari/analyzers/otx.rb
CHANGED
@@ -9,13 +9,19 @@ module Mihari
|
|
9
9
|
|
10
10
|
param :query
|
11
11
|
|
12
|
+
# @return [String, nil]
|
12
13
|
attr_reader :type
|
13
14
|
|
15
|
+
# @return [String, nil]
|
16
|
+
attr_reader :api_key
|
17
|
+
|
14
18
|
def initialize(*args, **kwargs)
|
15
19
|
super
|
16
20
|
|
17
21
|
@query = refang(query)
|
18
22
|
@type = TypeChecker.type(query)
|
23
|
+
|
24
|
+
@api_key = kwargs[:api_key] || Mihari.config.otx_api_key
|
19
25
|
end
|
20
26
|
|
21
27
|
def artifacts
|
@@ -29,11 +35,11 @@ module Mihari
|
|
29
35
|
end
|
30
36
|
|
31
37
|
def domain_client
|
32
|
-
@domain_client ||= ::OTX::Domain.new(
|
38
|
+
@domain_client ||= ::OTX::Domain.new(api_key)
|
33
39
|
end
|
34
40
|
|
35
41
|
def ip_client
|
36
|
-
@ip_client ||= ::OTX::IP.new(
|
42
|
+
@ip_client ||= ::OTX::IP.new(api_key)
|
37
43
|
end
|
38
44
|
|
39
45
|
#
|
@@ -9,19 +9,33 @@ module Mihari
|
|
9
9
|
|
10
10
|
param :query
|
11
11
|
|
12
|
+
# @return [String, nil]
|
12
13
|
attr_reader :type
|
13
14
|
|
15
|
+
# @return [String, nil]
|
16
|
+
attr_reader :username
|
17
|
+
|
18
|
+
# @return [String, nil]
|
19
|
+
attr_reader :api_key
|
20
|
+
|
14
21
|
def initialize(*args, **kwargs)
|
15
|
-
super
|
22
|
+
super(*args, **kwargs)
|
16
23
|
|
17
24
|
@query = refang(query)
|
18
25
|
@type = TypeChecker.type(query)
|
26
|
+
|
27
|
+
@username = kwargs[:username] || Mihari.config.passivetotal_username
|
28
|
+
@api_key = kwargs[:api_key] || Mihari.config.passivetotal_api_key
|
19
29
|
end
|
20
30
|
|
21
31
|
def artifacts
|
22
32
|
search || []
|
23
33
|
end
|
24
34
|
|
35
|
+
def configured?
|
36
|
+
configuration_keys.all? { |key| Mihari.config.send(key) } || (username? && api_key?)
|
37
|
+
end
|
38
|
+
|
25
39
|
private
|
26
40
|
|
27
41
|
def configuration_keys
|
@@ -29,7 +43,7 @@ module Mihari
|
|
29
43
|
end
|
30
44
|
|
31
45
|
def api
|
32
|
-
@api ||= ::PassiveTotal::API.new(username:
|
46
|
+
@api ||= ::PassiveTotal::API.new(username: username, api_key: api_key)
|
33
47
|
end
|
34
48
|
|
35
49
|
#
|
@@ -93,9 +107,17 @@ module Mihari
|
|
93
107
|
results = res["results"] || []
|
94
108
|
results.map do |result|
|
95
109
|
data = result["ipAddresses"]
|
96
|
-
Artifact.new(data:
|
110
|
+
data.map { |d| Artifact.new(data: d, source: source, metadata: result) }
|
97
111
|
end.flatten
|
98
112
|
end
|
113
|
+
|
114
|
+
def username?
|
115
|
+
!username.nil?
|
116
|
+
end
|
117
|
+
|
118
|
+
def api_key?
|
119
|
+
!api_key.nil?
|
120
|
+
end
|
99
121
|
end
|
100
122
|
end
|
101
123
|
end
|
@@ -9,13 +9,19 @@ module Mihari
|
|
9
9
|
|
10
10
|
param :query
|
11
11
|
|
12
|
+
# @return [String, nil]
|
12
13
|
attr_reader :type
|
13
14
|
|
15
|
+
# @return [String, nil]
|
16
|
+
attr_reader :api_key
|
17
|
+
|
14
18
|
def initialize(*args, **kwargs)
|
15
19
|
super
|
16
20
|
|
17
21
|
@query = refang(query)
|
18
22
|
@type = TypeChecker.type(query)
|
23
|
+
|
24
|
+
@api_key = kwargs[:api_key] || Mihari.config.pulsedive_api_key
|
19
25
|
end
|
20
26
|
|
21
27
|
def artifacts
|
@@ -29,7 +35,7 @@ module Mihari
|
|
29
35
|
end
|
30
36
|
|
31
37
|
def api
|
32
|
-
@api ||= ::Pulsedive::API.new(
|
38
|
+
@api ||= ::Pulsedive::API.new(api_key)
|
33
39
|
end
|
34
40
|
|
35
41
|
#
|
@@ -9,13 +9,19 @@ module Mihari
|
|
9
9
|
|
10
10
|
param :query
|
11
11
|
|
12
|
+
# @return [String, nil]
|
12
13
|
attr_reader :type
|
13
14
|
|
15
|
+
# @return [String, nil]
|
16
|
+
attr_reader :api_key
|
17
|
+
|
14
18
|
def initialize(*args, **kwargs)
|
15
19
|
super
|
16
20
|
|
17
21
|
@query = refang(query)
|
18
22
|
@type = TypeChecker.type(query)
|
23
|
+
|
24
|
+
@api_key = kwargs[:api_key] || Mihari.config.securitytrails_api_key
|
19
25
|
end
|
20
26
|
|
21
27
|
def artifacts
|
@@ -29,7 +35,7 @@ module Mihari
|
|
29
35
|
end
|
30
36
|
|
31
37
|
def api
|
32
|
-
@api ||= ::SecurityTrails::API.new(
|
38
|
+
@api ||= ::SecurityTrails::API.new(api_key)
|
33
39
|
end
|
34
40
|
|
35
41
|
#
|
@@ -9,6 +9,15 @@ module Mihari
|
|
9
9
|
|
10
10
|
option :interval, default: proc { 0 }
|
11
11
|
|
12
|
+
# @return [String, nil]
|
13
|
+
attr_reader :api_key
|
14
|
+
|
15
|
+
def initialize(*args, **kwargs)
|
16
|
+
super(*args, **kwargs)
|
17
|
+
|
18
|
+
@api_key = kwargs[:api_key] || Mihari.config.shodan_api_key
|
19
|
+
end
|
20
|
+
|
12
21
|
def artifacts
|
13
22
|
results = search
|
14
23
|
return [] unless results || results.empty?
|
@@ -29,7 +38,7 @@ module Mihari
|
|
29
38
|
end
|
30
39
|
|
31
40
|
def api
|
32
|
-
@api ||= ::Shodan::API.new(key:
|
41
|
+
@api ||= ::Shodan::API.new(key: api_key)
|
33
42
|
end
|
34
43
|
|
35
44
|
#
|
@@ -9,6 +9,15 @@ module Mihari
|
|
9
9
|
|
10
10
|
option :type, default: proc { "domain" }
|
11
11
|
|
12
|
+
# @return [String, nil]
|
13
|
+
attr_reader :api_key
|
14
|
+
|
15
|
+
def initialize(*args, **kwargs)
|
16
|
+
super(*args, **kwargs)
|
17
|
+
|
18
|
+
@api_key = kwargs[:api_key] || Mihari.config.spyse_api_key
|
19
|
+
end
|
20
|
+
|
12
21
|
def artifacts
|
13
22
|
search || []
|
14
23
|
end
|
@@ -24,7 +33,7 @@ module Mihari
|
|
24
33
|
end
|
25
34
|
|
26
35
|
def api
|
27
|
-
@api ||= ::Spyse::API.new(
|
36
|
+
@api ||= ::Spyse::API.new(api_key)
|
28
37
|
end
|
29
38
|
|
30
39
|
#
|
@@ -14,10 +14,15 @@ module Mihari
|
|
14
14
|
SUPPORTED_DATA_TYPES = %w[url domain ip].freeze
|
15
15
|
SIZE = 1000
|
16
16
|
|
17
|
+
# @return [String, nil]
|
18
|
+
attr_reader :api_key
|
19
|
+
|
17
20
|
def initialize(*args, **kwargs)
|
18
21
|
super
|
19
22
|
|
20
23
|
raise InvalidInputError, "allowed_data_types should be any of url, domain and ip." unless valid_alllowed_data_types?
|
24
|
+
|
25
|
+
@api_key = kwargs[:api_key] || Mihari.config.urlscan_api_key
|
21
26
|
end
|
22
27
|
|
23
28
|
def artifacts
|
@@ -40,7 +45,7 @@ module Mihari
|
|
40
45
|
end
|
41
46
|
|
42
47
|
def api
|
43
|
-
@api ||= ::UrlScan::API.new(
|
48
|
+
@api ||= ::UrlScan::API.new(api_key)
|
44
49
|
end
|
45
50
|
|
46
51
|
#
|
@@ -11,11 +11,16 @@ module Mihari
|
|
11
11
|
|
12
12
|
attr_reader :type
|
13
13
|
|
14
|
+
# @return [String, nil]
|
15
|
+
attr_reader :api_key
|
16
|
+
|
14
17
|
def initialize(*args, **kwargs)
|
15
|
-
super
|
18
|
+
super(*args, **kwargs)
|
16
19
|
|
17
20
|
@query = refang(query)
|
18
21
|
@type = TypeChecker.type(query)
|
22
|
+
|
23
|
+
@api_key = kwargs[:api_key] || Mihari.config.virustotal_api_key
|
19
24
|
end
|
20
25
|
|
21
26
|
def artifacts
|
@@ -29,7 +34,7 @@ module Mihari
|
|
29
34
|
end
|
30
35
|
|
31
36
|
def api
|
32
|
-
@api = ::VirusTotal::API.new(key:
|
37
|
+
@api = ::VirusTotal::API.new(key: api_key)
|
33
38
|
end
|
34
39
|
|
35
40
|
#
|
@@ -9,10 +9,15 @@ module Mihari
|
|
9
9
|
|
10
10
|
option :interval, default: proc { 0 }
|
11
11
|
|
12
|
+
# @return [String, nil]
|
13
|
+
attr_reader :api_key
|
14
|
+
|
12
15
|
def initialize(*args, **kwargs)
|
13
16
|
super
|
14
17
|
|
15
18
|
@query = query
|
19
|
+
|
20
|
+
@api_key = kwargs[:api_key] || Mihari.config.virustotal_api_key
|
16
21
|
end
|
17
22
|
|
18
23
|
def artifacts
|
@@ -36,7 +41,7 @@ module Mihari
|
|
36
41
|
# @return [::VirusTotal::API]
|
37
42
|
#
|
38
43
|
def api
|
39
|
-
@api = ::VirusTotal::API.new(key:
|
44
|
+
@api = ::VirusTotal::API.new(key: api_key)
|
40
45
|
end
|
41
46
|
|
42
47
|
#
|
@@ -11,6 +11,15 @@ module Mihari
|
|
11
11
|
|
12
12
|
option :interval, default: proc { 0 }
|
13
13
|
|
14
|
+
# @return [String, nil]
|
15
|
+
attr_reader :api_key
|
16
|
+
|
17
|
+
def initialize(*args, **kwargs)
|
18
|
+
super(*args, **kwargs)
|
19
|
+
|
20
|
+
@api_key = kwargs[:api_key] || Mihari.config.zoomeye_api_key
|
21
|
+
end
|
22
|
+
|
14
23
|
def artifacts
|
15
24
|
case type
|
16
25
|
when "host"
|
@@ -40,7 +49,7 @@ module Mihari
|
|
40
49
|
end
|
41
50
|
|
42
51
|
def api
|
43
|
-
@api ||= ::ZoomEye::API.new(api_key:
|
52
|
+
@api ||= ::ZoomEye::API.new(api_key: api_key)
|
44
53
|
end
|
45
54
|
|
46
55
|
#
|
@@ -55,7 +64,12 @@ module Mihari
|
|
55
64
|
matches = res["matches"] || []
|
56
65
|
matches.map do |match|
|
57
66
|
data = match["ip"]
|
58
|
-
|
67
|
+
|
68
|
+
if data.is_a?(Array)
|
69
|
+
data.map { |d| Artifact.new(data: d, source: source, metadata: match) }
|
70
|
+
else
|
71
|
+
Artifact.new(data: data, source: source, metadata: match)
|
72
|
+
end
|
59
73
|
end
|
60
74
|
end.flatten.compact.uniq
|
61
75
|
end
|
data/lib/mihari/cli/main.rb
CHANGED
@@ -4,6 +4,7 @@ require "thor"
|
|
4
4
|
|
5
5
|
# Commands
|
6
6
|
require "mihari/commands/search"
|
7
|
+
require "mihari/commands/version"
|
7
8
|
require "mihari/commands/web"
|
8
9
|
|
9
10
|
# CLIs
|
@@ -16,6 +17,7 @@ module Mihari
|
|
16
17
|
module CLI
|
17
18
|
class Main < Base
|
18
19
|
include Mihari::Commands::Search
|
20
|
+
include Mihari::Commands::Version
|
19
21
|
include Mihari::Commands::Web
|
20
22
|
|
21
23
|
desc "init", "Sub commands to initialize a rule"
|
@@ -10,6 +10,7 @@ module Mihari
|
|
10
10
|
def self.included(thor)
|
11
11
|
thor.class_eval do
|
12
12
|
desc "search [RULE]", "Search by a rule"
|
13
|
+
method_option :yes, type: :boolean, aliases: "-y", desc: "yes to overwrite the rule in the database"
|
13
14
|
def search_by_rule(path_or_id)
|
14
15
|
rule = load_rule(path_or_id)
|
15
16
|
|
@@ -20,6 +21,19 @@ module Mihari
|
|
20
21
|
raise e
|
21
22
|
end
|
22
23
|
|
24
|
+
# check update
|
25
|
+
id = rule.id
|
26
|
+
yes = options["yes"] || false
|
27
|
+
unless yes
|
28
|
+
with_db_connection do
|
29
|
+
rule_ = Mihari::Rule.find(id)
|
30
|
+
next if rule.yaml == rule_.yaml
|
31
|
+
return unless yes?("This operation will overwrite the rule in the database (Rule ID: #{id}). Are you sure you want to update the rule? (yes/no)")
|
32
|
+
rescue ActiveRecord::RecordNotFound
|
33
|
+
next
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
23
37
|
analyzer = rule.to_analyzer
|
24
38
|
|
25
39
|
with_error_notification do
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mihari
|
4
|
+
module Commands
|
5
|
+
module Version
|
6
|
+
def self.included(thor)
|
7
|
+
thor.class_eval do
|
8
|
+
map %w[--version -v] => :__print_version
|
9
|
+
|
10
|
+
desc "--version, -v", "Print the version"
|
11
|
+
def __print_version
|
12
|
+
puts Mihari::VERSION
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/mihari/database.rb
CHANGED
@@ -112,6 +112,12 @@ class AddeMetadataToArtifactSchema < ActiveRecord::Migration[7.0]
|
|
112
112
|
end
|
113
113
|
end
|
114
114
|
|
115
|
+
class AddYAMLToRulesSchema < ActiveRecord::Migration[7.0]
|
116
|
+
def change
|
117
|
+
add_column :rules, :yaml, :text, if_not_exists: true
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
115
121
|
def adapter
|
116
122
|
return "postgresql" if Mihari.config.database.start_with?("postgresql://", "postgres://")
|
117
123
|
return "mysql2" if Mihari.config.database.start_with?("mysql2://")
|
@@ -137,9 +143,11 @@ module Mihari
|
|
137
143
|
AddeSourceToArtifactSchema,
|
138
144
|
EnrichmentsSchema,
|
139
145
|
EnrichmentCreatedAtSchema,
|
140
|
-
# v4
|
146
|
+
# v4.0
|
141
147
|
RuleSchema,
|
142
|
-
AddeMetadataToArtifactSchema
|
148
|
+
AddeMetadataToArtifactSchema,
|
149
|
+
# v4.4
|
150
|
+
AddYAMLToRulesSchema
|
143
151
|
].each { |schema| schema.migrate direction }
|
144
152
|
end
|
145
153
|
memoize :migrate unless test_env?
|
data/lib/mihari/emitters/misp.rb
CHANGED
@@ -5,12 +5,21 @@ require "misp"
|
|
5
5
|
module Mihari
|
6
6
|
module Emitters
|
7
7
|
class MISP < Base
|
8
|
-
|
9
|
-
|
8
|
+
# @return [String, nil]
|
9
|
+
attr_reader :api_endpoint
|
10
|
+
|
11
|
+
# @return [String, nil]
|
12
|
+
attr_reader :api_key
|
13
|
+
|
14
|
+
def initialize(*args, **kwargs)
|
15
|
+
super(*args, **kwargs)
|
16
|
+
|
17
|
+
@api_endpoint = kwargs[:api_endpoint] || Mihari.config.misp_api_endpoint
|
18
|
+
@api_key = kwargs[:api_key] || Mihari.config.misp_api_key
|
10
19
|
|
11
20
|
::MISP.configure do |config|
|
12
|
-
config.api_endpoint =
|
13
|
-
config.api_key =
|
21
|
+
config.api_endpoint = api_endpoint
|
22
|
+
config.api_key = api_key
|
14
23
|
end
|
15
24
|
end
|
16
25
|
|
@@ -99,7 +108,6 @@ module Mihari
|
|
99
108
|
# @return [Boolean]
|
100
109
|
#
|
101
110
|
def api_endpoint?
|
102
|
-
api_endpoint = ::MISP.configuration.api_endpoint
|
103
111
|
!api_endpoint.nil? && !api_endpoint.empty?
|
104
112
|
end
|
105
113
|
|
@@ -109,7 +117,6 @@ module Mihari
|
|
109
117
|
# @return [Boolean]
|
110
118
|
#
|
111
119
|
def api_key?
|
112
|
-
api_key = ::MISP.configuration.api_key
|
113
120
|
!api_key.nil? && !api_key.empty?
|
114
121
|
end
|
115
122
|
|
@@ -119,8 +126,7 @@ module Mihari
|
|
119
126
|
# @return [Boolean]
|
120
127
|
#
|
121
128
|
def ping?
|
122
|
-
base_url =
|
123
|
-
base_url = base_url.end_with?("/") ? base_url[0..-2] : base_url
|
129
|
+
base_url = api_endpoint.end_with?("/") ? api_endpoint[0..-2] : api_endpoint
|
124
130
|
url = "#{base_url}/users/login"
|
125
131
|
|
126
132
|
http = Net::Ping::HTTP.new(url)
|