mihari 2.4.0 → 3.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/.gitignore +7 -0
- data/.overcommit.yml +12 -0
- data/README.md +1 -9
- data/build_frontend.sh +5 -0
- data/docker/Dockerfile +1 -1
- data/exe/mihari +1 -1
- data/lib/mihari.rb +89 -15
- data/lib/mihari/analyzers/base.rb +49 -8
- data/lib/mihari/analyzers/basic.rb +1 -2
- data/lib/mihari/analyzers/binaryedge.rb +7 -13
- data/lib/mihari/analyzers/censys.rb +26 -63
- data/lib/mihari/analyzers/circl.rb +20 -17
- data/lib/mihari/analyzers/crtsh.rb +6 -13
- data/lib/mihari/analyzers/dnpedia.rb +6 -12
- data/lib/mihari/analyzers/dnstwister.rb +13 -10
- data/lib/mihari/analyzers/onyphe.rb +6 -12
- data/lib/mihari/analyzers/otx.rb +22 -19
- data/lib/mihari/analyzers/passivetotal.rb +22 -21
- data/lib/mihari/analyzers/pulsedive.rb +16 -13
- data/lib/mihari/analyzers/rule.rb +97 -0
- data/lib/mihari/analyzers/securitytrails.rb +22 -19
- data/lib/mihari/analyzers/shodan.rb +7 -13
- data/lib/mihari/analyzers/spyse.rb +12 -19
- data/lib/mihari/analyzers/urlscan.rb +22 -27
- data/lib/mihari/analyzers/virustotal.rb +25 -22
- data/lib/mihari/analyzers/zoomeye.rb +14 -20
- data/lib/mihari/cli/analyzer.rb +44 -0
- data/lib/mihari/cli/base.rb +27 -0
- data/lib/mihari/cli/init.rb +13 -0
- data/lib/mihari/cli/main.rb +30 -0
- data/lib/mihari/cli/mixins/utils.rb +88 -0
- data/lib/mihari/cli/validator.rb +11 -0
- data/lib/mihari/commands/binaryedge.rb +1 -1
- data/lib/mihari/commands/censys.rb +1 -1
- data/lib/mihari/commands/circl.rb +2 -2
- data/lib/mihari/commands/crtsh.rb +1 -1
- data/lib/mihari/commands/dnpedia.rb +1 -1
- data/lib/mihari/commands/dnstwister.rb +2 -2
- data/lib/mihari/commands/init.rb +46 -0
- data/lib/mihari/commands/json.rb +1 -1
- data/lib/mihari/commands/onyphe.rb +1 -1
- data/lib/mihari/commands/otx.rb +2 -2
- data/lib/mihari/commands/passivetotal.rb +2 -2
- data/lib/mihari/commands/pulsedive.rb +2 -2
- data/lib/mihari/commands/search.rb +77 -0
- data/lib/mihari/commands/securitytrails.rb +2 -2
- data/lib/mihari/commands/shodan.rb +1 -1
- data/lib/mihari/commands/spyse.rb +1 -1
- data/lib/mihari/commands/urlscan.rb +2 -2
- data/lib/mihari/commands/validator.rb +38 -0
- data/lib/mihari/commands/virustotal.rb +2 -2
- data/lib/mihari/commands/zoomeye.rb +1 -1
- data/lib/mihari/constraints.rb +5 -0
- data/lib/mihari/database.rb +13 -2
- data/lib/mihari/emitters/base.rb +2 -2
- data/lib/mihari/emitters/database.rb +1 -1
- data/lib/mihari/emitters/misp.rb +3 -1
- data/lib/mihari/emitters/slack.rb +6 -7
- data/lib/mihari/emitters/the_hive.rb +1 -1
- data/lib/mihari/emitters/webhook.rb +2 -9
- data/lib/mihari/mixins/configurable.rb +38 -0
- data/lib/mihari/mixins/configuration.rb +90 -0
- data/lib/mihari/mixins/hash.rb +20 -0
- data/lib/mihari/mixins/refang.rb +21 -0
- data/lib/mihari/mixins/retriable.rb +27 -0
- data/lib/mihari/mixins/rule.rb +79 -0
- data/lib/mihari/models/alert.rb +28 -1
- data/lib/mihari/models/artifact.rb +11 -1
- data/lib/mihari/notifiers/base.rb +9 -1
- data/lib/mihari/notifiers/exception_notifier.rb +50 -0
- data/lib/mihari/notifiers/slack.rb +29 -0
- data/lib/mihari/schemas/analyzer.rb +25 -0
- data/lib/mihari/schemas/configuration.rb +42 -0
- data/lib/mihari/schemas/macros.rb +17 -0
- data/lib/mihari/schemas/rule.rb +72 -0
- data/lib/mihari/serializers/artifact.rb +1 -1
- data/lib/mihari/status.rb +14 -0
- data/lib/mihari/templates/rule.yml.erb +19 -0
- data/lib/mihari/type_checker.rb +8 -3
- data/lib/mihari/version.rb +1 -1
- data/lib/mihari/web/app.rb +2 -1
- data/lib/mihari/web/controllers/analyzers_controller.rb +38 -0
- data/lib/mihari/web/controllers/base_controller.rb +1 -1
- data/lib/mihari/web/public/index.html +1 -21
- data/lib/mihari/web/public/redoc-static.html +338 -461
- data/lib/mihari/web/public/static/js/app.365f1907.js +13 -0
- data/lib/mihari/web/public/static/js/app.365f1907.js.map +1 -0
- data/lib/mihari/web/public/static/js/app.ab213f7c.js +12 -0
- data/lib/mihari/web/public/static/js/app.ab213f7c.js.map +1 -0
- data/mihari.gemspec +16 -9
- metadata +135 -58
- data/.rubocop.yml +0 -161
- data/lib/mihari/analyzers/free_text.rb +0 -48
- data/lib/mihari/analyzers/http_hash.rb +0 -100
- data/lib/mihari/analyzers/passive_dns.rb +0 -59
- data/lib/mihari/analyzers/passive_ssl.rb +0 -55
- data/lib/mihari/analyzers/reverse_whois.rb +0 -55
- data/lib/mihari/analyzers/securitytrails_domain_feed.rb +0 -59
- data/lib/mihari/analyzers/ssh_fingerprint.rb +0 -58
- data/lib/mihari/cli.rb +0 -126
- data/lib/mihari/commands/config.rb +0 -27
- data/lib/mihari/commands/free_text.rb +0 -21
- data/lib/mihari/commands/http_hash.rb +0 -25
- data/lib/mihari/commands/passive_dns.rb +0 -21
- data/lib/mihari/commands/passive_ssl.rb +0 -21
- data/lib/mihari/commands/reverse_whois.rb +0 -21
- data/lib/mihari/commands/securitytrails_domain_feed.rb +0 -23
- data/lib/mihari/commands/ssh_fingerprint.rb +0 -21
- data/lib/mihari/config.rb +0 -85
- data/lib/mihari/configurable.rb +0 -21
- data/lib/mihari/html.rb +0 -43
- data/lib/mihari/retriable.rb +0 -17
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "securitytrails"
|
|
4
|
-
|
|
5
|
-
module Mihari
|
|
6
|
-
module Analyzers
|
|
7
|
-
class SecurityTrailsDomainFeed < Base
|
|
8
|
-
attr_reader :type, :title, :description, :tags
|
|
9
|
-
|
|
10
|
-
def initialize(regexp, type: "registered", title: nil, description: nil, tags: [])
|
|
11
|
-
super()
|
|
12
|
-
|
|
13
|
-
@_regexp = regexp
|
|
14
|
-
@type = type
|
|
15
|
-
|
|
16
|
-
raise InvalidInputError, "#{@_regexp} is not a valid regexp" unless regexp
|
|
17
|
-
raise InvalidInputError, "#{type} is not a valid type" unless valid_type?
|
|
18
|
-
|
|
19
|
-
@title = title || "SecurityTrails domain feed lookup"
|
|
20
|
-
@description = description || "Regexp = /#{@_regexp}/"
|
|
21
|
-
@tags = tags
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def artifacts
|
|
25
|
-
lookup || []
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
private
|
|
29
|
-
|
|
30
|
-
def config_keys
|
|
31
|
-
%w[securitytrails_api_key]
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def api
|
|
35
|
-
@api ||= ::SecurityTrails::API.new(Mihari.config.securitytrails_api_key)
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def valid_type?
|
|
39
|
-
%w[all new registered].include? type
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def regexp
|
|
43
|
-
@regexp ||= Regexp.compile(@_regexp)
|
|
44
|
-
rescue InvalidInputError => _e
|
|
45
|
-
nil
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
def lookup
|
|
49
|
-
new_domains.select do |domain|
|
|
50
|
-
regexp.match? domain
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
def new_domains
|
|
55
|
-
api.feeds.domains type
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
end
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "parallel"
|
|
4
|
-
|
|
5
|
-
module Mihari
|
|
6
|
-
module Analyzers
|
|
7
|
-
class SSHFingerprint < Base
|
|
8
|
-
attr_reader :fingerprint, :title, :description, :tags
|
|
9
|
-
|
|
10
|
-
def initialize(fingerprint, title: nil, description: nil, tags: [])
|
|
11
|
-
super()
|
|
12
|
-
|
|
13
|
-
@fingerprint = fingerprint
|
|
14
|
-
|
|
15
|
-
@title = title || "SSH fingerprint cross search"
|
|
16
|
-
@description = description || "fingerprint = #{fingerprint}"
|
|
17
|
-
@tags = tags
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def artifacts
|
|
21
|
-
Parallel.map(analyzers) do |analyzer|
|
|
22
|
-
run_analyzer analyzer
|
|
23
|
-
end.flatten
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
private
|
|
27
|
-
|
|
28
|
-
def valid_fingerprint?
|
|
29
|
-
/^([0-9a-f]{2}:){15}[0-9a-f]{2}$/.match? fingerprint
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def binary_edge
|
|
33
|
-
BinaryEdge.new "ssh.fingerprint:\"#{fingerprint}\""
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def shodan
|
|
37
|
-
Shodan.new fingerprint
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def analyzers
|
|
41
|
-
raise InvalidInputError, "Invalid fingerprint is given." unless valid_fingerprint?
|
|
42
|
-
|
|
43
|
-
[
|
|
44
|
-
binary_edge,
|
|
45
|
-
shodan
|
|
46
|
-
].compact
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
def run_analyzer(analyzer)
|
|
50
|
-
analyzer.artifacts
|
|
51
|
-
rescue ArgumentError, InvalidInputError => _e
|
|
52
|
-
nil
|
|
53
|
-
rescue ::BinaryEdge::Error, ::Shodan::Error => _e
|
|
54
|
-
nil
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
end
|
data/lib/mihari/cli.rb
DELETED
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "thor"
|
|
4
|
-
|
|
5
|
-
require "mihari/commands/binaryedge"
|
|
6
|
-
require "mihari/commands/censys"
|
|
7
|
-
require "mihari/commands/circl"
|
|
8
|
-
require "mihari/commands/crtsh"
|
|
9
|
-
require "mihari/commands/dnpedia"
|
|
10
|
-
require "mihari/commands/dnstwister"
|
|
11
|
-
require "mihari/commands/onyphe"
|
|
12
|
-
require "mihari/commands/otx"
|
|
13
|
-
require "mihari/commands/passivetotal"
|
|
14
|
-
require "mihari/commands/pulsedive"
|
|
15
|
-
require "mihari/commands/securitytrails_domain_feed"
|
|
16
|
-
require "mihari/commands/securitytrails"
|
|
17
|
-
require "mihari/commands/shodan"
|
|
18
|
-
require "mihari/commands/spyse"
|
|
19
|
-
require "mihari/commands/urlscan"
|
|
20
|
-
require "mihari/commands/virustotal"
|
|
21
|
-
require "mihari/commands/zoomeye"
|
|
22
|
-
|
|
23
|
-
require "mihari/commands/free_text"
|
|
24
|
-
require "mihari/commands/http_hash"
|
|
25
|
-
require "mihari/commands/passive_dns"
|
|
26
|
-
require "mihari/commands/passive_ssl"
|
|
27
|
-
require "mihari/commands/reverse_whois"
|
|
28
|
-
require "mihari/commands/ssh_fingerprint"
|
|
29
|
-
|
|
30
|
-
require "mihari/commands/config"
|
|
31
|
-
require "mihari/commands/json"
|
|
32
|
-
require "mihari/commands/web"
|
|
33
|
-
|
|
34
|
-
module Mihari
|
|
35
|
-
class CLI < Thor
|
|
36
|
-
class_option :config, type: :string, desc: "Path to the config file"
|
|
37
|
-
|
|
38
|
-
class_option :ignore_old_artifacts, type: :boolean, default: false, desc: "Whether to ignore old artifacts from checking or not. Only affects with analyze commands."
|
|
39
|
-
class_option :ignore_threshold, type: :numeric, default: 0, desc: "Number of days to define whether an artifact is old or not. Only affects with analyze commands."
|
|
40
|
-
|
|
41
|
-
include Mihari::Commands::BinaryEdge
|
|
42
|
-
include Mihari::Commands::Censys
|
|
43
|
-
include Mihari::Commands::CIRCL
|
|
44
|
-
include Mihari::Commands::Config
|
|
45
|
-
include Mihari::Commands::Crtsh
|
|
46
|
-
include Mihari::Commands::DNPedia
|
|
47
|
-
include Mihari::Commands::DNSTwister
|
|
48
|
-
include Mihari::Commands::FreeText
|
|
49
|
-
include Mihari::Commands::HTTPHash
|
|
50
|
-
include Mihari::Commands::JSON
|
|
51
|
-
include Mihari::Commands::Onyphe
|
|
52
|
-
include Mihari::Commands::OTX
|
|
53
|
-
include Mihari::Commands::PassiveDNS
|
|
54
|
-
include Mihari::Commands::PassiveSSL
|
|
55
|
-
include Mihari::Commands::PassiveTotal
|
|
56
|
-
include Mihari::Commands::Pulsedive
|
|
57
|
-
include Mihari::Commands::ReverseWhois
|
|
58
|
-
include Mihari::Commands::SecurityTrails
|
|
59
|
-
include Mihari::Commands::SecurityTrailsDomainFeed
|
|
60
|
-
include Mihari::Commands::Shodan
|
|
61
|
-
include Mihari::Commands::Spyse
|
|
62
|
-
include Mihari::Commands::SSHFingerprint
|
|
63
|
-
include Mihari::Commands::Urlscan
|
|
64
|
-
include Mihari::Commands::VirusTotal
|
|
65
|
-
include Mihari::Commands::Web
|
|
66
|
-
include Mihari::Commands::ZoomEye
|
|
67
|
-
|
|
68
|
-
class << self
|
|
69
|
-
def exit_on_failure?
|
|
70
|
-
true
|
|
71
|
-
end
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
no_commands do
|
|
75
|
-
def with_error_handling
|
|
76
|
-
yield
|
|
77
|
-
rescue StandardError => e
|
|
78
|
-
notifier = Notifiers::ExceptionNotifier.new
|
|
79
|
-
notifier.notify e
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
# @return [true, false]
|
|
83
|
-
def valid_json?(json)
|
|
84
|
-
%w[title description artifacts].all? { |key| json.key? key }
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
def load_configuration
|
|
88
|
-
config = options["config"]
|
|
89
|
-
return unless config
|
|
90
|
-
|
|
91
|
-
Config.load_from_yaml(config)
|
|
92
|
-
Database.connect
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
def run_analyzer(analyzer_class, query:, options:)
|
|
96
|
-
load_configuration
|
|
97
|
-
|
|
98
|
-
options = symbolize_hash_keys(options)
|
|
99
|
-
options = normalize_options(options)
|
|
100
|
-
|
|
101
|
-
analyzer = analyzer_class.new(query, **options)
|
|
102
|
-
|
|
103
|
-
analyzer.ignore_old_artifacts = options[:ignore_old_artifacts] || false
|
|
104
|
-
analyzer.ignore_threshold = options[:ignore_threshold] || 0
|
|
105
|
-
|
|
106
|
-
analyzer.run
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
def symbolize_hash_keys(hash)
|
|
110
|
-
hash.transform_keys(&:to_sym)
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
def normalize_options(options)
|
|
114
|
-
# Delete :config because it is not intended to use for running an analyzer
|
|
115
|
-
[:config, :ignore_old_artifacts, :ignore_threshold].each do |ignore_key|
|
|
116
|
-
options.delete(ignore_key)
|
|
117
|
-
end
|
|
118
|
-
options
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
def refang(indicator)
|
|
122
|
-
indicator.gsub("[.]", ".").gsub("(.)", ".")
|
|
123
|
-
end
|
|
124
|
-
end
|
|
125
|
-
end
|
|
126
|
-
end
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "colorize"
|
|
4
|
-
|
|
5
|
-
module Mihari
|
|
6
|
-
module Commands
|
|
7
|
-
module Config
|
|
8
|
-
def self.included(thor)
|
|
9
|
-
thor.class_eval do
|
|
10
|
-
desc "init_config", "Create a config file"
|
|
11
|
-
method_option :filename, type: :string, default: "mihari.yml"
|
|
12
|
-
def init_config
|
|
13
|
-
filename = options["filename"]
|
|
14
|
-
|
|
15
|
-
warning = "#{filename} exists. Do you want to overwrite it? (y/n)"
|
|
16
|
-
if File.exist?(filename) && !(yes? warning)
|
|
17
|
-
return
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
Mihari::Config.initialize_yaml filename
|
|
21
|
-
puts "The config file is initialized as #{filename}.".colorize(:blue)
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
end
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Mihari
|
|
4
|
-
module Commands
|
|
5
|
-
module FreeText
|
|
6
|
-
def self.included(thor)
|
|
7
|
-
thor.class_eval do
|
|
8
|
-
desc "free_text [TEXT]", "Cross search with search engines by a free text"
|
|
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 free_text(text)
|
|
13
|
-
with_error_handling do
|
|
14
|
-
run_analyzer Analyzers::FreeText, query: text, options: options
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
end
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Mihari
|
|
4
|
-
module Commands
|
|
5
|
-
module HTTPHash
|
|
6
|
-
def self.included(thor)
|
|
7
|
-
thor.class_eval do
|
|
8
|
-
desc "http_hash", "Cross search with search engines by a hash of an HTTP response (SHA256, MD5 and MurmurHash3)"
|
|
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 :md5, type: :string, desc: "MD5 hash"
|
|
13
|
-
method_option :sha256, type: :string, desc: "SHA256 hash"
|
|
14
|
-
method_option :mmh3, type: :numeric, desc: "MurmurHash3 hash"
|
|
15
|
-
method_option :html, type: :string, desc: "path to an HTML file"
|
|
16
|
-
def http_hash
|
|
17
|
-
with_error_handling do
|
|
18
|
-
run_analyzer Analyzers::HTTPHash, query: nil, options: options
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
end
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Mihari
|
|
4
|
-
module Commands
|
|
5
|
-
module PassiveDNS
|
|
6
|
-
def self.included(thor)
|
|
7
|
-
thor.class_eval do
|
|
8
|
-
desc "passive_dns [IP|DOMAIN]", "Cross search with passive DNS services 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 passive_dns(query)
|
|
13
|
-
with_error_handling do
|
|
14
|
-
run_analyzer Analyzers::PassiveDNS, query: refang(query), options: options
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
end
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Mihari
|
|
4
|
-
module Commands
|
|
5
|
-
module PassiveSSL
|
|
6
|
-
def self.included(thor)
|
|
7
|
-
thor.class_eval do
|
|
8
|
-
desc "passive_ssl [SHA1]", "Cross search with passive SSL services by an 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 passive_ssl(query)
|
|
13
|
-
with_error_handling do
|
|
14
|
-
run_analyzer Analyzers::PassiveSSL, query: query, options: options
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
end
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Mihari
|
|
4
|
-
module Commands
|
|
5
|
-
module ReverseWhois
|
|
6
|
-
def self.included(thor)
|
|
7
|
-
thor.class_eval do
|
|
8
|
-
desc "reverse_whois [EMAIL]", "Cross search with reverse whois services by an 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 reverse_whois(query)
|
|
13
|
-
with_error_handling do
|
|
14
|
-
run_analyzer Analyzers::ReveseWhois, query: refang(query), options: options
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
end
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Mihari
|
|
4
|
-
module Commands
|
|
5
|
-
module SecurityTrailsDomainFeed
|
|
6
|
-
def self.included(thor)
|
|
7
|
-
thor.class_eval do
|
|
8
|
-
desc "securitytrails_domain_feed [REGEXP]", "SecurityTrails new domain feed search by a regexp"
|
|
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, default: "registered", desc: "A type of domain feed ('all', 'new' or 'registered')"
|
|
13
|
-
def securitytrails_domain_feed(regexp)
|
|
14
|
-
with_error_handling do
|
|
15
|
-
run_analyzer Analyzers::SecurityTrailsDomainFeed, query: regexp, options: options
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
map "st_domain_feed" => :securitytrails_domain_feedd
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
end
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Mihari
|
|
4
|
-
module Commands
|
|
5
|
-
module SSHFingerprint
|
|
6
|
-
def self.included(thor)
|
|
7
|
-
thor.class_eval do
|
|
8
|
-
desc "ssh_fingerprint [FINGERPRINT]", "Cross search with search engines by an SSH fingerprint (e.g. dc:14:de:8e:d7:c1:15:43:23:82:25:81:d2:59:e8:c0)"
|
|
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 ssh_fingerprint(fingerprint)
|
|
13
|
-
with_error_handling do
|
|
14
|
-
run_analyzer Analyzers::SSHFingerprint, query: fingerprint, options: options
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
end
|
data/lib/mihari/config.rb
DELETED
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "yaml"
|
|
4
|
-
|
|
5
|
-
module Mihari
|
|
6
|
-
class Config
|
|
7
|
-
attr_accessor :binaryedge_api_key, :censys_id, :censys_secret, :circl_passive_password, :circl_passive_username, :misp_api_endpoint, :misp_api_key, :onyphe_api_key, :otx_api_key, :passivetotal_api_key, :passivetotal_username, :pulsedive_api_key, :securitytrails_api_key, :shodan_api_key, :slack_channel, :slack_webhook_url, :spyse_api_key, :thehive_api_endpoint, :thehive_api_key, :urlscan_api_key, :virustotal_api_key, :zoomeye_api_key, :webhook_url, :webhook_use_json_body, :database
|
|
8
|
-
|
|
9
|
-
def initialize
|
|
10
|
-
load_from_env
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def load_from_env
|
|
14
|
-
@binaryedge_api_key = ENV["BINARYEDGE_API_KEY"]
|
|
15
|
-
@censys_id = ENV["CENSYS_ID"]
|
|
16
|
-
@censys_secret = ENV["CENSYS_SECRET"]
|
|
17
|
-
@circl_passive_password = ENV["CIRCL_PASSIVE_PASSWORD"]
|
|
18
|
-
@circl_passive_username = ENV["CIRCL_PASSIVE_USERNAME"]
|
|
19
|
-
@misp_api_endpoint = ENV["MISP_API_ENDPOINT"]
|
|
20
|
-
@misp_api_key = ENV["MISP_API_KEY"]
|
|
21
|
-
@onyphe_api_key = ENV["ONYPHE_API_KEY"]
|
|
22
|
-
@otx_api_key = ENV["OTX_API_KEY"]
|
|
23
|
-
@passivetotal_api_key = ENV["PASSIVETOTAL_API_KEY"]
|
|
24
|
-
@passivetotal_username = ENV["PASSIVETOTAL_USERNAME"]
|
|
25
|
-
@pulsedive_api_key = ENV["PULSEDIVE_API_KEY"]
|
|
26
|
-
@securitytrails_api_key = ENV["SECURITYTRAILS_API_KEY"]
|
|
27
|
-
@shodan_api_key = ENV["SHODAN_API_KEY"]
|
|
28
|
-
@slack_channel = ENV["SLACK_CHANNEL"]
|
|
29
|
-
@slack_webhook_url = ENV["SLACK_WEBHOOK_URL"]
|
|
30
|
-
@spyse_api_key = ENV["SPYSE_API_KEY"]
|
|
31
|
-
@thehive_api_endpoint = ENV["THEHIVE_API_ENDPOINT"]
|
|
32
|
-
@thehive_api_key = ENV["THEHIVE_API_KEY"]
|
|
33
|
-
@urlscan_api_key = ENV["URLSCAN_API_KEY"]
|
|
34
|
-
@virustotal_api_key = ENV["VIRUSTOTAL_API_KEY"]
|
|
35
|
-
@zoomeye_api_key = ENV["ZOOMEYE_API_KEY"]
|
|
36
|
-
@webhook_url = ENV["WEBHOOK_URL"]
|
|
37
|
-
@webhook_use_json_body = ENV["WEBHOOK_USE_JSON_BODY"]
|
|
38
|
-
|
|
39
|
-
@database = ENV["DATABASE"] || "mihari.db"
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
class << self
|
|
43
|
-
def load_from_yaml(path)
|
|
44
|
-
raise ArgumentError, "#{path} does not exist." unless File.exist?(path)
|
|
45
|
-
|
|
46
|
-
data = File.read(path)
|
|
47
|
-
begin
|
|
48
|
-
yaml = YAML.safe_load(data)
|
|
49
|
-
rescue TypeError => _e
|
|
50
|
-
return
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
Mihari.configure do |config|
|
|
54
|
-
yaml.each do |key, value|
|
|
55
|
-
config.send("#{key.downcase}=".to_sym, value)
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
def initialize_yaml(filename)
|
|
61
|
-
keys = new.instance_variables.map do |key|
|
|
62
|
-
key.to_s[1..]
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
config = keys.map do |key|
|
|
66
|
-
[key, nil]
|
|
67
|
-
end.to_h
|
|
68
|
-
|
|
69
|
-
YAML.dump(config, File.open(filename, "w"))
|
|
70
|
-
end
|
|
71
|
-
end
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
class << self
|
|
75
|
-
def config
|
|
76
|
-
@config ||= Config.new
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
attr_writer :config
|
|
80
|
-
|
|
81
|
-
def configure
|
|
82
|
-
yield config
|
|
83
|
-
end
|
|
84
|
-
end
|
|
85
|
-
end
|