mihari 5.7.0 → 5.7.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -1
- data/lib/mihari/actor.rb +10 -4
- data/lib/mihari/cli/main.rb +2 -0
- data/lib/mihari/clients/base.rb +23 -1
- data/lib/mihari/clients/binaryedge.rb +1 -3
- data/lib/mihari/clients/censys.rb +1 -2
- data/lib/mihari/clients/crtsh.rb +2 -3
- data/lib/mihari/clients/dnstwister.rb +1 -2
- data/lib/mihari/clients/fofa.rb +1 -3
- data/lib/mihari/clients/greynoise.rb +1 -2
- data/lib/mihari/clients/hunterhow.rb +1 -2
- data/lib/mihari/clients/misp.rb +1 -2
- data/lib/mihari/clients/onyphe.rb +1 -2
- data/lib/mihari/clients/otx.rb +2 -14
- data/lib/mihari/clients/passivetotal.rb +3 -16
- data/lib/mihari/clients/publsedive.rb +2 -17
- data/lib/mihari/clients/securitytrails.rb +3 -25
- data/lib/mihari/clients/shodan.rb +1 -2
- data/lib/mihari/clients/the_hive.rb +1 -2
- data/lib/mihari/clients/urlscan.rb +1 -2
- data/lib/mihari/clients/virustotal.rb +3 -17
- data/lib/mihari/clients/zoomeye.rb +9 -19
- data/lib/mihari/commands/alert.rb +11 -9
- data/lib/mihari/commands/database.rb +4 -1
- data/lib/mihari/commands/mixins.rb +11 -0
- data/lib/mihari/commands/search.rb +13 -32
- data/lib/mihari/constants.rb +1 -1
- data/lib/mihari/database.rb +1 -1
- data/lib/mihari/enrichers/ipinfo.rb +1 -1
- data/lib/mihari/entities/tag.rb +1 -0
- data/lib/mihari/http.rb +13 -11
- data/lib/mihari/rule.rb +14 -0
- data/lib/mihari/service.rb +12 -2
- data/lib/mihari/services/alert_builder.rb +81 -8
- data/lib/mihari/services/alert_runner.rb +3 -10
- data/lib/mihari/services/rule_builder.rb +8 -10
- data/lib/mihari/services/rule_runner.rb +2 -25
- data/lib/mihari/structs/binaryedge.rb +9 -0
- data/lib/mihari/structs/censys.rb +0 -14
- data/lib/mihari/structs/fofa.rb +3 -0
- data/lib/mihari/structs/google_public_dns.rb +0 -4
- data/lib/mihari/structs/greynoise.rb +0 -6
- data/lib/mihari/structs/hunterhow.rb +0 -6
- data/lib/mihari/structs/ipinfo.rb +0 -2
- data/lib/mihari/structs/onyphe.rb +0 -4
- data/lib/mihari/structs/shodan.rb +0 -2
- data/lib/mihari/structs/urlscan.rb +0 -6
- data/lib/mihari/structs/virustotal_intelligence.rb +0 -8
- data/lib/mihari/version.rb +1 -1
- data/lib/mihari/web/app.rb +20 -17
- data/lib/mihari/web/endpoints/alerts.rb +75 -38
- data/lib/mihari/web/endpoints/artifacts.rb +60 -53
- data/lib/mihari/web/endpoints/ip_addresses.rb +19 -4
- data/lib/mihari/web/endpoints/rules.rb +132 -88
- data/lib/mihari/web/endpoints/tags.rb +15 -13
- data/lib/mihari/web/middleware/error_notification_adapter.rb +8 -3
- data/lib/mihari/web/public/assets/{index-821134e2.js → index-ec641cb0.js} +45 -44
- data/lib/mihari/web/public/index.html +1 -1
- data/lib/mihari/web/public/redoc-static.html +400 -400
- data/lib/mihari.rb +0 -2
- data/mihari.gemspec +5 -5
- data/mkdocs.yml +14 -7
- metadata +13 -140
- data/docs/alternatives.md +0 -5
- data/docs/analyzers/binaryedge.md +0 -26
- data/docs/analyzers/censys.md +0 -31
- data/docs/analyzers/circl.md +0 -37
- data/docs/analyzers/crtsh.md +0 -26
- data/docs/analyzers/dnstwister.md +0 -25
- data/docs/analyzers/feed.md +0 -73
- data/docs/analyzers/fofa.md +0 -31
- data/docs/analyzers/greynoise.md +0 -26
- data/docs/analyzers/hunterhow.md +0 -33
- data/docs/analyzers/index.md +0 -104
- data/docs/analyzers/onyphe.md +0 -26
- data/docs/analyzers/otx.md +0 -28
- data/docs/analyzers/passivetotal.md +0 -52
- data/docs/analyzers/pulsedive.md +0 -28
- data/docs/analyzers/securitytrails.md +0 -41
- data/docs/analyzers/shodan.md +0 -26
- data/docs/analyzers/urlscan.md +0 -28
- data/docs/analyzers/virustotal.md +0 -43
- data/docs/analyzers/virustotal_intelligence.md +0 -33
- data/docs/analyzers/zoomeye.md +0 -38
- data/docs/configuration.md +0 -35
- data/docs/emitters/database.md +0 -22
- data/docs/emitters/hive.md +0 -26
- data/docs/emitters/index.md +0 -36
- data/docs/emitters/misp.md +0 -21
- data/docs/emitters/slack.md +0 -21
- data/docs/emitters/webhook.md +0 -63
- data/docs/enrichers/google_public_dns.md +0 -19
- data/docs/enrichers/index.md +0 -35
- data/docs/enrichers/ipinfo.md +0 -26
- data/docs/enrichers/shodan.md +0 -22
- data/docs/enrichers/whois.md +0 -17
- data/docs/github_actions.md +0 -43
- data/docs/index.md +0 -11
- data/docs/installation.md +0 -31
- data/docs/requirements.md +0 -13
- data/docs/rule.md +0 -168
- data/docs/tags.md +0 -3
- data/docs/usage.md +0 -103
- data/frontend/.eslintrc.cjs +0 -22
- data/frontend/.gitignore +0 -31
- data/frontend/.prettierrc.json +0 -8
- data/frontend/README.md +0 -3
- data/frontend/env.d.ts +0 -5
- data/frontend/index.html +0 -21
- data/frontend/package-lock.json +0 -7219
- data/frontend/package.json +0 -67
- data/frontend/public/favicon.ico +0 -0
- data/frontend/scripts/swagger_doc_to_yaml.rb +0 -23
- data/frontend/src/App.vue +0 -27
- data/frontend/src/ace-config.ts +0 -6
- data/frontend/src/api-helper.ts +0 -111
- data/frontend/src/api.ts +0 -105
- data/frontend/src/components/ErrorMessage.vue +0 -31
- data/frontend/src/components/Loading.vue +0 -15
- data/frontend/src/components/Navbar.vue +0 -42
- data/frontend/src/components/Pagination.vue +0 -119
- data/frontend/src/components/alert/Alert.vue +0 -87
- data/frontend/src/components/alert/Alerts.vue +0 -63
- data/frontend/src/components/alert/AlertsWithPagination.vue +0 -90
- data/frontend/src/components/alert/AlertsWrapper.vue +0 -128
- data/frontend/src/components/alert/Form.vue +0 -169
- data/frontend/src/components/artifact/AS.vue +0 -23
- data/frontend/src/components/artifact/Artifact.vue +0 -287
- data/frontend/src/components/artifact/ArtifactTag.vue +0 -64
- data/frontend/src/components/artifact/ArtifactTags.vue +0 -29
- data/frontend/src/components/artifact/ArtifactWrapper.vue +0 -57
- data/frontend/src/components/artifact/CPEs.vue +0 -23
- data/frontend/src/components/artifact/DnsRecords.vue +0 -32
- data/frontend/src/components/artifact/Ports.vue +0 -23
- data/frontend/src/components/artifact/ReverseDnsNames.vue +0 -23
- data/frontend/src/components/artifact/Tags.vue +0 -29
- data/frontend/src/components/artifact/WhoisRecord.vue +0 -44
- data/frontend/src/components/config/Configs.vue +0 -65
- data/frontend/src/components/config/ConfigsWrapper.vue +0 -32
- data/frontend/src/components/link/Link.vue +0 -32
- data/frontend/src/components/link/Links.vue +0 -42
- data/frontend/src/components/rule/EditRule.vue +0 -72
- data/frontend/src/components/rule/EditRuleWrapper.vue +0 -48
- data/frontend/src/components/rule/Form.vue +0 -158
- data/frontend/src/components/rule/InputForm.vue +0 -45
- data/frontend/src/components/rule/NewRule.vue +0 -57
- data/frontend/src/components/rule/Rule.vue +0 -100
- data/frontend/src/components/rule/RuleWrapper.vue +0 -53
- data/frontend/src/components/rule/Rules.vue +0 -84
- data/frontend/src/components/rule/RulesWrapper.vue +0 -121
- data/frontend/src/components/rule/YAML.vue +0 -37
- data/frontend/src/components/tag/Tag.vue +0 -65
- data/frontend/src/components/tag/Tags.vue +0 -37
- data/frontend/src/countries.ts +0 -350
- data/frontend/src/index.ts +0 -20
- data/frontend/src/links/anyrun.ts +0 -19
- data/frontend/src/links/base.ts +0 -14
- data/frontend/src/links/censys.ts +0 -20
- data/frontend/src/links/crtsh.ts +0 -20
- data/frontend/src/links/dnslytics.ts +0 -38
- data/frontend/src/links/greynoise.ts +0 -20
- data/frontend/src/links/index.ts +0 -40
- data/frontend/src/links/intezer.ts +0 -20
- data/frontend/src/links/otx.ts +0 -33
- data/frontend/src/links/securitytrails.ts +0 -38
- data/frontend/src/links/shodan.ts +0 -20
- data/frontend/src/links/urlscan.ts +0 -50
- data/frontend/src/links/virustotal.ts +0 -72
- data/frontend/src/main.ts +0 -41
- data/frontend/src/router/index.ts +0 -57
- data/frontend/src/rule.ts +0 -14
- data/frontend/src/shims-vue.d.ts +0 -6
- data/frontend/src/swagger.yaml +0 -771
- data/frontend/src/types.ts +0 -188
- data/frontend/src/utils.ts +0 -54
- data/frontend/src/views/Alerts.vue +0 -20
- data/frontend/src/views/Artifact.vue +0 -39
- data/frontend/src/views/Configs.vue +0 -20
- data/frontend/src/views/EditRule.vue +0 -39
- data/frontend/src/views/NewRule.vue +0 -26
- data/frontend/src/views/Rule.vue +0 -39
- data/frontend/src/views/Rules.vue +0 -20
- data/frontend/tests/utils.spec.ts +0 -9
- data/frontend/tsconfig.app.json +0 -21
- data/frontend/tsconfig.json +0 -14
- data/frontend/tsconfig.node.json +0 -13
- data/frontend/tsconfig.vitest.json +0 -12
- data/frontend/vite.config.ts +0 -24
- data/frontend/vitest.config.ts +0 -21
- data/lib/mihari/mixins/error_notification.rb +0 -21
- data/lib/mihari/services/alert_proxy.rb +0 -97
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5c7fa4de39ec815c08930311d4ed642857236021301508c47d298cba157dd811
|
4
|
+
data.tar.gz: 1598a9992be6739957bc5145c11d93f8a869588d42985799d527703178f78a8f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6c96715d51778d724b4df1c502d3083c4af084997019cc7ef43fc5d131cfeb02c4b0f06d6353c0d8e75e26dec0fb20038fa36718f9a65bb1a3a771224442bc3e
|
7
|
+
data.tar.gz: 655c0efa77ff2602fef509b351ebf02ab9c222728ddfcfc0da36ba8fa27a4e1518f1d70406b5ba3ace86012c196954a98c9af10a4de58c5dcdf73bbc760d2056
|
data/.rubocop.yml
CHANGED
data/lib/mihari/actor.rb
CHANGED
@@ -2,9 +2,11 @@
|
|
2
2
|
|
3
3
|
module Mihari
|
4
4
|
#
|
5
|
-
#
|
5
|
+
# Yet another base service class for Analyzer, Emitter and Enricher
|
6
6
|
#
|
7
|
-
class Actor
|
7
|
+
class Actor
|
8
|
+
include Dry::Monads[:result, :try]
|
9
|
+
|
8
10
|
include Mixins::Configurable
|
9
11
|
include Mixins::Retriable
|
10
12
|
|
@@ -57,13 +59,17 @@ module Mihari
|
|
57
59
|
raise ConfigurationError, message
|
58
60
|
end
|
59
61
|
|
60
|
-
def
|
62
|
+
def call(*args, **kwargs)
|
63
|
+
raise NotImplementedError, "You must implement #{self.class}##{__method__}"
|
64
|
+
end
|
65
|
+
|
66
|
+
def result(...)
|
61
67
|
Try[StandardError] do
|
62
68
|
retry_on_error(
|
63
69
|
times: retry_times,
|
64
70
|
interval: retry_interval,
|
65
71
|
exponential_backoff: retry_exponential_backoff
|
66
|
-
) { call }
|
72
|
+
) { call(...) }
|
67
73
|
end.to_result
|
68
74
|
end
|
69
75
|
|
data/lib/mihari/cli/main.rb
CHANGED
data/lib/mihari/clients/base.rb
CHANGED
@@ -41,7 +41,7 @@ module Mihari
|
|
41
41
|
# @return [::HTTP::Client]
|
42
42
|
#
|
43
43
|
def http
|
44
|
-
HTTP::Factory.build
|
44
|
+
@http ||= HTTP::Factory.build(headers: headers, timeout: timeout)
|
45
45
|
end
|
46
46
|
|
47
47
|
#
|
@@ -63,6 +63,17 @@ module Mihari
|
|
63
63
|
http.get(url_for(path), params: params)
|
64
64
|
end
|
65
65
|
|
66
|
+
#
|
67
|
+
# @param [String] path
|
68
|
+
# @param [Hash, nil] params
|
69
|
+
#
|
70
|
+
# @return [Hash]
|
71
|
+
#
|
72
|
+
def get_json(path, params: nil)
|
73
|
+
res = get(path, params: params)
|
74
|
+
JSON.parse res.body.to_s
|
75
|
+
end
|
76
|
+
|
66
77
|
#
|
67
78
|
# @param [String] path
|
68
79
|
# @param [Hash, nil] json
|
@@ -72,6 +83,17 @@ module Mihari
|
|
72
83
|
def post(path, json: {})
|
73
84
|
http.post(url_for(path), json: json)
|
74
85
|
end
|
86
|
+
|
87
|
+
#
|
88
|
+
# @param [String] path
|
89
|
+
# @param [Hash, nil] json
|
90
|
+
#
|
91
|
+
# @return [Hash]
|
92
|
+
#
|
93
|
+
def post_json(path, json: {})
|
94
|
+
res = http.post(url_for(path), json: json)
|
95
|
+
JSON.parse res.body.to_s
|
96
|
+
end
|
75
97
|
end
|
76
98
|
end
|
77
99
|
end
|
@@ -38,9 +38,7 @@ module Mihari
|
|
38
38
|
page: page,
|
39
39
|
only_ips: only_ips
|
40
40
|
}.compact
|
41
|
-
|
42
|
-
res = get("/query/search", params: params)
|
43
|
-
Structs::BinaryEdge::Response.from_dynamic! JSON.parse(res.body.to_s)
|
41
|
+
Structs::BinaryEdge::Response.from_dynamic! get_json("/query/search", params: params)
|
44
42
|
end
|
45
43
|
|
46
44
|
#
|
@@ -46,8 +46,7 @@ module Mihari
|
|
46
46
|
#
|
47
47
|
def search(query, per_page: nil, cursor: nil)
|
48
48
|
params = { q: query, per_page: per_page, cursor: cursor }.compact
|
49
|
-
|
50
|
-
Structs::Censys::Response.from_dynamic! JSON.parse(res.body.to_s)
|
49
|
+
Structs::Censys::Response.from_dynamic! get_json("/api/v2/hosts/search", params: params)
|
51
50
|
end
|
52
51
|
|
53
52
|
#
|
data/lib/mihari/clients/crtsh.rb
CHANGED
@@ -27,9 +27,8 @@ module Mihari
|
|
27
27
|
def search(identity, match: nil, exclude: nil)
|
28
28
|
params = { identity: identity, match: match, exclude: exclude, output: "json" }.compact
|
29
29
|
|
30
|
-
|
31
|
-
parsed =
|
32
|
-
|
30
|
+
# @type [Array[Hash]]
|
31
|
+
parsed = get_json("/", params: params)
|
33
32
|
parsed.map do |result|
|
34
33
|
values = result["name_value"].to_s.lines.map(&:chomp)
|
35
34
|
values.map { |value| Models::Artifact.new(data: value, metadata: result) }
|
@@ -23,8 +23,7 @@ module Mihari
|
|
23
23
|
# @return [Array<String>]
|
24
24
|
#
|
25
25
|
def fuzz(domain)
|
26
|
-
res =
|
27
|
-
res = JSON.parse(res.body.to_s)
|
26
|
+
res = get_json("/api/fuzz/#{to_hex(domain)}")
|
28
27
|
fuzzy_domains = res["fuzzy_domains"] || []
|
29
28
|
fuzzy_domains.map { |d| d["domain"] }
|
30
29
|
end
|
data/lib/mihari/clients/fofa.rb
CHANGED
@@ -52,8 +52,7 @@ module Mihari
|
|
52
52
|
def search(query, page:, size: PAGE_SIZE)
|
53
53
|
qbase64 = Base64.urlsafe_encode64(query)
|
54
54
|
params = { qbase64: qbase64, size: size, page: page, email: email, key: api_key }.compact
|
55
|
-
|
56
|
-
Structs::Fofa::Response.from_dynamic! JSON.parse(res.body.to_s)
|
55
|
+
Structs::Fofa::Response.from_dynamic! get_json("/api/v1/search/all", params: params)
|
57
56
|
end
|
58
57
|
|
59
58
|
#
|
@@ -71,7 +70,6 @@ module Mihari
|
|
71
70
|
y.yield res
|
72
71
|
|
73
72
|
break if res.error
|
74
|
-
|
75
73
|
break if (res.results || []).length < size
|
76
74
|
|
77
75
|
sleep_pagination_interval
|
@@ -39,8 +39,7 @@ module Mihari
|
|
39
39
|
#
|
40
40
|
def gnql_search(query, size: PAGE_SIZE, scroll: nil)
|
41
41
|
params = { query: query, size: size, scroll: scroll }.compact
|
42
|
-
|
43
|
-
Structs::GreyNoise::Response.from_dynamic! JSON.parse(res.body.to_s)
|
42
|
+
Structs::GreyNoise::Response.from_dynamic! get_json("/v2/experimental/gnql", params: params)
|
44
43
|
end
|
45
44
|
|
46
45
|
#
|
@@ -52,8 +52,7 @@ module Mihari
|
|
52
52
|
end_time: end_time,
|
53
53
|
"api-key": api_key
|
54
54
|
}.compact
|
55
|
-
|
56
|
-
Structs::HunterHow::Response.from_dynamic! JSON.parse(res.body.to_s)
|
55
|
+
Structs::HunterHow::Response.from_dynamic! get_json("/search", params: params)
|
57
56
|
end
|
58
57
|
|
59
58
|
#
|
data/lib/mihari/clients/misp.rb
CHANGED
@@ -40,8 +40,7 @@ module Mihari
|
|
40
40
|
#
|
41
41
|
def datascan(query, page: 1)
|
42
42
|
params = { page: page, apikey: api_key }
|
43
|
-
|
44
|
-
Structs::Onyphe::Response.from_dynamic! JSON.parse(res.body.to_s)
|
43
|
+
Structs::Onyphe::Response.from_dynamic! get_json("/api/v2/simple/datascan/#{query}", params: params)
|
45
44
|
end
|
46
45
|
|
47
46
|
#
|
data/lib/mihari/clients/otx.rb
CHANGED
@@ -65,7 +65,7 @@ module Mihari
|
|
65
65
|
# @return [Hash]
|
66
66
|
#
|
67
67
|
def query_by_ip(ip)
|
68
|
-
|
68
|
+
get_json "/api/v1/indicators/IPv4/#{ip}/passive_dns"
|
69
69
|
end
|
70
70
|
|
71
71
|
#
|
@@ -74,19 +74,7 @@ module Mihari
|
|
74
74
|
# @return [Hash]
|
75
75
|
#
|
76
76
|
def query_by_domain(domain)
|
77
|
-
|
78
|
-
end
|
79
|
-
|
80
|
-
private
|
81
|
-
|
82
|
-
#
|
83
|
-
# @param [String] path
|
84
|
-
#
|
85
|
-
# @return [Hash]
|
86
|
-
#
|
87
|
-
def _get(path)
|
88
|
-
res = get(path)
|
89
|
-
JSON.parse(res.body.to_s)
|
77
|
+
get_json "/api/v1/indicators/domain/#{domain}/passive_dns"
|
90
78
|
end
|
91
79
|
end
|
92
80
|
end
|
@@ -33,7 +33,7 @@ module Mihari
|
|
33
33
|
#
|
34
34
|
def passive_dns_search(query)
|
35
35
|
params = { query: query }
|
36
|
-
res =
|
36
|
+
res = get_json("/v2/dns/passive/unique", params: params)
|
37
37
|
res["results"] || []
|
38
38
|
end
|
39
39
|
|
@@ -49,7 +49,7 @@ module Mihari
|
|
49
49
|
query: query,
|
50
50
|
field: "email"
|
51
51
|
}.compact
|
52
|
-
res =
|
52
|
+
res = get_json("/v2/whois/search", params: params)
|
53
53
|
results = res["results"] || []
|
54
54
|
results.map do |result|
|
55
55
|
data = result["domain"]
|
@@ -66,26 +66,13 @@ module Mihari
|
|
66
66
|
#
|
67
67
|
def ssl_search(query)
|
68
68
|
params = { query: query }
|
69
|
-
res =
|
69
|
+
res = get_json("/v2/ssl-certificate/history", params: params)
|
70
70
|
results = res["results"] || []
|
71
71
|
results.map do |result|
|
72
72
|
data = result["ipAddresses"]
|
73
73
|
data.map { |d| Models::Artifact.new(data: d, metadata: result) }
|
74
74
|
end.flatten
|
75
75
|
end
|
76
|
-
|
77
|
-
private
|
78
|
-
|
79
|
-
#
|
80
|
-
# @param [String] path
|
81
|
-
# @param [Hash] params
|
82
|
-
#
|
83
|
-
# @return [Hash]
|
84
|
-
#
|
85
|
-
def _get(path, params: {})
|
86
|
-
res = get(path, params: params)
|
87
|
-
JSON.parse(res.body.to_s)
|
88
|
-
end
|
89
76
|
end
|
90
77
|
end
|
91
78
|
end
|
@@ -29,7 +29,7 @@ module Mihari
|
|
29
29
|
# @return [Hash]
|
30
30
|
#
|
31
31
|
def get_indicator(ip_or_domain)
|
32
|
-
|
32
|
+
get_json "/api/info.php", params: { indicator: ip_or_domain, key: api_key }
|
33
33
|
end
|
34
34
|
|
35
35
|
#
|
@@ -38,22 +38,7 @@ module Mihari
|
|
38
38
|
# @return [Hash]
|
39
39
|
#
|
40
40
|
def get_properties(indicator_id)
|
41
|
-
|
42
|
-
end
|
43
|
-
|
44
|
-
private
|
45
|
-
|
46
|
-
#
|
47
|
-
# @param [String] path
|
48
|
-
# @param [Hash] params
|
49
|
-
#
|
50
|
-
# @return [Hash]
|
51
|
-
#
|
52
|
-
def _get(path, params: {})
|
53
|
-
params["key"] = api_key
|
54
|
-
|
55
|
-
res = get(path, params: params)
|
56
|
-
JSON.parse res.body.to_s
|
41
|
+
get_json "/api/info.php", params: { iid: indicator_id, get: "properties", key: api_key }
|
57
42
|
end
|
58
43
|
end
|
59
44
|
end
|
@@ -70,7 +70,7 @@ module Mihari
|
|
70
70
|
# @return [Array<Hash>]
|
71
71
|
#
|
72
72
|
def search_by_mail(mail)
|
73
|
-
res =
|
73
|
+
res = post_json "/v1/domains/list", json: { filter: { whois_email: mail } }
|
74
74
|
res["records"] || []
|
75
75
|
end
|
76
76
|
|
@@ -80,7 +80,7 @@ module Mihari
|
|
80
80
|
# @return [Array<Hash>]
|
81
81
|
#
|
82
82
|
def search_by_ip(ip)
|
83
|
-
res =
|
83
|
+
res = post_json "/v1/domains/list", json: { filter: { ipv4: ip } }
|
84
84
|
res["records"] || []
|
85
85
|
end
|
86
86
|
|
@@ -114,29 +114,7 @@ module Mihari
|
|
114
114
|
# @return [Array<Hash>]
|
115
115
|
#
|
116
116
|
def get_dns_history(domain, type:, page:)
|
117
|
-
|
118
|
-
end
|
119
|
-
|
120
|
-
#
|
121
|
-
# @param [String] path
|
122
|
-
# @param [Hash, nil] params
|
123
|
-
#
|
124
|
-
# @return [Hash]
|
125
|
-
#
|
126
|
-
def _get(path, params:)
|
127
|
-
res = get(path, params: params)
|
128
|
-
JSON.parse(res.body.to_s)
|
129
|
-
end
|
130
|
-
|
131
|
-
#
|
132
|
-
# @param [String] path
|
133
|
-
# @param [Hash, nil] json
|
134
|
-
#
|
135
|
-
# @return [Hash]
|
136
|
-
#
|
137
|
-
def _post(path, json:)
|
138
|
-
res = post(path, json: json)
|
139
|
-
JSON.parse(res.body.to_s)
|
117
|
+
get_json "/v1/history/#{domain}/dns/#{type}", params: { page: page }
|
140
118
|
end
|
141
119
|
end
|
142
120
|
end
|
@@ -46,8 +46,7 @@ module Mihari
|
|
46
46
|
minify: minify,
|
47
47
|
key: api_key
|
48
48
|
}
|
49
|
-
|
50
|
-
Structs::Shodan::Response.from_dynamic! JSON.parse(res.body.to_s)
|
49
|
+
Structs::Shodan::Response.from_dynamic! get_json("/shodan/host/search", params: params)
|
51
50
|
end
|
52
51
|
|
53
52
|
#
|
@@ -36,8 +36,7 @@ module Mihari
|
|
36
36
|
#
|
37
37
|
def search(q, size: nil, search_after: nil)
|
38
38
|
params = { q: q, size: size, search_after: search_after }.compact
|
39
|
-
|
40
|
-
Structs::Urlscan::Response.from_dynamic! JSON.parse(res.body.to_s)
|
39
|
+
Structs::Urlscan::Response.from_dynamic! get_json("/api/v1/search/", params: params)
|
41
40
|
end
|
42
41
|
|
43
42
|
#
|
@@ -33,7 +33,7 @@ module Mihari
|
|
33
33
|
# @return [Hash]
|
34
34
|
#
|
35
35
|
def domain_search(query)
|
36
|
-
|
36
|
+
get_json "/api/v3/domains/#{query}/resolutions"
|
37
37
|
end
|
38
38
|
|
39
39
|
#
|
@@ -42,7 +42,7 @@ module Mihari
|
|
42
42
|
# @return [Hash]
|
43
43
|
#
|
44
44
|
def ip_search(query)
|
45
|
-
|
45
|
+
get_json "/api/v3/ip_addresses/#{query}/resolutions"
|
46
46
|
end
|
47
47
|
|
48
48
|
#
|
@@ -53,8 +53,7 @@ module Mihari
|
|
53
53
|
#
|
54
54
|
def intel_search(query, cursor: nil)
|
55
55
|
params = { query: query, cursor: cursor }.compact
|
56
|
-
|
57
|
-
Structs::VirusTotalIntelligence::Response.from_dynamic! res
|
56
|
+
Structs::VirusTotalIntelligence::Response.from_dynamic! get_json("/api/v3/intelligence/search", params: params)
|
58
57
|
end
|
59
58
|
|
60
59
|
#
|
@@ -79,19 +78,6 @@ module Mihari
|
|
79
78
|
end
|
80
79
|
end
|
81
80
|
end
|
82
|
-
|
83
|
-
private
|
84
|
-
|
85
|
-
#
|
86
|
-
# @param [String] path
|
87
|
-
# @param [Hash] params
|
88
|
-
#
|
89
|
-
# @return [Hash]
|
90
|
-
#
|
91
|
-
def _get(path, params: {})
|
92
|
-
res = get(path, params: params)
|
93
|
-
JSON.parse(res.body.to_s)
|
94
|
-
end
|
95
81
|
end
|
96
82
|
end
|
97
83
|
end
|
@@ -30,6 +30,13 @@ module Mihari
|
|
30
30
|
super(base_url, headers: headers, pagination_interval: pagination_interval, timeout: timeout)
|
31
31
|
end
|
32
32
|
|
33
|
+
#
|
34
|
+
# @return [::HTTP::Client]
|
35
|
+
#
|
36
|
+
def http
|
37
|
+
@http ||= HTTP::Factory.build(headers: headers, timeout: timeout, raise_exception: false)
|
38
|
+
end
|
39
|
+
|
33
40
|
#
|
34
41
|
# Search the Host devices
|
35
42
|
#
|
@@ -45,8 +52,7 @@ module Mihari
|
|
45
52
|
page: page,
|
46
53
|
facets: facets
|
47
54
|
}.compact
|
48
|
-
|
49
|
-
_get("/host/search", params: params)
|
55
|
+
get_json "/host/search", params: params
|
50
56
|
end
|
51
57
|
|
52
58
|
#
|
@@ -88,8 +94,7 @@ module Mihari
|
|
88
94
|
page: page,
|
89
95
|
facets: facets
|
90
96
|
}.compact
|
91
|
-
|
92
|
-
_get("/web/search", params: params)
|
97
|
+
get_json "/web/search", params: params
|
93
98
|
end
|
94
99
|
|
95
100
|
#
|
@@ -115,21 +120,6 @@ module Mihari
|
|
115
120
|
end
|
116
121
|
end
|
117
122
|
end
|
118
|
-
|
119
|
-
private
|
120
|
-
|
121
|
-
#
|
122
|
-
# @param [String] path
|
123
|
-
# @param [Hash] params
|
124
|
-
#
|
125
|
-
# @return [Hash, nil]
|
126
|
-
#
|
127
|
-
def _get(path, params: {})
|
128
|
-
res = get(path, params: params)
|
129
|
-
JSON.parse(res.body.to_s)
|
130
|
-
rescue HTTPError
|
131
|
-
nil
|
132
|
-
end
|
133
123
|
end
|
134
124
|
end
|
135
125
|
end
|
@@ -10,22 +10,24 @@ module Mihari
|
|
10
10
|
def included(thor)
|
11
11
|
thor.class_eval do
|
12
12
|
include Dry::Monads[:result, :try]
|
13
|
+
include Mixins
|
13
14
|
|
14
15
|
desc "add [PATH]", "Add an alert"
|
16
|
+
around :with_db_connection
|
15
17
|
#
|
16
18
|
# @param [String] path
|
17
19
|
#
|
18
20
|
def add(path)
|
19
|
-
|
20
|
-
|
21
|
+
result = Dry::Monads::Try[StandardError] do
|
22
|
+
# @type [Mihari::Services::AlertProxy]
|
23
|
+
proxy = Mihari::Services::AlertBuilder.call(path)
|
24
|
+
Mihari::Services::AlertRunner.call proxy
|
25
|
+
end.to_result
|
21
26
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
data = Entities::Alert.represent(alert)
|
27
|
-
puts JSON.pretty_generate(data.as_json)
|
28
|
-
end
|
27
|
+
# @type [Mihari::Models::Alert]
|
28
|
+
alert = result.value!
|
29
|
+
data = Entities::Alert.represent(alert)
|
30
|
+
puts JSON.pretty_generate(data.as_json)
|
29
31
|
end
|
30
32
|
end
|
31
33
|
end
|
@@ -9,7 +9,10 @@ module Mihari
|
|
9
9
|
class << self
|
10
10
|
def included(thor)
|
11
11
|
thor.class_eval do
|
12
|
+
include Mixins
|
13
|
+
|
12
14
|
desc "migrate", "Migrate DB schemas"
|
15
|
+
around :with_db_connection
|
13
16
|
method_option :verbose, type: :boolean, default: true
|
14
17
|
#
|
15
18
|
# @param [String] direction
|
@@ -17,7 +20,7 @@ module Mihari
|
|
17
20
|
def migrate(direction = "up")
|
18
21
|
ActiveRecord::Migration.verbose = options["verbose"]
|
19
22
|
|
20
|
-
Mihari::Database.
|
23
|
+
Mihari::Database.migrate direction.to_sym
|
21
24
|
end
|
22
25
|
end
|
23
26
|
end
|
@@ -10,8 +10,10 @@ module Mihari
|
|
10
10
|
def included(thor)
|
11
11
|
thor.class_eval do
|
12
12
|
include Dry::Monads[:try, :result]
|
13
|
+
include Mixins
|
13
14
|
|
14
15
|
desc "search [PATH_OR_ID]", "Search by a rule (Outputs null if there is no new finding)"
|
16
|
+
around :with_db_connection
|
15
17
|
method_option :force_overwrite, type: :boolean, aliases: "-f", desc: "Force overwriting a rule"
|
16
18
|
#
|
17
19
|
# Search by a rule
|
@@ -19,43 +21,22 @@ module Mihari
|
|
19
21
|
# @param [String] path_or_id
|
20
22
|
#
|
21
23
|
def search(path_or_id)
|
22
|
-
|
23
|
-
|
24
|
+
result = Dry::Monads::Try[StandardError] do
|
25
|
+
# @type [Mihari::Rule]
|
26
|
+
rule = Services::RuleBuilder.call(path_or_id)
|
24
27
|
|
25
|
-
check_diff_l = ->(rule) { check_diff rule }
|
26
|
-
update_and_call_l = ->(runner) { update_and_call runner }
|
27
|
-
|
28
|
-
result = builder.result.bind(check_diff_l).bind(update_and_call_l)
|
29
|
-
|
30
|
-
alert = result.value!
|
31
|
-
data = Entities::Alert.represent(alert)
|
32
|
-
puts JSON.pretty_generate(data.as_json)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
no_commands do
|
37
|
-
#
|
38
|
-
# @param [Mihari::RuleRunner] rule
|
39
|
-
#
|
40
|
-
def check_diff(rule)
|
41
28
|
force_overwrite = options["force_overwrite"] || false
|
42
29
|
message = "There is a diff in the rule. Are you sure you want to overwrite the rule? (y/n)"
|
43
|
-
|
44
|
-
|
45
|
-
exit 0 if runner.diff? && !force_overwrite && !yes?(message)
|
30
|
+
exit 0 if rule.diff? && !force_overwrite && !yes?(message)
|
46
31
|
|
47
|
-
|
48
|
-
|
32
|
+
rule.update_or_create
|
33
|
+
rule.call
|
34
|
+
end.to_result
|
49
35
|
|
50
|
-
#
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
Dry::Monads::Try[StandardError] do
|
55
|
-
runner.update_or_create
|
56
|
-
runner.call
|
57
|
-
end.to_result
|
58
|
-
end
|
36
|
+
# @type [Mihari::Models::Alert]
|
37
|
+
alert = result.value!
|
38
|
+
data = Entities::Alert.represent(alert)
|
39
|
+
puts JSON.pretty_generate(data.as_json)
|
59
40
|
end
|
60
41
|
end
|
61
42
|
end
|
data/lib/mihari/constants.rb
CHANGED
@@ -5,7 +5,7 @@ module Mihari
|
|
5
5
|
DEFAULT_DATA_TYPES = Types::DataTypes.values.freeze
|
6
6
|
|
7
7
|
# @return [Array<Hash>]
|
8
|
-
DEFAULT_EMITTERS = Emitters::Database.class_keys.map { |name| { emitter: name } }.freeze
|
8
|
+
DEFAULT_EMITTERS = Emitters::Database.class_keys.map { |name| { emitter: name.downcase } }.freeze
|
9
9
|
|
10
10
|
# @return [Array<Hash>]
|
11
11
|
DEFAULT_ENRICHERS = Mihari.enricher_to_class.keys.map { |name| { enricher: name.downcase } }.freeze
|