mihari 4.3.0 → 4.4.0
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 +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)
|