mihari 3.4.0 → 3.6.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitmodules +3 -0
- data/README.md +2 -0
- data/Steepfile +32 -0
- data/config.ru +1 -0
- data/lib/mihari/analyzers/base.rb +39 -11
- data/lib/mihari/analyzers/binaryedge.rb +13 -0
- data/lib/mihari/analyzers/censys.rb +42 -9
- data/lib/mihari/analyzers/circl.rb +15 -0
- data/lib/mihari/analyzers/crtsh.rb +5 -0
- data/lib/mihari/analyzers/dnpedia.rb +5 -0
- data/lib/mihari/analyzers/dnstwister.rb +17 -0
- data/lib/mihari/analyzers/onyphe.rb +50 -9
- data/lib/mihari/analyzers/otx.rb +20 -0
- data/lib/mihari/analyzers/passivetotal.rb +25 -0
- data/lib/mihari/analyzers/pulsedive.rb +10 -0
- data/lib/mihari/analyzers/rule.rb +18 -0
- data/lib/mihari/analyzers/securitytrails.rb +25 -0
- data/lib/mihari/analyzers/shodan.rb +39 -5
- data/lib/mihari/analyzers/spyse.rb +20 -0
- data/lib/mihari/analyzers/urlscan.rb +10 -0
- data/lib/mihari/analyzers/virustotal.rb +20 -0
- data/lib/mihari/analyzers/zoomeye.rb +38 -0
- data/lib/mihari/cli/analyzer.rb +1 -0
- data/lib/mihari/cli/base.rb +0 -2
- data/lib/mihari/commands/init.rb +4 -4
- data/lib/mihari/commands/search.rb +1 -0
- data/lib/mihari/commands/web.rb +1 -0
- data/lib/mihari/{constraints.rb → constants.rb} +0 -0
- data/lib/mihari/database.rb +42 -3
- data/lib/mihari/emitters/base.rb +1 -1
- data/lib/mihari/emitters/misp.rb +38 -5
- data/lib/mihari/emitters/slack.rb +20 -2
- data/lib/mihari/emitters/the_hive.rb +16 -3
- data/lib/mihari/emitters/webhook.rb +18 -3
- data/lib/mihari/mixins/disallowed_data_value.rb +1 -1
- data/lib/mihari/models/alert.rb +28 -10
- data/lib/mihari/models/artifact.rb +55 -0
- data/lib/mihari/models/autonomous_system.rb +9 -0
- data/lib/mihari/models/dns.rb +53 -0
- data/lib/mihari/models/geolocation.rb +9 -0
- data/lib/mihari/models/reverse_dns.rb +24 -0
- data/lib/mihari/models/whois.rb +119 -0
- data/lib/mihari/schemas/configuration.rb +1 -0
- data/lib/mihari/schemas/rule.rb +2 -15
- data/lib/mihari/serializers/alert.rb +6 -4
- data/lib/mihari/serializers/artifact.rb +11 -2
- data/lib/mihari/serializers/autonomous_system.rb +9 -0
- data/lib/mihari/serializers/dns.rb +11 -0
- data/lib/mihari/serializers/geolocation.rb +11 -0
- data/lib/mihari/serializers/reverse_dns.rb +11 -0
- data/lib/mihari/serializers/tag.rb +4 -2
- data/lib/mihari/serializers/whois.rb +11 -0
- data/lib/mihari/structs/censys.rb +92 -0
- data/lib/mihari/structs/onyphe.rb +47 -0
- data/lib/mihari/structs/shodan.rb +53 -0
- data/lib/mihari/type_checker.rb +9 -9
- data/lib/mihari/types.rb +21 -0
- data/lib/mihari/version.rb +1 -1
- data/lib/mihari/web/app.rb +2 -0
- data/lib/mihari/web/controllers/alerts_controller.rb +3 -4
- data/lib/mihari/web/controllers/artifacts_controller.rb +46 -2
- data/lib/mihari/web/controllers/ip_address_controller.rb +36 -0
- data/lib/mihari/web/controllers/sources_controller.rb +2 -2
- data/lib/mihari/web/controllers/tags_controller.rb +3 -1
- data/lib/mihari/web/public/index.html +1 -1
- data/lib/mihari/web/public/redoc-static.html +12 -10
- data/lib/mihari/web/public/static/fonts/fa-brands-400.1a575a41.woff +0 -0
- data/lib/mihari/web/public/static/fonts/fa-brands-400.513aa607.ttf +0 -0
- data/lib/mihari/web/public/static/fonts/fa-brands-400.592643a8.eot +0 -0
- data/lib/mihari/web/public/static/fonts/fa-brands-400.ed311c7a.woff2 +0 -0
- data/lib/mihari/web/public/static/fonts/fa-regular-400.766913e6.ttf +0 -0
- data/lib/mihari/web/public/static/fonts/fa-regular-400.b0e2db3b.eot +0 -0
- data/lib/mihari/web/public/static/fonts/fa-regular-400.b91d376b.woff2 +0 -0
- data/lib/mihari/web/public/static/fonts/fa-regular-400.d1d7e3b4.woff +0 -0
- data/lib/mihari/web/public/static/fonts/fa-solid-900.0c6bfc66.eot +0 -0
- data/lib/mihari/web/public/static/fonts/fa-solid-900.b9625119.ttf +0 -0
- data/lib/mihari/web/public/static/fonts/fa-solid-900.d745348d.woff +0 -0
- data/lib/mihari/web/public/static/fonts/fa-solid-900.d824df7e.woff2 +0 -0
- data/lib/mihari/web/public/static/img/fa-brands-400.1d5619cd.svg +3717 -0
- data/lib/mihari/web/public/static/img/fa-regular-400.c5d109be.svg +801 -0
- data/lib/mihari/web/public/static/img/fa-solid-900.37bc7099.svg +5034 -0
- data/lib/mihari/web/public/static/js/app.8e3e5150.js +36 -0
- data/lib/mihari/web/public/static/js/app.8e3e5150.js.map +1 -0
- data/lib/mihari/web/public/static/js/app.b5914c39.js +36 -0
- data/lib/mihari/web/public/static/js/app.b5914c39.js.map +1 -0
- data/lib/mihari.rb +25 -4
- data/mihari.gemspec +10 -2
- data/sig/lib/mihari/analyzers/base.rbs +99 -0
- data/sig/lib/mihari/analyzers/basic.rbs +17 -0
- data/sig/lib/mihari/analyzers/binaryedge.rbs +25 -0
- data/sig/lib/mihari/analyzers/censys.rbs +38 -0
- data/sig/lib/mihari/analyzers/circl.rbs +29 -0
- data/sig/lib/mihari/analyzers/crtsh.rbs +19 -0
- data/sig/lib/mihari/analyzers/dnpedia.rbs +18 -0
- data/sig/lib/mihari/analyzers/dnstwister.rbs +27 -0
- data/sig/lib/mihari/analyzers/onyphe.rbs +33 -0
- data/sig/lib/mihari/analyzers/otx.rbs +33 -0
- data/sig/lib/mihari/analyzers/passivetotal.rbs +33 -0
- data/sig/lib/mihari/analyzers/pulsedive.rbs +27 -0
- data/sig/lib/mihari/analyzers/rule.rbs +68 -0
- data/sig/lib/mihari/analyzers/securitytrails.rbs +33 -0
- data/sig/lib/mihari/analyzers/shodan.rbs +33 -0
- data/sig/lib/mihari/analyzers/spyse.rbs +29 -0
- data/sig/lib/mihari/analyzers/urlscan.rbs +28 -0
- data/sig/lib/mihari/analyzers/virustotal.rbs +31 -0
- data/sig/lib/mihari/analyzers/zoomeye.rbs +33 -0
- data/sig/lib/mihari/cli/analyzer.rbs +39 -0
- data/sig/lib/mihari/cli/base.rbs +11 -0
- data/sig/lib/mihari/cli/init.rbs +7 -0
- data/sig/lib/mihari/cli/main.rbs +9 -0
- data/sig/lib/mihari/cli/mixins/utils.rbs +50 -0
- data/sig/lib/mihari/cli/validator.rbs +7 -0
- data/sig/lib/mihari/commands/binaryedge.rbs +7 -0
- data/sig/lib/mihari/commands/censys.rbs +7 -0
- data/sig/lib/mihari/commands/circl.rbs +7 -0
- data/sig/lib/mihari/commands/crtsh.rbs +7 -0
- data/sig/lib/mihari/commands/dnpedia.rbs +7 -0
- data/sig/lib/mihari/commands/dnstwister.rbs +7 -0
- data/sig/lib/mihari/commands/init.rbs +11 -0
- data/sig/lib/mihari/commands/json.rbs +7 -0
- data/sig/lib/mihari/commands/onyphe.rbs +7 -0
- data/sig/lib/mihari/commands/otx.rbs +7 -0
- data/sig/lib/mihari/commands/passivetotal.rbs +7 -0
- data/sig/lib/mihari/commands/pulsedive.rbs +7 -0
- data/sig/lib/mihari/commands/search.rbs +35 -0
- data/sig/lib/mihari/commands/securitytrails.rbs +7 -0
- data/sig/lib/mihari/commands/shodan.rbs +7 -0
- data/sig/lib/mihari/commands/spyse.rbs +7 -0
- data/sig/lib/mihari/commands/urlscan.rbs +7 -0
- data/sig/lib/mihari/commands/validator.rbs +11 -0
- data/sig/lib/mihari/commands/virustotal.rbs +7 -0
- data/sig/lib/mihari/commands/web.rbs +7 -0
- data/sig/lib/mihari/commands/zoomeye.rbs +7 -0
- data/sig/lib/mihari/constants.rbs +3 -0
- data/sig/lib/mihari/database.rbs +25 -0
- data/sig/lib/mihari/emitters/base.rbs +18 -0
- data/sig/lib/mihari/emitters/database.rbs +9 -0
- data/sig/lib/mihari/emitters/misp.rbs +28 -0
- data/sig/lib/mihari/emitters/slack.rbs +58 -0
- data/sig/lib/mihari/emitters/stdout.rbs +9 -0
- data/sig/lib/mihari/emitters/the_hive.rbs +24 -0
- data/sig/lib/mihari/emitters/webhook.rbs +20 -0
- data/sig/lib/mihari/errors.rbs +10 -0
- data/sig/lib/mihari/mixins/configurable.rbs +26 -0
- data/sig/lib/mihari/mixins/configuration.rbs +45 -0
- data/sig/lib/mihari/mixins/disallowed_data_value.rbs +25 -0
- data/sig/lib/mihari/mixins/hash.rbs +14 -0
- data/sig/lib/mihari/mixins/refang.rbs +14 -0
- data/sig/lib/mihari/mixins/retriable.rbs +15 -0
- data/sig/lib/mihari/mixins/rule.rbs +41 -0
- data/sig/lib/mihari/models/alert.rbs +46 -0
- data/sig/lib/mihari/models/artifact.rbs +54 -0
- data/sig/lib/mihari/models/autonomous_system.rbs +5 -0
- data/sig/lib/mihari/models/dns.rbs +19 -0
- data/sig/lib/mihari/models/geolocation.rbs +6 -0
- data/sig/lib/mihari/models/reverse_dns.rbs +14 -0
- data/sig/lib/mihari/models/tag.rbs +5 -0
- data/sig/lib/mihari/models/tagging.rbs +4 -0
- data/sig/lib/mihari/models/whois.rbs +66 -0
- data/sig/lib/mihari/notifiers/base.rbs +18 -0
- data/sig/lib/mihari/notifiers/exception_notifier.rbs +75 -0
- data/sig/lib/mihari/notifiers/slack.rbs +50 -0
- data/sig/lib/mihari/status.rbs +25 -0
- data/sig/lib/mihari/structs/censys.rbs +50 -0
- data/sig/lib/mihari/structs/onyphe.rbs +25 -0
- data/sig/lib/mihari/structs/shodan.rbs +28 -0
- data/sig/lib/mihari/type_checker.rbs +48 -0
- data/sig/lib/mihari/types.rbs +17 -0
- data/sig/lib/mihari/version.rbs +3 -0
- data/sig/lib/mihari/web/app.rbs +5 -0
- data/sig/lib/mihari.rbs +57 -0
- metadata +240 -8
@@ -0,0 +1,92 @@
|
|
1
|
+
require "json"
|
2
|
+
require "dry/struct"
|
3
|
+
|
4
|
+
module Mihari
|
5
|
+
module Structs
|
6
|
+
module Censys
|
7
|
+
class AutonomousSystem < Dry::Struct
|
8
|
+
attribute :asn, Types::Int
|
9
|
+
|
10
|
+
def self.from_dynamic!(d)
|
11
|
+
d = Types::Hash[d]
|
12
|
+
new(
|
13
|
+
asn: d.fetch("asn")
|
14
|
+
)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class Location < Dry::Struct
|
19
|
+
attribute :country, Types::String.optional
|
20
|
+
attribute :country_code, Types::String.optional
|
21
|
+
|
22
|
+
def self.from_dynamic!(d)
|
23
|
+
d = Types::Hash[d]
|
24
|
+
new(
|
25
|
+
country: d["country"],
|
26
|
+
country_code: d["country_code"]
|
27
|
+
)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class Hit < Dry::Struct
|
32
|
+
attribute :ip, Types::String
|
33
|
+
attribute :location, Location
|
34
|
+
attribute :autonomous_system, AutonomousSystem
|
35
|
+
|
36
|
+
def self.from_dynamic!(d)
|
37
|
+
d = Types::Hash[d]
|
38
|
+
new(
|
39
|
+
ip: d.fetch("ip"),
|
40
|
+
location: Location.from_dynamic!(d.fetch("location")),
|
41
|
+
autonomous_system: AutonomousSystem.from_dynamic!(d.fetch("autonomous_system"))
|
42
|
+
)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
class Links < Dry::Struct
|
47
|
+
attribute :next, Types::String
|
48
|
+
attribute :prev, Types::String
|
49
|
+
|
50
|
+
def self.from_dynamic!(d)
|
51
|
+
d = Types::Hash[d]
|
52
|
+
new(
|
53
|
+
next: d.fetch("next"),
|
54
|
+
prev: d.fetch("prev")
|
55
|
+
)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
class Result < Dry::Struct
|
60
|
+
attribute :query, Types::String
|
61
|
+
attribute :total, Types::Int
|
62
|
+
attribute :hits, Types.Array(Hit)
|
63
|
+
attribute :links, Links
|
64
|
+
|
65
|
+
def self.from_dynamic!(d)
|
66
|
+
d = Types::Hash[d]
|
67
|
+
new(
|
68
|
+
query: d.fetch("query"),
|
69
|
+
total: d.fetch("total"),
|
70
|
+
hits: d.fetch("hits", []).map { |x| Hit.from_dynamic!(x) },
|
71
|
+
links: Links.from_dynamic!(d.fetch("links"))
|
72
|
+
)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
class Response < Dry::Struct
|
77
|
+
attribute :code, Types::Int
|
78
|
+
attribute :status, Types::String
|
79
|
+
attribute :result, Result
|
80
|
+
|
81
|
+
def self.from_dynamic!(d)
|
82
|
+
d = Types::Hash[d]
|
83
|
+
new(
|
84
|
+
code: d.fetch("code"),
|
85
|
+
status: d.fetch("status"),
|
86
|
+
result: Result.from_dynamic!(d.fetch("result"))
|
87
|
+
)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require "json"
|
2
|
+
require "dry/struct"
|
3
|
+
|
4
|
+
module Mihari
|
5
|
+
module Structs
|
6
|
+
module Onyphe
|
7
|
+
class Result < Dry::Struct
|
8
|
+
attribute :asn, Types::String
|
9
|
+
attribute :country_code, Types::String.optional
|
10
|
+
attribute :ip, Types::String
|
11
|
+
|
12
|
+
def self.from_dynamic!(d)
|
13
|
+
d = Types::Hash[d]
|
14
|
+
new(
|
15
|
+
asn: d.fetch("asn"),
|
16
|
+
ip: d.fetch("ip"),
|
17
|
+
# Onyphe's country = 2-letter country code
|
18
|
+
country_code: d["country"]
|
19
|
+
)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class Response < Dry::Struct
|
24
|
+
attribute :count, Types::Int
|
25
|
+
attribute :error, Types::Int
|
26
|
+
attribute :max_page, Types::Int
|
27
|
+
attribute :page, Types::String
|
28
|
+
attribute :results, Types.Array(Result)
|
29
|
+
attribute :status, Types::String
|
30
|
+
attribute :total, Types::Int
|
31
|
+
|
32
|
+
def self.from_dynamic!(d)
|
33
|
+
d = Types::Hash[d]
|
34
|
+
new(
|
35
|
+
count: d.fetch("count"),
|
36
|
+
error: d.fetch("error"),
|
37
|
+
max_page: d.fetch("max_page"),
|
38
|
+
page: d.fetch("page"),
|
39
|
+
results: d.fetch("results").map { |x| Result.from_dynamic!(x) },
|
40
|
+
status: d.fetch("status"),
|
41
|
+
total: d.fetch("total")
|
42
|
+
)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require "json"
|
2
|
+
require "dry/struct"
|
3
|
+
|
4
|
+
module Mihari
|
5
|
+
module Structs
|
6
|
+
module Shodan
|
7
|
+
class Location < Dry::Struct
|
8
|
+
attribute :country_code, Types::String
|
9
|
+
attribute :country_name, Types::String
|
10
|
+
|
11
|
+
def self.from_dynamic!(d)
|
12
|
+
d = Types::Hash[d]
|
13
|
+
new(
|
14
|
+
country_code: d.fetch("country_code"),
|
15
|
+
country_name: d.fetch("country_name")
|
16
|
+
)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class Match < Dry::Struct
|
21
|
+
attribute :asn, Types::String
|
22
|
+
attribute :hostnames, Types.Array(Types::String)
|
23
|
+
attribute :location, Location
|
24
|
+
attribute :domains, Types.Array(Types::String)
|
25
|
+
attribute :ip_str, Types::String
|
26
|
+
|
27
|
+
def self.from_dynamic!(d)
|
28
|
+
d = Types::Hash[d]
|
29
|
+
new(
|
30
|
+
asn: d.fetch("asn"),
|
31
|
+
hostnames: d.fetch("hostnames"),
|
32
|
+
location: Location.from_dynamic!(d.fetch("location")),
|
33
|
+
domains: d.fetch("domains"),
|
34
|
+
ip_str: d.fetch("ip_str")
|
35
|
+
)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class Result < Dry::Struct
|
40
|
+
attribute :matches, Types.Array(Match)
|
41
|
+
attribute :total, Types::Int
|
42
|
+
|
43
|
+
def self.from_dynamic!(d)
|
44
|
+
d = Types::Hash[d]
|
45
|
+
new(
|
46
|
+
matches: d.fetch("matches", []).map { |x| Match.from_dynamic!(x) },
|
47
|
+
total: d.fetch("total")
|
48
|
+
)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/lib/mihari/type_checker.rb
CHANGED
@@ -18,12 +18,12 @@ module Mihari
|
|
18
18
|
raise ArgumentError if data.is_a?(Hash)
|
19
19
|
end
|
20
20
|
|
21
|
-
# @return [
|
21
|
+
# @return [Boolean]
|
22
22
|
def hash?
|
23
23
|
md5? || sha1? || sha256? || sha512?
|
24
24
|
end
|
25
25
|
|
26
|
-
# @return [
|
26
|
+
# @return [Boolean]
|
27
27
|
def ip?
|
28
28
|
IPAddr.new data
|
29
29
|
true
|
@@ -31,7 +31,7 @@ module Mihari
|
|
31
31
|
false
|
32
32
|
end
|
33
33
|
|
34
|
-
# @return [
|
34
|
+
# @return [Boolean]
|
35
35
|
def domain?
|
36
36
|
uri = Addressable::URI.parse("http://#{data}")
|
37
37
|
uri.host == data && PublicSuffix.valid?(uri.host)
|
@@ -39,7 +39,7 @@ module Mihari
|
|
39
39
|
false
|
40
40
|
end
|
41
41
|
|
42
|
-
# @return [
|
42
|
+
# @return [Boolean]
|
43
43
|
def url?
|
44
44
|
uri = Addressable::URI.parse(data)
|
45
45
|
uri.scheme && uri.host && uri.path && PublicSuffix.valid?(uri.host)
|
@@ -47,7 +47,7 @@ module Mihari
|
|
47
47
|
false
|
48
48
|
end
|
49
49
|
|
50
|
-
# @return [
|
50
|
+
# @return [Boolean]
|
51
51
|
def mail?
|
52
52
|
EmailAddress.valid? data, host_validation: :syntax
|
53
53
|
end
|
@@ -83,22 +83,22 @@ module Mihari
|
|
83
83
|
|
84
84
|
private
|
85
85
|
|
86
|
-
# @return [
|
86
|
+
# @return [Boolean]
|
87
87
|
def md5?
|
88
88
|
data.match?(/^[A-Fa-f0-9]{32}$/)
|
89
89
|
end
|
90
90
|
|
91
|
-
# @return [
|
91
|
+
# @return [Boolean]
|
92
92
|
def sha1?
|
93
93
|
data.match?(/^[A-Fa-f0-9]{40}$/)
|
94
94
|
end
|
95
95
|
|
96
|
-
# @return [
|
96
|
+
# @return [Boolean]
|
97
97
|
def sha256?
|
98
98
|
data.match?(/^[A-Fa-f0-9]{64}$/)
|
99
99
|
end
|
100
100
|
|
101
|
-
# @return [
|
101
|
+
# @return [Boolean]
|
102
102
|
def sha512?
|
103
103
|
data.match?(/^[A-Fa-f0-9]{128}$/)
|
104
104
|
end
|
data/lib/mihari/types.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require "dry/types"
|
2
|
+
|
3
|
+
module Mihari
|
4
|
+
module Types
|
5
|
+
include Dry.Types()
|
6
|
+
|
7
|
+
Int = Strict::Integer
|
8
|
+
Nil = Strict::Nil
|
9
|
+
Hash = Strict::Hash
|
10
|
+
String = Strict::String
|
11
|
+
Double = Strict::Float | Strict::Integer
|
12
|
+
|
13
|
+
DataTypes = Types::String.enum(*ALLOWED_DATA_TYPES)
|
14
|
+
|
15
|
+
AnalyzerTypes = Types::String.enum(
|
16
|
+
"binaryedge", "censys", "circl", "dnpedia", "dnstwister",
|
17
|
+
"onyphe", "otx", "passivetotal", "pulsedive", "securitytrails",
|
18
|
+
"shodan", "virustotal"
|
19
|
+
)
|
20
|
+
end
|
21
|
+
end
|
data/lib/mihari/version.rb
CHANGED
data/lib/mihari/web/app.rb
CHANGED
@@ -14,6 +14,7 @@ require "mihari/web/controllers/analyzers_controller"
|
|
14
14
|
require "mihari/web/controllers/artifacts_controller"
|
15
15
|
require "mihari/web/controllers/command_controller"
|
16
16
|
require "mihari/web/controllers/config_controller"
|
17
|
+
require "mihari/web/controllers/ip_address_controller"
|
17
18
|
require "mihari/web/controllers/sources_controller"
|
18
19
|
require "mihari/web/controllers/tags_controller"
|
19
20
|
|
@@ -31,6 +32,7 @@ module Mihari
|
|
31
32
|
use Mihari::Controllers::ArtifactsController
|
32
33
|
use Mihari::Controllers::CommandController
|
33
34
|
use Mihari::Controllers::ConfigController
|
35
|
+
use Mihari::Controllers::IPAddressController
|
34
36
|
use Mihari::Controllers::SourcesController
|
35
37
|
use Mihari::Controllers::TagsController
|
36
38
|
|
@@ -26,9 +26,7 @@ module Mihari
|
|
26
26
|
title = params["title"]
|
27
27
|
|
28
28
|
from_at = params["from_at"] || params["fromAt"]
|
29
|
-
from_at = DateTime.parse(from_at) if from_at
|
30
29
|
to_at = params["to_at"] || params["toAt"]
|
31
|
-
to_at = DateTime.parse(to_at) if to_at
|
32
30
|
|
33
31
|
alerts = Mihari::Alert.search(
|
34
32
|
artifact_data: artifact_data,
|
@@ -55,8 +53,9 @@ module Mihari
|
|
55
53
|
end
|
56
54
|
|
57
55
|
delete "/api/alerts/:id" do
|
58
|
-
id
|
59
|
-
|
56
|
+
param :id, Integer, required: true
|
57
|
+
|
58
|
+
id = params["id"].to_i
|
60
59
|
|
61
60
|
begin
|
62
61
|
alert = Mihari::Alert.find(id)
|
@@ -3,9 +3,53 @@
|
|
3
3
|
module Mihari
|
4
4
|
module Controllers
|
5
5
|
class ArtifactsController < BaseController
|
6
|
+
get "/api/artifacts/:id" do
|
7
|
+
param :id, Integer, required: true
|
8
|
+
|
9
|
+
id = params["id"].to_i
|
10
|
+
|
11
|
+
begin
|
12
|
+
artifact = Mihari::Artifact.includes(
|
13
|
+
:autonomous_system,
|
14
|
+
:geolocation,
|
15
|
+
:whois_record,
|
16
|
+
:dns_records,
|
17
|
+
:reverse_dns_names
|
18
|
+
).find(id)
|
19
|
+
rescue ActiveRecord::RecordNotFound
|
20
|
+
status 404
|
21
|
+
|
22
|
+
return json({ message: "ID:#{id} is not found" })
|
23
|
+
end
|
24
|
+
|
25
|
+
# TODO: improve queries
|
26
|
+
alert_ids = Mihari::Artifact.where(data: artifact.data).pluck(:alert_id)
|
27
|
+
tag_ids = Mihari::Tagging.where(alert_id: alert_ids).pluck(:tag_id)
|
28
|
+
tag_names = Mihari::Tag.where(id: tag_ids).distinct.pluck(:name)
|
29
|
+
|
30
|
+
artifact_json = Serializers::ArtifactSerializer.new(artifact).as_json
|
31
|
+
|
32
|
+
# convert reverse DNS names into an array of string
|
33
|
+
# also change it as nil if it is empty
|
34
|
+
reverse_dns_names = (artifact_json[:reverse_dns_names] || []).filter_map { |v| v[:name] }
|
35
|
+
reverse_dns_names = nil if reverse_dns_names.empty?
|
36
|
+
artifact_json[:reverse_dns_names] = reverse_dns_names
|
37
|
+
|
38
|
+
# change DNS records as nil if it is empty
|
39
|
+
dns_records = artifact_json[:dns_records] || []
|
40
|
+
dns_records = nil if dns_records.empty?
|
41
|
+
artifact_json[:dns_records] = dns_records
|
42
|
+
|
43
|
+
# set tags
|
44
|
+
artifact_json[:tags] = tag_names
|
45
|
+
|
46
|
+
json artifact_json
|
47
|
+
end
|
48
|
+
|
6
49
|
delete "/api/artifacts/:id" do
|
7
|
-
id
|
8
|
-
|
50
|
+
param :id, Integer, required: true
|
51
|
+
|
52
|
+
id = params["id"].to_i
|
9
53
|
|
10
54
|
begin
|
11
55
|
alert = Mihari::Artifact.find(id)
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "http"
|
4
|
+
require "json"
|
5
|
+
|
6
|
+
module Mihari
|
7
|
+
module Controllers
|
8
|
+
class IPAddressController < BaseController
|
9
|
+
def query(ip)
|
10
|
+
headers = {}
|
11
|
+
token = Mihari.config.ipinfo_api_key
|
12
|
+
unless token.nil?
|
13
|
+
headers[:authorization] = "Bearer #{token}"
|
14
|
+
end
|
15
|
+
|
16
|
+
res = HTTP.headers(headers).get("https://ipinfo.io/#{ip}/json")
|
17
|
+
JSON.parse res.to_s
|
18
|
+
end
|
19
|
+
|
20
|
+
get "/api/ip_addresses/:ip" do
|
21
|
+
param :ip, String, required: true
|
22
|
+
|
23
|
+
ip = params["ip"].to_s
|
24
|
+
|
25
|
+
begin
|
26
|
+
data = query(ip)
|
27
|
+
json data
|
28
|
+
rescue HTTP::Error
|
29
|
+
status 404
|
30
|
+
|
31
|
+
json({ message: "IP:#{ip} is not found" })
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|