mihari 5.1.3 → 5.2.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/commands/web.rb +5 -8
- data/lib/mihari/emitters/misp.rb +4 -4
- data/lib/mihari/entities/artifact.rb +3 -2
- data/lib/mihari/mixins/configurable.rb +3 -1
- data/lib/mihari/models/alert.rb +16 -12
- data/lib/mihari/models/rule.rb +1 -2
- data/lib/mihari/schemas/rule.rb +1 -0
- data/lib/mihari/structs/filters.rb +1 -15
- data/lib/mihari/structs/rule.rb +1 -1
- data/lib/mihari/version.rb +1 -1
- data/lib/mihari/web/app.rb +7 -5
- data/lib/mihari/web/endpoints/alerts.rb +7 -20
- data/lib/mihari/web/endpoints/rules.rb +4 -11
- data/lib/mihari/web/public/assets/{fa-brands-400-2ef6fdde.ttf → fa-brands-400-20c4a58b.ttf} +0 -0
- data/lib/mihari/web/public/assets/fa-brands-400-74833209.woff2 +0 -0
- data/lib/mihari/web/public/assets/{fa-regular-400-12dea17b.ttf → fa-regular-400-528d022d.ttf} +0 -0
- data/lib/mihari/web/public/assets/fa-regular-400-8e7e5ea1.woff2 +0 -0
- data/lib/mihari/web/public/assets/{fa-solid-900-67a880b4.ttf → fa-solid-900-67a65763.ttf} +0 -0
- data/lib/mihari/web/public/assets/fa-solid-900-7152a693.woff2 +0 -0
- data/lib/mihari/web/public/assets/{fa-v4compatibility-8d9500e8.ttf → fa-v4compatibility-0515a423.ttf} +0 -0
- data/lib/mihari/web/public/assets/fa-v4compatibility-694a17c3.woff2 +0 -0
- data/lib/mihari/web/public/assets/index-9948ee35.js +50 -0
- data/lib/mihari/web/public/assets/{index-625e95fe.css → index-d88cc3f1.css} +2 -2
- data/lib/mihari/web/public/index.html +2 -2
- data/lib/mihari/web/public/redoc-static.html +7 -4
- data/lib/mihari.rb +2 -0
- data/mihari.gemspec +8 -8
- metadata +30 -30
- data/lib/mihari/web/public/assets/fa-brands-400-f4617423.woff2 +0 -0
- data/lib/mihari/web/public/assets/fa-regular-400-7ba24c41.woff2 +0 -0
- data/lib/mihari/web/public/assets/fa-solid-900-e2c5cf54.woff2 +0 -0
- data/lib/mihari/web/public/assets/fa-v4compatibility-7c377405.woff2 +0 -0
- data/lib/mihari/web/public/assets/index-7d0fb8c4.js +0 -50
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0c98bfd494945e88b92bbf939e9ea94d5d4161cc35ae7d7a0d01ead7a30a1f09
|
|
4
|
+
data.tar.gz: 4794020ea3ad71fe70016030abd52063d523c7bbf7a31d9129fe8a2b76f43bc5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: aff9062a772dd86fd202e9112d92c923c815dba5d15b83b567c8ff00a72803ece1674201daeffc2934beba54f7d9ff2e929e1d570de9fe21c503bd89c6648c13
|
|
7
|
+
data.tar.gz: 8ab4db7d0385ac7301c158c95cba0855cc002c9e115911e497011e0705c97fdc5205a6f47e07917d867ba5270f3e4b24f80c38a407c34a2a3db717b9fd5ef732
|
data/lib/mihari/commands/web.rb
CHANGED
|
@@ -11,17 +11,14 @@ module Mihari
|
|
|
11
11
|
method_option :threads, type: :string, default: "0:5", desc: "min:max threads to use"
|
|
12
12
|
method_option :verbose, type: :boolean, default: true, desc: "Report each request"
|
|
13
13
|
method_option :worker_timeout, type: :numeric, default: 60, desc: "Worker timeout value (in seconds)"
|
|
14
|
+
method_option :hide_config_values, type: :boolean, default: false,
|
|
15
|
+
desc: "Whether to hide config values or not"
|
|
14
16
|
def web
|
|
15
|
-
|
|
16
|
-
host = options["host"]
|
|
17
|
-
threads = options["threads"]
|
|
18
|
-
verbose = options["verbose"]
|
|
19
|
-
worker_timeout = options["worker_timeout"]
|
|
20
|
-
|
|
17
|
+
Mihari.config.hide_config_values = options["hide_config_values"]
|
|
21
18
|
# set rack env as production
|
|
22
19
|
ENV["RACK_ENV"] ||= "production"
|
|
23
|
-
|
|
24
|
-
|
|
20
|
+
Mihari::App.run!(port: options["port"], host: options["host"], threads: options["threads"],
|
|
21
|
+
verbose: options["verbose"], worker_timeout: options["worker_timeout"])
|
|
25
22
|
end
|
|
26
23
|
end
|
|
27
24
|
end
|
data/lib/mihari/emitters/misp.rb
CHANGED
|
@@ -45,10 +45,10 @@ module Mihari
|
|
|
45
45
|
|
|
46
46
|
client.create_event({
|
|
47
47
|
Event: {
|
|
48
|
-
info: rule.title
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
48
|
+
info: rule.title,
|
|
49
|
+
Attribute: artifacts.map { |artifact| build_attribute(artifact) },
|
|
50
|
+
Tag: rule.tags.map { |tag| { name: tag } }
|
|
51
|
+
}
|
|
52
52
|
})
|
|
53
53
|
end
|
|
54
54
|
|
|
@@ -12,11 +12,12 @@ module Mihari
|
|
|
12
12
|
expose :data_type, documentation: { type: String, required: true }, as: :dataType
|
|
13
13
|
expose :source, documentation: { type: String, required: true }
|
|
14
14
|
expose :tags, documentation: { type: String, is_array: true }
|
|
15
|
-
|
|
16
|
-
expose :metadata, documentation: { type: Hash }
|
|
17
15
|
end
|
|
18
16
|
|
|
19
17
|
class Artifact < BaseArtifact
|
|
18
|
+
# NOTE: do not define metadata in BaseArtifact since metadata can be relatively big
|
|
19
|
+
expose :metadata, documentation: { type: Hash }
|
|
20
|
+
|
|
20
21
|
expose :autonomous_system, using: Entities::AutonomousSystem,
|
|
21
22
|
documentation: { type: Entities::AutonomousSystem, required: false }, as: :autonomousSystem
|
|
22
23
|
expose :geolocation, using: Entities::Geolocation, documentation: { type: Entities::Geolocation, required: false }
|
|
@@ -23,7 +23,9 @@ module Mihari
|
|
|
23
23
|
return nil if configuration_keys.empty?
|
|
24
24
|
|
|
25
25
|
configuration_keys.map do |key|
|
|
26
|
-
|
|
26
|
+
value = Mihari.config.send(key)
|
|
27
|
+
value = "REDACTED" if value && Mihari.config.hide_config_values
|
|
28
|
+
{ key: key.upcase, value: value }
|
|
27
29
|
end
|
|
28
30
|
end
|
|
29
31
|
|
data/lib/mihari/models/alert.rb
CHANGED
|
@@ -48,22 +48,29 @@ module Mihari
|
|
|
48
48
|
#
|
|
49
49
|
# @param [Structs::Filters::Alert::SearchFilter] filter
|
|
50
50
|
#
|
|
51
|
-
# @return [
|
|
51
|
+
# @return [Array<Integer>]
|
|
52
52
|
#
|
|
53
|
-
def
|
|
53
|
+
def get_artifact_ids_by_filter(filter)
|
|
54
54
|
artifact_ids = []
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
artifact = artifact.where(dns_records: { value: filter.dns_record }) if filter.dns_record
|
|
59
|
-
artifact = artifact.where(reverse_dns_names: { name: filter.reverse_dns_name }) if filter.reverse_dns_name
|
|
60
|
-
# get artifact ids if there is any valid filter for artifact
|
|
61
|
-
if filter.valid_artifact_filters?
|
|
55
|
+
|
|
56
|
+
if filter.artifact_data
|
|
57
|
+
artifact = Artifact.where(data: filter.artifact_data)
|
|
62
58
|
artifact_ids = artifact.pluck(:id)
|
|
63
59
|
# set invalid ID if nothing is matched with the filters
|
|
64
60
|
artifact_ids = [-1] if artifact_ids.empty?
|
|
65
61
|
end
|
|
66
62
|
|
|
63
|
+
artifact_ids
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
#
|
|
67
|
+
# @param [Structs::Filters::Alert::SearchFilter] filter
|
|
68
|
+
#
|
|
69
|
+
# @return [Mihari::Alert]
|
|
70
|
+
#
|
|
71
|
+
def build_relation(filter)
|
|
72
|
+
artifact_ids = get_artifact_ids_by_filter(filter)
|
|
73
|
+
|
|
67
74
|
relation = self
|
|
68
75
|
relation = relation.includes(:artifacts, :tags)
|
|
69
76
|
|
|
@@ -71,9 +78,6 @@ module Mihari
|
|
|
71
78
|
relation = relation.where(tags: { name: filter.tag_name }) if filter.tag_name
|
|
72
79
|
|
|
73
80
|
relation = relation.where(rule_id: filter.rule_id) if filter.rule_id
|
|
74
|
-
relation = relation.where(title: filter.title) if filter.title
|
|
75
|
-
|
|
76
|
-
relation = relation.where("description LIKE ?", "%#{filter.description}%") if filter.description
|
|
77
81
|
|
|
78
82
|
relation = relation.where("alerts.created_at >= ?", filter.from_at) if filter.from_at
|
|
79
83
|
relation = relation.where("alerts.created_at <= ?", filter.to_at) if filter.to_at
|
data/lib/mihari/models/rule.rb
CHANGED
|
@@ -67,8 +67,7 @@ module Mihari
|
|
|
67
67
|
|
|
68
68
|
relation = relation.where(alerts: { tags: { name: filter.tag_name } }) if filter.tag_name
|
|
69
69
|
|
|
70
|
-
relation = relation.where(title
|
|
71
|
-
|
|
70
|
+
relation = relation.where("rules.title LIKE ?", "%#{filter.title}%") if filter.title
|
|
72
71
|
relation = relation.where("rules.description LIKE ?", "%#{filter.description}%") if filter.description
|
|
73
72
|
|
|
74
73
|
relation = relation.where("rules.created_at >= ?", filter.from_at) if filter.from_at
|
data/lib/mihari/schemas/rule.rb
CHANGED
|
@@ -33,6 +33,7 @@ module Mihari
|
|
|
33
33
|
optional(:falsepositives).value(array[:string]).default([])
|
|
34
34
|
|
|
35
35
|
optional(:artifact_lifetime).value(:integer)
|
|
36
|
+
optional(:artifact_ttl).value(:integer)
|
|
36
37
|
|
|
37
38
|
before(:key_coercer) do |result|
|
|
38
39
|
# it looks like that dry-schema v1.9.1 has an issue with setting an array of schemas as a default value
|
|
@@ -6,19 +6,10 @@ module Mihari
|
|
|
6
6
|
module Alert
|
|
7
7
|
class SearchFilter < Dry::Struct
|
|
8
8
|
attribute? :artifact_data, Types::String.optional
|
|
9
|
-
attribute? :description, Types::String.optional
|
|
10
9
|
attribute? :rule_id, Types::String.optional
|
|
11
10
|
attribute? :tag_name, Types::String.optional
|
|
12
|
-
attribute? :title, Types::String.optional
|
|
13
11
|
attribute? :from_at, Types::DateTime.optional
|
|
14
12
|
attribute? :to_at, Types::DateTime.optional
|
|
15
|
-
attribute? :asn, Types::Int.optional
|
|
16
|
-
attribute? :dns_record, Types::String.optional
|
|
17
|
-
attribute? :reverse_dns_name, Types::String.optional
|
|
18
|
-
|
|
19
|
-
def valid_artifact_filters?
|
|
20
|
-
!(artifact_data || asn || dns_record || reverse_dns_name).nil?
|
|
21
|
-
end
|
|
22
13
|
end
|
|
23
14
|
|
|
24
15
|
class SearchFilterWithPagination < SearchFilter
|
|
@@ -28,15 +19,10 @@ module Mihari
|
|
|
28
19
|
def without_pagination
|
|
29
20
|
SearchFilter.new(
|
|
30
21
|
artifact_data: artifact_data,
|
|
31
|
-
description: description,
|
|
32
22
|
from_at: from_at,
|
|
33
23
|
rule_id: rule_id,
|
|
34
24
|
tag_name: tag_name,
|
|
35
|
-
|
|
36
|
-
to_at: to_at,
|
|
37
|
-
asn: asn,
|
|
38
|
-
dns_record: dns_record,
|
|
39
|
-
reverse_dns_name: reverse_dns_name
|
|
25
|
+
to_at: to_at
|
|
40
26
|
)
|
|
41
27
|
end
|
|
42
28
|
end
|
data/lib/mihari/structs/rule.rb
CHANGED
data/lib/mihari/version.rb
CHANGED
data/lib/mihari/web/app.rb
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "launchy"
|
|
4
|
+
|
|
4
5
|
require "rack"
|
|
5
|
-
require "
|
|
6
|
-
require "rack/handler/puma"
|
|
6
|
+
require "rackup"
|
|
7
7
|
require "rack/cors"
|
|
8
8
|
|
|
9
|
+
require "rack/handler/puma"
|
|
10
|
+
|
|
9
11
|
require "grape-swagger"
|
|
10
12
|
require "grape-swagger-entity"
|
|
11
13
|
|
|
@@ -18,7 +20,7 @@ module Mihari
|
|
|
18
20
|
class App
|
|
19
21
|
def initialize
|
|
20
22
|
@filenames = ["", ".html", "index.html", "/index.html"]
|
|
21
|
-
@rack_static =
|
|
23
|
+
@rack_static = Rack::Static.new(
|
|
22
24
|
-> { [404, {}, []] },
|
|
23
25
|
root: File.expand_path("./public", __dir__),
|
|
24
26
|
urls: ["/"]
|
|
@@ -50,14 +52,14 @@ module Mihari
|
|
|
50
52
|
# TODO: is this the best way?
|
|
51
53
|
_min_thread, max_thread = threads.split(":")
|
|
52
54
|
ENV["PARALLEL_PROCESSOR_COUNT"] = max_thread if ENV["PARALLEL_PROCESSOR_COUNT"].nil?
|
|
53
|
-
|
|
55
|
+
Rackup::Handler::Puma.run(
|
|
54
56
|
instance,
|
|
55
57
|
Port: port,
|
|
56
58
|
Host: host,
|
|
57
59
|
Threads: threads,
|
|
58
60
|
Verbose: verbose,
|
|
59
61
|
worker_timeout: worker_timeout
|
|
60
|
-
) do |
|
|
62
|
+
) do |_|
|
|
61
63
|
Launchy.open(url) if ENV["RACK_ENV"] != "development"
|
|
62
64
|
rescue Launchy::CommandNotFoundError
|
|
63
65
|
# ref. https://github.com/ninoseki/mihari/issues/477
|
|
@@ -11,48 +11,35 @@ module Mihari
|
|
|
11
11
|
summary: "Search alerts"
|
|
12
12
|
}
|
|
13
13
|
params do
|
|
14
|
-
optional :page, type: Integer
|
|
14
|
+
optional :page, type: Integer, default: 1
|
|
15
|
+
optional :limit, type: Integer, default: 10
|
|
15
16
|
|
|
16
17
|
optional :artifact, type: String
|
|
17
|
-
optional :description, type: String
|
|
18
18
|
optional :rule_id, type: String
|
|
19
19
|
optional :tag, type: String
|
|
20
|
-
optional :title, type: String
|
|
21
20
|
|
|
22
21
|
optional :fromAt, type: DateTime
|
|
23
22
|
optional :toAt, type: DateTime
|
|
24
|
-
|
|
25
|
-
optional :asn, type: Integer
|
|
26
|
-
optional :dnsRecord, type: String
|
|
27
|
-
optional :reverseDnsName, type: String
|
|
28
23
|
end
|
|
29
24
|
get "/" do
|
|
30
25
|
filter = params.to_h.to_snake_keys
|
|
31
26
|
|
|
32
|
-
# set page & limit
|
|
33
|
-
page = filter["page"] || 1
|
|
34
|
-
filter["page"] = page.to_i
|
|
35
|
-
|
|
36
|
-
limit = 10
|
|
37
|
-
filter["limit"] = 10
|
|
38
|
-
|
|
39
27
|
# normalize keys
|
|
40
28
|
filter["artifact_data"] = filter["artifact"]
|
|
41
29
|
filter["tag_name"] = filter["tag"]
|
|
42
|
-
|
|
43
30
|
# symbolize hash keys
|
|
44
31
|
filter = filter.to_h.symbolize_keys
|
|
45
32
|
|
|
46
|
-
|
|
47
|
-
alerts = Mihari::Alert.search(
|
|
48
|
-
total = Mihari::Alert.count(
|
|
33
|
+
search_filter_with_pagination = Structs::Filters::Alert::SearchFilterWithPagination.new(**filter)
|
|
34
|
+
alerts = Mihari::Alert.search(search_filter_with_pagination)
|
|
35
|
+
total = Mihari::Alert.count(search_filter_with_pagination.without_pagination)
|
|
49
36
|
|
|
50
37
|
present(
|
|
51
38
|
{
|
|
52
39
|
alerts: alerts,
|
|
53
40
|
total: total,
|
|
54
|
-
current_page: page,
|
|
55
|
-
page_size: limit
|
|
41
|
+
current_page: filter[:page].to_i,
|
|
42
|
+
page_size: filter[:limit].to_i
|
|
56
43
|
},
|
|
57
44
|
with: Entities::AlertsWithPagination
|
|
58
45
|
)
|
|
@@ -21,7 +21,8 @@ module Mihari
|
|
|
21
21
|
summary: "Search rules"
|
|
22
22
|
}
|
|
23
23
|
params do
|
|
24
|
-
optional :page, type: Integer
|
|
24
|
+
optional :page, type: Integer, default: 1
|
|
25
|
+
optional :limit, type: Integer, default: 10
|
|
25
26
|
|
|
26
27
|
optional :title, type: String
|
|
27
28
|
optional :description, type: String
|
|
@@ -33,16 +34,8 @@ module Mihari
|
|
|
33
34
|
get "/" do
|
|
34
35
|
filter = params.to_h.to_snake_keys
|
|
35
36
|
|
|
36
|
-
# set page & limit
|
|
37
|
-
page = filter["page"] || 1
|
|
38
|
-
filter["page"] = page.to_i
|
|
39
|
-
|
|
40
|
-
limit = 10
|
|
41
|
-
filter["limit"] = 10
|
|
42
|
-
|
|
43
37
|
# normalize keys
|
|
44
38
|
filter["tag_name"] = filter["tag"]
|
|
45
|
-
|
|
46
39
|
# symbolize hash keys
|
|
47
40
|
filter = filter.to_h.symbolize_keys
|
|
48
41
|
|
|
@@ -53,8 +46,8 @@ module Mihari
|
|
|
53
46
|
present(
|
|
54
47
|
{ rules: rules,
|
|
55
48
|
total: total,
|
|
56
|
-
current_page: page,
|
|
57
|
-
page_size: limit },
|
|
49
|
+
current_page: filter[:page].to_i,
|
|
50
|
+
page_size: filter[:limit].to_i },
|
|
58
51
|
with: Entities::RulesWithPagination
|
|
59
52
|
)
|
|
60
53
|
end
|
|
Binary file
|
|
Binary file
|
data/lib/mihari/web/public/assets/{fa-regular-400-12dea17b.ttf → fa-regular-400-528d022d.ttf}
RENAMED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|