mihari 3.12.0 → 4.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Rakefile +5 -0
- data/config.ru +0 -1
- data/lib/mihari/analyzers/base.rb +6 -6
- data/lib/mihari/analyzers/binaryedge.rb +3 -5
- data/lib/mihari/analyzers/censys.rb +1 -3
- data/lib/mihari/analyzers/circl.rb +0 -3
- data/lib/mihari/analyzers/crtsh.rb +7 -5
- data/lib/mihari/analyzers/dnpedia.rb +4 -4
- data/lib/mihari/analyzers/dnstwister.rb +1 -4
- data/lib/mihari/analyzers/feed.rb +0 -3
- data/lib/mihari/analyzers/greynoise.rb +1 -3
- data/lib/mihari/analyzers/onyphe.rb +1 -3
- data/lib/mihari/analyzers/otx.rb +0 -3
- data/lib/mihari/analyzers/passivetotal.rb +8 -9
- data/lib/mihari/analyzers/pulsedive.rb +7 -5
- data/lib/mihari/analyzers/rule.rb +5 -6
- data/lib/mihari/analyzers/securitytrails.rb +10 -7
- data/lib/mihari/analyzers/shodan.rb +19 -6
- data/lib/mihari/analyzers/spyse.rb +10 -11
- data/lib/mihari/analyzers/urlscan.rb +5 -6
- data/lib/mihari/analyzers/virustotal.rb +8 -9
- data/lib/mihari/analyzers/virustotal_intelligence.rb +4 -5
- data/lib/mihari/analyzers/zoomeye.rb +4 -5
- data/lib/mihari/cli/base.rb +0 -5
- data/lib/mihari/cli/init.rb +0 -2
- data/lib/mihari/cli/main.rb +4 -6
- data/lib/mihari/cli/mixins/utils.rb +2 -18
- data/lib/mihari/commands/init.rb +0 -18
- data/lib/mihari/commands/search.rb +20 -15
- data/lib/mihari/commands/validator.rb +7 -19
- data/lib/mihari/commands/web.rb +0 -3
- data/lib/mihari/database.rb +66 -14
- data/lib/mihari/emitters/misp.rb +0 -1
- data/lib/mihari/emitters/slack.rb +3 -4
- data/lib/mihari/emitters/stdout.rb +0 -2
- data/lib/mihari/emitters/the_hive.rb +0 -1
- data/lib/mihari/emitters/webhook.rb +1 -5
- data/lib/mihari/enrichers/ipinfo.rb +0 -2
- data/lib/mihari/errors.rb +2 -0
- data/lib/mihari/feed/reader.rb +22 -8
- data/lib/mihari/mixins/database.rb +14 -0
- data/lib/mihari/mixins/disallowed_data_value.rb +1 -4
- data/lib/mihari/mixins/rule.rb +34 -31
- data/lib/mihari/models/alert.rb +3 -3
- data/lib/mihari/models/artifact.rb +0 -5
- data/lib/mihari/models/autonomous_system.rb +0 -2
- data/lib/mihari/models/dns.rb +0 -3
- data/lib/mihari/models/geolocation.rb +0 -1
- data/lib/mihari/models/reverse_dns.rb +0 -3
- data/lib/mihari/models/rule.rb +73 -0
- data/lib/mihari/models/tag.rb +0 -2
- data/lib/mihari/models/tagging.rb +0 -2
- data/lib/mihari/models/whois.rb +0 -2
- data/lib/mihari/notifiers/exception_notifier.rb +0 -2
- data/lib/mihari/schemas/analyzer.rb +0 -5
- data/lib/mihari/schemas/macros.rb +0 -2
- data/lib/mihari/schemas/rule.rb +0 -5
- data/lib/mihari/structs/alert.rb +0 -3
- data/lib/mihari/structs/censys.rb +3 -4
- data/lib/mihari/structs/greynoise.rb +3 -4
- data/lib/mihari/structs/ipinfo.rb +0 -3
- data/lib/mihari/structs/onyphe.rb +5 -6
- data/lib/mihari/structs/rule.rb +127 -0
- data/lib/mihari/structs/shodan.rb +3 -4
- data/lib/mihari/structs/urlscan.rb +0 -3
- data/lib/mihari/structs/virustotal_intelligence.rb +3 -4
- data/lib/mihari/type_checker.rb +2 -6
- data/lib/mihari/types.rb +0 -2
- data/lib/mihari/version.rb +1 -1
- data/lib/mihari/web/api.rb +4 -0
- data/lib/mihari/web/app.rb +6 -8
- data/lib/mihari/web/endpoints/alerts.rb +7 -3
- data/lib/mihari/web/endpoints/artifacts.rb +6 -3
- data/lib/mihari/web/endpoints/command.rb +2 -1
- data/lib/mihari/web/endpoints/configs.rb +2 -1
- data/lib/mihari/web/endpoints/ip_addresses.rb +2 -1
- data/lib/mihari/web/endpoints/rules.rb +175 -0
- data/lib/mihari/web/endpoints/sources.rb +2 -1
- data/lib/mihari/web/endpoints/tags.rb +4 -2
- data/lib/mihari/web/entities/artifact.rb +2 -0
- data/lib/mihari/web/entities/rule.rb +35 -0
- data/lib/mihari/web/middleware/connection_adapter.rb +19 -0
- data/lib/mihari/web/public/index.html +1 -1
- data/lib/mihari/web/public/redoc-static.html +39 -22
- data/lib/mihari/web/public/static/js/app.49ab738a.js +21 -0
- data/lib/mihari/web/public/static/js/app.49ab738a.js.map +1 -0
- data/lib/mihari/web/public/static/js/app.b88ce341.js +35 -0
- data/lib/mihari/web/public/static/js/app.b88ce341.js.map +1 -0
- data/lib/mihari/web/public/static/js/app.cb1fa7be.js +30 -0
- data/lib/mihari/web/public/static/js/app.cb1fa7be.js.map +1 -0
- data/lib/mihari/web/public/static/js/app.eb95cfc9.js +30 -0
- data/lib/mihari/web/public/static/js/app.eb95cfc9.js.map +1 -0
- data/lib/mihari.rb +40 -35
- data/mihari.gemspec +11 -13
- data/sig/lib/mihari/analyzers/binaryedge.rbs +0 -3
- data/sig/lib/mihari/analyzers/censys.rbs +0 -3
- data/sig/lib/mihari/analyzers/circl.rbs +1 -3
- data/sig/lib/mihari/analyzers/crtsh.rbs +1 -3
- data/sig/lib/mihari/analyzers/dnpedia.rbs +1 -4
- data/sig/lib/mihari/analyzers/dnstwister.rbs +1 -3
- data/sig/lib/mihari/analyzers/feed.rbs +0 -3
- data/sig/lib/mihari/analyzers/onyphe.rbs +0 -3
- data/sig/lib/mihari/analyzers/otx.rbs +1 -3
- data/sig/lib/mihari/analyzers/passivetotal.rbs +3 -5
- data/sig/lib/mihari/analyzers/pulsedive.rbs +2 -4
- data/sig/lib/mihari/analyzers/securitytrails.rbs +3 -5
- data/sig/lib/mihari/analyzers/shodan.rbs +2 -3
- data/sig/lib/mihari/analyzers/spyse.rbs +4 -6
- data/sig/lib/mihari/analyzers/urlscan.rbs +1 -3
- data/sig/lib/mihari/analyzers/virustotal.rbs +4 -6
- data/sig/lib/mihari/analyzers/virustotal_intelligence.rbs +0 -3
- data/sig/lib/mihari/analyzers/zoomeye.rbs +2 -4
- data/sig/lib/mihari/commands/init.rbs +0 -2
- data/sig/lib/mihari/commands/validator.rbs +0 -2
- data/sig/lib/mihari/emitters/slack.rbs +0 -1
- data/sig/lib/mihari/feed/reader.rbs +1 -1
- data/sig/lib/mihari/mixins/disallowed_data_value.rbs +0 -2
- data/sig/lib/mihari/mixins/rule.rbs +5 -12
- data/sig/lib/mihari/models/alert.rbs +1 -1
- data/sig/lib/mihari/models/artifact.rbs +2 -0
- data/sig/lib/mihari/models/rule.rbs +14 -0
- data/sig/lib/mihari/structs/rule.rbs +56 -0
- data/sig/lib/mihari.rbs +0 -2
- metadata +40 -97
- data/lib/mihari/analyzers/basic.rb +0 -19
- data/lib/mihari/cli/analyzer.rb +0 -55
- data/lib/mihari/commands/binaryedge.rb +0 -21
- data/lib/mihari/commands/censys.rb +0 -22
- data/lib/mihari/commands/circl.rb +0 -21
- data/lib/mihari/commands/crtsh.rb +0 -22
- data/lib/mihari/commands/dnpedia.rb +0 -21
- data/lib/mihari/commands/dnstwister.rb +0 -21
- data/lib/mihari/commands/feed.rb +0 -26
- data/lib/mihari/commands/greynoise.rb +0 -21
- data/lib/mihari/commands/json.rb +0 -42
- data/lib/mihari/commands/onyphe.rb +0 -21
- data/lib/mihari/commands/otx.rb +0 -21
- data/lib/mihari/commands/passivetotal.rb +0 -22
- data/lib/mihari/commands/pulsedive.rb +0 -21
- data/lib/mihari/commands/securitytrails.rb +0 -22
- data/lib/mihari/commands/shodan.rb +0 -21
- data/lib/mihari/commands/spyse.rb +0 -22
- data/lib/mihari/commands/urlscan.rb +0 -22
- data/lib/mihari/commands/virustotal.rb +0 -22
- data/lib/mihari/commands/virustotal_intelligence.rb +0 -22
- data/lib/mihari/commands/zoomeye.rb +0 -22
- data/lib/mihari/mixins/configuration.rb +0 -100
- data/lib/mihari/mixins/hash.rb +0 -20
- data/lib/mihari/schemas/configuration.rb +0 -44
- data/lib/mihari/web/public/grape.rb +0 -73
- data/sig/lib/mihari/analyzers/basic.rbs +0 -17
- data/sig/lib/mihari/cli/analyzer.rbs +0 -43
- data/sig/lib/mihari/commands/binaryedge.rbs +0 -7
- data/sig/lib/mihari/commands/censys.rbs +0 -7
- data/sig/lib/mihari/commands/circl.rbs +0 -7
- data/sig/lib/mihari/commands/crtsh.rbs +0 -7
- data/sig/lib/mihari/commands/dnpedia.rbs +0 -7
- data/sig/lib/mihari/commands/dnstwister.rbs +0 -7
- data/sig/lib/mihari/commands/feed.rbs +0 -7
- data/sig/lib/mihari/commands/onyphe.rbs +0 -7
- data/sig/lib/mihari/commands/otx.rbs +0 -7
- data/sig/lib/mihari/commands/passivetotal.rbs +0 -7
- data/sig/lib/mihari/commands/pulsedive.rbs +0 -7
- data/sig/lib/mihari/commands/securitytrails.rbs +0 -7
- data/sig/lib/mihari/commands/shodan.rbs +0 -7
- data/sig/lib/mihari/commands/spyse.rbs +0 -7
- data/sig/lib/mihari/commands/urlscan.rbs +0 -7
- data/sig/lib/mihari/commands/virustotal.rbs +0 -7
- data/sig/lib/mihari/commands/zoomeye.rbs +0 -7
@@ -1,21 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Mihari
|
4
|
-
module Commands
|
5
|
-
module DNSTwister
|
6
|
-
def self.included(thor)
|
7
|
-
thor.class_eval do
|
8
|
-
desc "dnstwister [DOMAIN]", "dnstwister search"
|
9
|
-
method_option :title, type: :string, desc: "title"
|
10
|
-
method_option :description, type: :string, desc: "description"
|
11
|
-
method_option :tags, type: :array, desc: "tags"
|
12
|
-
def dnstwister(domain)
|
13
|
-
with_error_handling do
|
14
|
-
run_analyzer Analyzers::DNSTwister, query: domain, options: options
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
data/lib/mihari/commands/feed.rb
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Mihari
|
4
|
-
module Commands
|
5
|
-
module Feed
|
6
|
-
def self.included(thor)
|
7
|
-
thor.class_eval do
|
8
|
-
desc "feed [URL]", "ingest feed"
|
9
|
-
method_option :title, type: :string, desc: "title"
|
10
|
-
method_option :description, type: :string, desc: "description"
|
11
|
-
method_option :tags, type: :array, desc: "tags"
|
12
|
-
method_option :http_request_method, type: :string, desc: "HTTP request method"
|
13
|
-
method_option :http_request_headers, type: :hash, desc: "HTTP request headers"
|
14
|
-
method_option :http_request_payload_type, type: :string, desc: "HTTP request payload type"
|
15
|
-
method_option :http_request_payload, type: :hash, desc: "HTTP request payload"
|
16
|
-
method_option :selector, type: :string, desc: "jr selector", required: true
|
17
|
-
def feed(query)
|
18
|
-
with_error_handling do
|
19
|
-
run_analyzer Analyzers::Feed, query: query, options: options
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
@@ -1,21 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Mihari
|
4
|
-
module Commands
|
5
|
-
module GreyNoise
|
6
|
-
def self.included(thor)
|
7
|
-
thor.class_eval do
|
8
|
-
desc "greynoise [QUERY]", "GreyNoise search"
|
9
|
-
method_option :title, type: :string, desc: "title"
|
10
|
-
method_option :description, type: :string, desc: "description"
|
11
|
-
method_option :tags, type: :array, desc: "tags"
|
12
|
-
def greynoise(query)
|
13
|
-
with_error_handling do
|
14
|
-
run_analyzer Analyzers::GreyNoise, query: query, options: options
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
data/lib/mihari/commands/json.rb
DELETED
@@ -1,42 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Mihari
|
4
|
-
module Commands
|
5
|
-
module JSON
|
6
|
-
def self.included(thor)
|
7
|
-
thor.class_eval do
|
8
|
-
desc "import_from_json", "Give a JSON input via STDIN"
|
9
|
-
def import_from_json(input = nil)
|
10
|
-
with_error_handling do
|
11
|
-
json = input || $stdin.gets.chomp
|
12
|
-
raise ArgumentError, "Input not found: please give an input in a JSON format" unless json
|
13
|
-
|
14
|
-
json = parse_as_json(json)
|
15
|
-
raise ArgumentError, "Invalid input format: an input JSON data should have title, description and artifacts key" unless required_alert_keys?(json)
|
16
|
-
|
17
|
-
title = json["title"]
|
18
|
-
description = json["description"]
|
19
|
-
artifacts = json["artifacts"]
|
20
|
-
tags = json["tags"] || []
|
21
|
-
|
22
|
-
basic = Analyzers::Basic.new(title: title, description: description, artifacts: artifacts, source: "json", tags: tags)
|
23
|
-
|
24
|
-
basic.ignore_old_artifacts = options["ignore_old_artifacts"] || false
|
25
|
-
basic.ignore_threshold = options["ignore_threshold"] || 0
|
26
|
-
|
27
|
-
basic.run
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
no_commands do
|
32
|
-
def parse_as_json(input)
|
33
|
-
::JSON.parse input
|
34
|
-
rescue ::JSON::ParserError => _e
|
35
|
-
nil
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
@@ -1,21 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Mihari
|
4
|
-
module Commands
|
5
|
-
module Onyphe
|
6
|
-
def self.included(thor)
|
7
|
-
thor.class_eval do
|
8
|
-
desc "onyphe [QUERY]", "Onyphe datascan search"
|
9
|
-
method_option :title, type: :string, desc: "title"
|
10
|
-
method_option :description, type: :string, desc: "description"
|
11
|
-
method_option :tags, type: :array, desc: "tags"
|
12
|
-
def onyphe(query)
|
13
|
-
with_error_handling do
|
14
|
-
run_analyzer Analyzers::Onyphe, query: query, options: options
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
data/lib/mihari/commands/otx.rb
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Mihari
|
4
|
-
module Commands
|
5
|
-
module OTX
|
6
|
-
def self.included(thor)
|
7
|
-
thor.class_eval do
|
8
|
-
desc "otx [IP|DOMAIN]", "OTX search by an IP or domain"
|
9
|
-
method_option :title, type: :string, desc: "title"
|
10
|
-
method_option :description, type: :string, desc: "description"
|
11
|
-
method_option :tags, type: :array, desc: "tags"
|
12
|
-
def otx(domain)
|
13
|
-
with_error_handling do
|
14
|
-
run_analyzer Analyzers::OTX, query: domain, options: options
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Mihari
|
4
|
-
module Commands
|
5
|
-
module PassiveTotal
|
6
|
-
def self.included(thor)
|
7
|
-
thor.class_eval do
|
8
|
-
desc "passivetotal [IP|DOMAIN|EMAIL|SHA1]", "PassiveTotal search by an ip, domain, email or SHA1 certificate fingerprint"
|
9
|
-
method_option :title, type: :string, desc: "title"
|
10
|
-
method_option :description, type: :string, desc: "description"
|
11
|
-
method_option :tags, type: :array, desc: "tags"
|
12
|
-
def passivetotal(indicator)
|
13
|
-
with_error_handling do
|
14
|
-
run_analyzer Analyzers::PassiveTotal, query: indicator, options: options
|
15
|
-
end
|
16
|
-
end
|
17
|
-
map "pt" => :passivetotal
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
@@ -1,21 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Mihari
|
4
|
-
module Commands
|
5
|
-
module Pulsedive
|
6
|
-
def self.included(thor)
|
7
|
-
thor.class_eval do
|
8
|
-
desc "pulsedive [IP|DOMAIN]", "Pulsedive search by an ip or domain"
|
9
|
-
method_option :title, type: :string, desc: "title"
|
10
|
-
method_option :description, type: :string, desc: "description"
|
11
|
-
method_option :tags, type: :array, desc: "tags"
|
12
|
-
def pulsedive(indiactor)
|
13
|
-
with_error_handling do
|
14
|
-
run_analyzer Analyzers::Pulsedive, query: indiactor, options: options
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Mihari
|
4
|
-
module Commands
|
5
|
-
module SecurityTrails
|
6
|
-
def self.included(thor)
|
7
|
-
thor.class_eval do
|
8
|
-
desc "securitytrails [IP|DOMAIN|EMAIL]", "SecurityTrails search by an ip, domain or email"
|
9
|
-
method_option :title, type: :string, desc: "title"
|
10
|
-
method_option :description, type: :string, desc: "description"
|
11
|
-
method_option :tags, type: :array, desc: "tags"
|
12
|
-
def securitytrails(indiactor)
|
13
|
-
with_error_handling do
|
14
|
-
run_analyzer Analyzers::SecurityTrails, query: indiactor, options: options
|
15
|
-
end
|
16
|
-
end
|
17
|
-
map "st" => :securitytrails
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
@@ -1,21 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Mihari
|
4
|
-
module Commands
|
5
|
-
module Shodan
|
6
|
-
def self.included(thor)
|
7
|
-
thor.class_eval do
|
8
|
-
desc "shodan [QUERY]", "Shodan host search"
|
9
|
-
method_option :title, type: :string, desc: "title"
|
10
|
-
method_option :description, type: :string, desc: "description"
|
11
|
-
method_option :tags, type: :array, desc: "tags"
|
12
|
-
def shodan(query)
|
13
|
-
with_error_handling do
|
14
|
-
run_analyzer Analyzers::Shodan, query: query, options: options
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Mihari
|
4
|
-
module Commands
|
5
|
-
module Spyse
|
6
|
-
def self.included(thor)
|
7
|
-
thor.class_eval do
|
8
|
-
desc "spyse [QUERY]", "Spyse search"
|
9
|
-
method_option :title, type: :string, desc: "title"
|
10
|
-
method_option :description, type: :string, desc: "description"
|
11
|
-
method_option :tags, type: :array, desc: "tags"
|
12
|
-
method_option :type, type: :string, desc: "type to search (ip or domain)", default: "doamin"
|
13
|
-
def spyse(query)
|
14
|
-
with_error_handling do
|
15
|
-
run_analyzer Analyzers::Spyse, query: query, options: options
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Mihari
|
4
|
-
module Commands
|
5
|
-
module Urlscan
|
6
|
-
def self.included(thor)
|
7
|
-
thor.class_eval do
|
8
|
-
desc "urlscan [QUERY]", "urlscan search"
|
9
|
-
method_option :title, type: :string, desc: "title"
|
10
|
-
method_option :description, type: :string, desc: "description"
|
11
|
-
method_option :tags, type: :array, desc: "tags"
|
12
|
-
method_option :allowed_data_types, type: :array, default: ["url", "ip", "domain"], desc: "types to fetch from search results ('url', 'domain' or 'ip')"
|
13
|
-
def urlscan(query)
|
14
|
-
with_error_handling do
|
15
|
-
run_analyzer Analyzers::Urlscan, query: query, options: options
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Mihari
|
4
|
-
module Commands
|
5
|
-
module VirusTotal
|
6
|
-
def self.included(thor)
|
7
|
-
thor.class_eval do
|
8
|
-
desc "virustotal [IP|DOMAIN]", "VirusTotal resolutions search by an ip or domain"
|
9
|
-
method_option :title, type: :string, desc: "title"
|
10
|
-
method_option :description, type: :string, desc: "description"
|
11
|
-
method_option :tags, type: :array, desc: "tags"
|
12
|
-
def virustotal(indiactor)
|
13
|
-
with_error_handling do
|
14
|
-
run_analyzer Analyzers::VirusTotal, query: indiactor, options: options
|
15
|
-
end
|
16
|
-
end
|
17
|
-
map "vt" => :virustotal
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Mihari
|
4
|
-
module Commands
|
5
|
-
module VirusTotalIntelligence
|
6
|
-
def self.included(thor)
|
7
|
-
thor.class_eval do
|
8
|
-
desc "virustotal_intelligence [QUERY]", "VirusTotal Intelligence search"
|
9
|
-
method_option :title, type: :string, desc: "title"
|
10
|
-
method_option :description, type: :string, desc: "description"
|
11
|
-
method_option :tags, type: :array, desc: "tags"
|
12
|
-
def virustotal_intelligence(query)
|
13
|
-
with_error_handling do
|
14
|
-
run_analyzer Analyzers::VirusTotalIntelligence, query: query, options: options
|
15
|
-
end
|
16
|
-
end
|
17
|
-
map "vt_intel" => :virustotal_intelligence
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Mihari
|
4
|
-
module Commands
|
5
|
-
module ZoomEye
|
6
|
-
def self.included(thor)
|
7
|
-
thor.class_eval do
|
8
|
-
desc "zoomeye [QUERY]", "ZoomEye search"
|
9
|
-
method_option :title, type: :string, desc: "title"
|
10
|
-
method_option :description, type: :string, desc: "description"
|
11
|
-
method_option :tags, type: :array, desc: "tags"
|
12
|
-
method_option :type, type: :string, desc: "type to search(host / web)", default: "host"
|
13
|
-
def zoomeye(query)
|
14
|
-
with_error_handling do
|
15
|
-
run_analyzer Analyzers::ZoomEye, query: query, options: options
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
@@ -1,100 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "colorize"
|
4
|
-
require "yaml"
|
5
|
-
|
6
|
-
module Mihari
|
7
|
-
module Mixins
|
8
|
-
module Configuration
|
9
|
-
#
|
10
|
-
# Load config file into hash
|
11
|
-
#
|
12
|
-
# @param [String] path Path to YAML file
|
13
|
-
#
|
14
|
-
# @return [Hash]
|
15
|
-
#
|
16
|
-
def load_config(path)
|
17
|
-
data = _load_config(path)
|
18
|
-
data.transform_keys(&:downcase)
|
19
|
-
end
|
20
|
-
|
21
|
-
#
|
22
|
-
# Validate config schema
|
23
|
-
#
|
24
|
-
# @param [Hash] config
|
25
|
-
#
|
26
|
-
def validate_config(config)
|
27
|
-
error_message = "Failed to parse the input as a config!"
|
28
|
-
|
29
|
-
contract = Schemas::ConfigurationContract.new
|
30
|
-
result = contract.call(config)
|
31
|
-
unless result.errors.empty?
|
32
|
-
puts error_message.colorize(:red)
|
33
|
-
show_validation_errors result.errors
|
34
|
-
raise ArgumentError, "Invalid config schema"
|
35
|
-
end
|
36
|
-
|
37
|
-
# check keys
|
38
|
-
# TODO: check keys with dry-schema
|
39
|
-
valid_keys = Mihari.config.values.keys
|
40
|
-
config.each_key do |key|
|
41
|
-
unless valid_keys.include?(key)
|
42
|
-
puts error_message.colorize(:red)
|
43
|
-
raise ArgumentError, "#{key} is not a valid key."
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
#
|
49
|
-
# Returns a template for config
|
50
|
-
#
|
51
|
-
# @return [String] A template for config
|
52
|
-
#
|
53
|
-
def config_template
|
54
|
-
config = Mihari.config.values.keys.to_h do |key|
|
55
|
-
[key.to_s, nil]
|
56
|
-
end
|
57
|
-
|
58
|
-
YAML.dump(config)
|
59
|
-
end
|
60
|
-
|
61
|
-
#
|
62
|
-
# Create (blank) config file
|
63
|
-
#
|
64
|
-
# @param [String] filename
|
65
|
-
# @param [Dry::Files] files
|
66
|
-
# @param [String] template
|
67
|
-
#
|
68
|
-
# @return [nil]
|
69
|
-
#
|
70
|
-
def initialize_config_yaml(filename, files = Dry::Files.new, template: config_template)
|
71
|
-
files.write(filename, template)
|
72
|
-
end
|
73
|
-
|
74
|
-
private
|
75
|
-
|
76
|
-
def show_validation_errors(errors)
|
77
|
-
errors.messages.each do |message|
|
78
|
-
path = message.path.map(&:to_s).join
|
79
|
-
puts "- #{path} #{message.text}".colorize(:red)
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
#
|
84
|
-
# Load configuration file
|
85
|
-
#
|
86
|
-
# @param [String] path
|
87
|
-
#
|
88
|
-
# @return [Hash]
|
89
|
-
#
|
90
|
-
def _load_config(path)
|
91
|
-
unless Pathname(path).exist?
|
92
|
-
puts "#{path} does not exist".colorize(:red)
|
93
|
-
raise FileNotFoundError
|
94
|
-
end
|
95
|
-
|
96
|
-
YAML.safe_load(File.read(path), symbolize_names: true)
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
data/lib/mihari/mixins/hash.rb
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "cymbal"
|
4
|
-
|
5
|
-
module Mihari
|
6
|
-
module Mixins
|
7
|
-
module Hash
|
8
|
-
#
|
9
|
-
# Symbolize hash keys
|
10
|
-
#
|
11
|
-
# @param [Hash] hash
|
12
|
-
#
|
13
|
-
# @return [Hash]
|
14
|
-
#
|
15
|
-
def symbolize_hash(hash)
|
16
|
-
Cymbal.symbolize hash
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
@@ -1,44 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "dry/schema"
|
4
|
-
require "dry/validation"
|
5
|
-
|
6
|
-
require "mihari/schemas/macros"
|
7
|
-
|
8
|
-
module Mihari
|
9
|
-
module Schemas
|
10
|
-
Configuration = Dry::Schema.Params do
|
11
|
-
optional(:binaryedge_api_key).value(:string)
|
12
|
-
optional(:censys_id).value(:string)
|
13
|
-
optional(:censys_secret).value(:string)
|
14
|
-
optional(:circl_passive_password).value(:string)
|
15
|
-
optional(:circl_passive_username).value(:string)
|
16
|
-
optional(:database).value(:string)
|
17
|
-
optional(:greynoise_api_key).value(:string)
|
18
|
-
optional(:ipinfo_api_key).value(:string)
|
19
|
-
optional(:misp_api_endpoint).value(:string)
|
20
|
-
optional(:misp_api_key).value(:string)
|
21
|
-
optional(:onyphe_api_key).value(:string)
|
22
|
-
optional(:otx_api_key).value(:string)
|
23
|
-
optional(:passivetotal_api_key).value(:string)
|
24
|
-
optional(:passivetotal_username).value(:string)
|
25
|
-
optional(:pulsedive_api_key).value(:string)
|
26
|
-
optional(:securitytrails_api_key).value(:string)
|
27
|
-
optional(:shodan_api_key).value(:string)
|
28
|
-
optional(:slack_channel).value(:string)
|
29
|
-
optional(:slack_webhook_url).value(:string)
|
30
|
-
optional(:spyse_api_key).value(:string)
|
31
|
-
optional(:thehive_api_endpoint).value(:string)
|
32
|
-
optional(:thehive_api_key).value(:string)
|
33
|
-
optional(:urlscan_api_key).value(:string)
|
34
|
-
optional(:virustotal_api_key).value(:string)
|
35
|
-
optional(:webhook_url).value(:string)
|
36
|
-
optional(:webhook_use_json_body).value(:bool)
|
37
|
-
optional(:zoomeye_api_key).value(:string)
|
38
|
-
end
|
39
|
-
|
40
|
-
class ConfigurationContract < Dry::Validation::Contract
|
41
|
-
params(Configuration)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
@@ -1,73 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "launchy"
|
4
|
-
require "rack"
|
5
|
-
require "rack/contrib"
|
6
|
-
require "rack/handler/puma"
|
7
|
-
require "rack/cors"
|
8
|
-
|
9
|
-
require "grape"
|
10
|
-
require "grape-swagger"
|
11
|
-
|
12
|
-
require "mihari/web/apis/ping"
|
13
|
-
|
14
|
-
module Mihari
|
15
|
-
class API < Grape::API
|
16
|
-
prefix "api"
|
17
|
-
format :json
|
18
|
-
mount Apis::Ping
|
19
|
-
add_swagger_documentation api_version: "v1"
|
20
|
-
end
|
21
|
-
|
22
|
-
class GrapeApp
|
23
|
-
def initialize
|
24
|
-
@filenames = ["", ".html", "index.html", "/index.html"]
|
25
|
-
@rack_static = ::Rack::Static.new(
|
26
|
-
lambda { [404, {}, []] },
|
27
|
-
root: File.expand_path("public", __dir__),
|
28
|
-
urls: ["/"]
|
29
|
-
)
|
30
|
-
end
|
31
|
-
|
32
|
-
class << self
|
33
|
-
def instance
|
34
|
-
@instance ||= Rack::Builder.new do
|
35
|
-
run GrapeApp.new
|
36
|
-
end.to_app
|
37
|
-
end
|
38
|
-
|
39
|
-
def run!(port: 9292, host: "localhost", threads: "0:16", verbose: false)
|
40
|
-
url = "http://#{host}:#{port}"
|
41
|
-
|
42
|
-
Rack::Handler::Puma.run(instance, Port: port, Host: host, Threads: threads, Verbose: verbose) do |server|
|
43
|
-
p ENV["RACK_ENV"]
|
44
|
-
p instance.class
|
45
|
-
|
46
|
-
Launchy.open(url) if ENV["RACK_ENV"] != "development"
|
47
|
-
|
48
|
-
[:INT, :TERM].each do |sig|
|
49
|
-
trap(sig) do
|
50
|
-
server.shutdown
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
def call(env)
|
58
|
-
# api
|
59
|
-
p GrapeApp.instance
|
60
|
-
response = API.call(env)
|
61
|
-
|
62
|
-
# Check if the App wants us to pass the response along to others
|
63
|
-
if response[1]["X-Cascade"] == "pass"
|
64
|
-
# static files
|
65
|
-
request_path = env["PATH_INFO"]
|
66
|
-
@filenames.each do |path|
|
67
|
-
response = @rack_static.call(env.merge("PATH_INFO" => request_path + path))
|
68
|
-
return response if response[0] != 404
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
module Mihari
|
2
|
-
module Analyzers
|
3
|
-
class Basic < Base
|
4
|
-
attr_reader title: String
|
5
|
-
|
6
|
-
attr_reader description: String
|
7
|
-
|
8
|
-
attr_reader artifacts: (Array[String] | Array[Mihari::Artifact])
|
9
|
-
|
10
|
-
attr_reader source: String
|
11
|
-
|
12
|
-
attr_reader tags: Array[String]?
|
13
|
-
|
14
|
-
def initialize: (title: String title, description: String description, artifacts: (Array[String] | Array[Mihari::Artifact]) artifacts, source: String source, ?tags: Array[String] tags) -> void
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
@@ -1,43 +0,0 @@
|
|
1
|
-
module Mihari
|
2
|
-
module CLI
|
3
|
-
class Analyzer < Base
|
4
|
-
include Mihari::Commands::BinaryEdge
|
5
|
-
|
6
|
-
include Mihari::Commands::Censys
|
7
|
-
|
8
|
-
include Mihari::Commands::CIRCL
|
9
|
-
|
10
|
-
include Mihari::Commands::Crtsh
|
11
|
-
|
12
|
-
include Mihari::Commands::DNPedia
|
13
|
-
|
14
|
-
include Mihari::Commands::DNSTwister
|
15
|
-
|
16
|
-
include Mihari::Commands::Feed
|
17
|
-
|
18
|
-
include Mihari::Commands::GreyNoise
|
19
|
-
|
20
|
-
include Mihari::Commands::JSON
|
21
|
-
|
22
|
-
include Mihari::Commands::Onyphe
|
23
|
-
|
24
|
-
include Mihari::Commands::OTX
|
25
|
-
|
26
|
-
include Mihari::Commands::PassiveTotal
|
27
|
-
|
28
|
-
include Mihari::Commands::Pulsedive
|
29
|
-
|
30
|
-
include Mihari::Commands::SecurityTrails
|
31
|
-
|
32
|
-
include Mihari::Commands::Shodan
|
33
|
-
|
34
|
-
include Mihari::Commands::Spyse
|
35
|
-
|
36
|
-
include Mihari::Commands::Urlscan
|
37
|
-
|
38
|
-
include Mihari::Commands::VirusTotal
|
39
|
-
|
40
|
-
include Mihari::Commands::ZoomEye
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|