mihari 0.13.2 → 0.14.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +17 -0
- data/lib/mihari.rb +5 -0
- data/lib/mihari/analyzers/passive_dns.rb +62 -0
- data/lib/mihari/analyzers/passive_ssl.rb +60 -0
- data/lib/mihari/analyzers/reverse_whois.rb +60 -0
- data/lib/mihari/analyzers/sha256.rb +60 -0
- data/lib/mihari/cli.rb +40 -0
- data/lib/mihari/type_checker.rb +15 -0
- data/lib/mihari/version.rb +1 -1
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 429387bdb6483e260f1631661721fce1a5abc284711a2c763b50452140388a0c
|
4
|
+
data.tar.gz: 7ba6ad5c62da25d668cf975a4ffecb3e70a01c7c5c6961e646412b0227886fc0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c64e408f6e8d11c27285f1bceccd504cbffa360978864cf5c4a45b7841a1718166158b6818af2d2a3f83087af21cda7c1808e948335270ac742a0c0094c467c4
|
7
|
+
data.tar.gz: c36b4d97ae530b19c5c9f06b22438032eeca23aeea941a39a12b56a0236565de1a09c7f977b8d04b7f2a5c62fbcfe4e2abf06f553d497d05660982879fa9edba
|
data/README.md
CHANGED
@@ -77,9 +77,13 @@ Commands:
|
|
77
77
|
mihari help [COMMAND] # Describe available commands or one specific command
|
78
78
|
mihari import_from_json # Give a JSON input via STDIN
|
79
79
|
mihari onyphe [QUERY] # Onyphe datascan search by a query
|
80
|
+
mihari passive_dns [IP|Domain] # Cross search with passive DNS services by an ip / domain
|
81
|
+
mihari passive_ssl [SHA1] # Cross search with passive SSL services by an SHA1 certificate fingerprint
|
80
82
|
mihari passivetotal [IP|DOMAIN|EMAIL|SHA1] # PassiveTotal lookup by an ip / domain / email / SHA1 certificate fingerprint
|
83
|
+
mihari reverse_whois [email] # Cross search with reverse whois services by an email
|
81
84
|
mihari securitytrails [IP|DOMAIN|EMAIL] # SecurityTrails lookup by an ip, domain or email
|
82
85
|
mihari securitytrails_domain_feed [REGEXP] # SecurityTrails new domain feed search by a regexp
|
86
|
+
mihari sha256 [SHA256] # Cross search with search engines by an SHA256 hash
|
83
87
|
mihari shodan [QUERY] # Shodan host search by a query
|
84
88
|
mihari status # Show the current configuration status
|
85
89
|
mihari urlscan [QUERY] # urlscan search by a given query
|
@@ -88,6 +92,19 @@ Commands:
|
|
88
92
|
|
89
93
|
```
|
90
94
|
|
95
|
+
### Cross searches
|
96
|
+
|
97
|
+
mihari has cross search features. A cross search is a search across a number of services.
|
98
|
+
|
99
|
+
You can get aggregated results by using the following commands.
|
100
|
+
|
101
|
+
| Command | Desc. |
|
102
|
+
|---------------|----------------------------------------------------------------------------------------|
|
103
|
+
| passive_dns | Passive DNS lookup with CIRCL passive DNS, PassiveTotal, SecurityTrails and VirusTotal |
|
104
|
+
| passive_ssl | Passive SSL lookup with CIRCL passive SSL and PassiveTotal |
|
105
|
+
| reverse_whois | Revese Whois lookup with PassiveTotal and SecurityTrails |
|
106
|
+
| sha256 | SHA256 hash search with BinaryEdge and Censys |
|
107
|
+
|
91
108
|
### Example usages
|
92
109
|
|
93
110
|
```bash
|
data/lib/mihari.rb
CHANGED
@@ -51,6 +51,11 @@ require "mihari/analyzers/urlscan"
|
|
51
51
|
require "mihari/analyzers/virustotal"
|
52
52
|
require "mihari/analyzers/zoomeye"
|
53
53
|
|
54
|
+
require "mihari/analyzers/passive_dns"
|
55
|
+
require "mihari/analyzers/passive_ssl"
|
56
|
+
require "mihari/analyzers/reverse_whois"
|
57
|
+
require "mihari/analyzers/sha256"
|
58
|
+
|
54
59
|
require "mihari/notifiers/base"
|
55
60
|
require "mihari/notifiers/slack"
|
56
61
|
require "mihari/notifiers/exception_notifier"
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "parallel"
|
4
|
+
|
5
|
+
module Mihari
|
6
|
+
module Analyzers
|
7
|
+
class PassiveDNS < Base
|
8
|
+
attr_reader :query
|
9
|
+
attr_reader :type
|
10
|
+
|
11
|
+
attr_reader :title
|
12
|
+
attr_reader :description
|
13
|
+
attr_reader :tags
|
14
|
+
|
15
|
+
ANALYZERS = [
|
16
|
+
Mihari::Analyzers::CIRCL,
|
17
|
+
Mihari::Analyzers::PassiveTotal,
|
18
|
+
Mihari::Analyzers::SecurityTrails,
|
19
|
+
Mihari::Analyzers::VirusTotal,
|
20
|
+
].freeze
|
21
|
+
|
22
|
+
def initialize(query, title: nil, description: nil, tags: [])
|
23
|
+
super()
|
24
|
+
|
25
|
+
@query = query
|
26
|
+
@type = TypeChecker.type(query)
|
27
|
+
|
28
|
+
@title = title || "PassiveDNS cross search"
|
29
|
+
@description = description || "query = #{query}"
|
30
|
+
@tags = tags
|
31
|
+
end
|
32
|
+
|
33
|
+
def artifacts
|
34
|
+
Parallel.map(analyzers) do |analyzer|
|
35
|
+
run_analyzer analyzer
|
36
|
+
end.flatten
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def valid_type?
|
42
|
+
%w(ip domain).include? type
|
43
|
+
end
|
44
|
+
|
45
|
+
def analyzers
|
46
|
+
raise InvalidInputError, "#{query}(type: #{type || 'unknown'}) is not supported." unless valid_type?
|
47
|
+
|
48
|
+
ANALYZERS.map do |klass|
|
49
|
+
klass.new(query)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def run_analyzer(analyzer)
|
54
|
+
analyzer.artifacts
|
55
|
+
rescue ArgumentError, InvalidInputError => _e
|
56
|
+
nil
|
57
|
+
rescue ::PassiveCIRCL::Error, ::PassiveTotal::Error, ::SecurityTrails::Error, ::VirusTotal::Error => _e
|
58
|
+
nil
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "parallel"
|
4
|
+
|
5
|
+
module Mihari
|
6
|
+
module Analyzers
|
7
|
+
class PassiveSSL < Base
|
8
|
+
attr_reader :query
|
9
|
+
attr_reader :type
|
10
|
+
|
11
|
+
attr_reader :title
|
12
|
+
attr_reader :description
|
13
|
+
attr_reader :tags
|
14
|
+
|
15
|
+
ANALYZERS = [
|
16
|
+
Mihari::Analyzers::CIRCL,
|
17
|
+
Mihari::Analyzers::PassiveTotal,
|
18
|
+
].freeze
|
19
|
+
|
20
|
+
def initialize(query, title: nil, description: nil, tags: [])
|
21
|
+
super()
|
22
|
+
|
23
|
+
@query = query
|
24
|
+
@type = TypeChecker.detailed_type(query)
|
25
|
+
|
26
|
+
@title = title || "PassiveSSL cross search"
|
27
|
+
@description = description || "query = #{query}"
|
28
|
+
@tags = tags
|
29
|
+
end
|
30
|
+
|
31
|
+
def artifacts
|
32
|
+
Parallel.map(analyzers) do |analyzer|
|
33
|
+
run_analyzer analyzer
|
34
|
+
end.flatten
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def valid_type?
|
40
|
+
%w(sha1).include? type
|
41
|
+
end
|
42
|
+
|
43
|
+
def analyzers
|
44
|
+
raise InvalidInputError, "#{query}(type: #{type || 'unknown'}) is not supported." unless valid_type?
|
45
|
+
|
46
|
+
ANALYZERS.map do |klass|
|
47
|
+
klass.new(query)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def run_analyzer(analyzer)
|
52
|
+
analyzer.artifacts
|
53
|
+
rescue ArgumentError, InvalidInputError => _e
|
54
|
+
nil
|
55
|
+
rescue ::PassiveCIRCL::Error, ::PassiveTotal::Error => _e
|
56
|
+
nil
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "parallel"
|
4
|
+
|
5
|
+
module Mihari
|
6
|
+
module Analyzers
|
7
|
+
class ReveseWhois < Base
|
8
|
+
attr_reader :query
|
9
|
+
attr_reader :type
|
10
|
+
|
11
|
+
attr_reader :title
|
12
|
+
attr_reader :description
|
13
|
+
attr_reader :tags
|
14
|
+
|
15
|
+
ANALYZERS = [
|
16
|
+
Mihari::Analyzers::PassiveTotal,
|
17
|
+
Mihari::Analyzers::SecurityTrails,
|
18
|
+
].freeze
|
19
|
+
|
20
|
+
def initialize(query, title: nil, description: nil, tags: [])
|
21
|
+
super()
|
22
|
+
|
23
|
+
@query = query
|
24
|
+
@type = TypeChecker.type(query)
|
25
|
+
|
26
|
+
@title = title || "ReveseWhois cross search"
|
27
|
+
@description = description || "query = #{query}"
|
28
|
+
@tags = tags
|
29
|
+
end
|
30
|
+
|
31
|
+
def artifacts
|
32
|
+
Parallel.map(analyzers) do |analyzer|
|
33
|
+
run_analyzer analyzer
|
34
|
+
end.flatten
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def valid_type?
|
40
|
+
%w(mail).include? type
|
41
|
+
end
|
42
|
+
|
43
|
+
def analyzers
|
44
|
+
raise InvalidInputError, "#{query}(type: #{type || 'unknown'}) is not supported." unless valid_type?
|
45
|
+
|
46
|
+
ANALYZERS.map do |klass|
|
47
|
+
klass.new(query)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def run_analyzer(analyzer)
|
52
|
+
analyzer.artifacts
|
53
|
+
rescue ArgumentError, InvalidInputError => _e
|
54
|
+
nil
|
55
|
+
rescue ::PassiveTotal::Error, ::SecurityTrails::Error => _e
|
56
|
+
nil
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "parallel"
|
4
|
+
|
5
|
+
module Mihari
|
6
|
+
module Analyzers
|
7
|
+
class SHA256 < Base
|
8
|
+
attr_reader :query
|
9
|
+
attr_reader :type
|
10
|
+
|
11
|
+
attr_reader :title
|
12
|
+
attr_reader :description
|
13
|
+
attr_reader :tags
|
14
|
+
|
15
|
+
ANALYZERS = [
|
16
|
+
Mihari::Analyzers::BinaryEdge,
|
17
|
+
Mihari::Analyzers::Censys,
|
18
|
+
].freeze
|
19
|
+
|
20
|
+
def initialize(query, title: nil, description: nil, tags: [])
|
21
|
+
super()
|
22
|
+
|
23
|
+
@query = query
|
24
|
+
@type = TypeChecker.detailed_type(query)
|
25
|
+
|
26
|
+
@title = title || "SHA256 hash cross search"
|
27
|
+
@description = description || "query = #{query}"
|
28
|
+
@tags = tags
|
29
|
+
end
|
30
|
+
|
31
|
+
def artifacts
|
32
|
+
Parallel.map(analyzers) do |analyzer|
|
33
|
+
run_analyzer analyzer
|
34
|
+
end.flatten
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def valid_type?
|
40
|
+
%w(sha256).include? type
|
41
|
+
end
|
42
|
+
|
43
|
+
def analyzers
|
44
|
+
raise InvalidInputError, "#{query}(type: #{type || 'unknown'}) is not supported." unless valid_type?
|
45
|
+
|
46
|
+
ANALYZERS.map do |klass|
|
47
|
+
klass.new(query)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def run_analyzer(analyzer)
|
52
|
+
analyzer.artifacts
|
53
|
+
rescue ArgumentError, InvalidInputError => _e
|
54
|
+
nil
|
55
|
+
rescue ::BinaryEdge::Error, ::Censys::ResponseError => _e
|
56
|
+
nil
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/lib/mihari/cli.rb
CHANGED
@@ -141,6 +141,46 @@ module Mihari
|
|
141
141
|
end
|
142
142
|
end
|
143
143
|
|
144
|
+
desc "passive_dns [IP|Domain]", "Cross search with passive DNS services by an ip / domain"
|
145
|
+
method_option :title, type: :string, desc: "title"
|
146
|
+
method_option :description, type: :string, desc: "description"
|
147
|
+
method_option :tags, type: :array, desc: "tags"
|
148
|
+
def passive_dns(query)
|
149
|
+
with_error_handling do
|
150
|
+
run_analyzer Analyzers::PassiveDNS, query: query, options: options
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
desc "passive_ssl [SHA1]", "Cross search with passive SSL services by an SHA1 certificate fingerprint"
|
155
|
+
method_option :title, type: :string, desc: "title"
|
156
|
+
method_option :description, type: :string, desc: "description"
|
157
|
+
method_option :tags, type: :array, desc: "tags"
|
158
|
+
def passive_ssl(query)
|
159
|
+
with_error_handling do
|
160
|
+
run_analyzer Analyzers::PassiveSSL, query: query, options: options
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
desc "reverse_whois [email]", "Cross search with reverse whois services by an email"
|
165
|
+
method_option :title, type: :string, desc: "title"
|
166
|
+
method_option :description, type: :string, desc: "description"
|
167
|
+
method_option :tags, type: :array, desc: "tags"
|
168
|
+
def reverse_whois(query)
|
169
|
+
with_error_handling do
|
170
|
+
run_analyzer Analyzers::ReveseWhois, query: query, options: options
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
desc "sha256 [SHA256]", "Cross search with search engines by an SHA256 hash"
|
175
|
+
method_option :title, type: :string, desc: "title"
|
176
|
+
method_option :description, type: :string, desc: "description"
|
177
|
+
method_option :tags, type: :array, desc: "tags"
|
178
|
+
def sha256(query)
|
179
|
+
with_error_handling do
|
180
|
+
run_analyzer Analyzers::SHA256, query: query, options: options
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
144
184
|
desc "import_from_json", "Give a JSON input via STDIN"
|
145
185
|
def import_from_json(input = nil)
|
146
186
|
with_error_handling do
|
data/lib/mihari/type_checker.rb
CHANGED
@@ -56,11 +56,26 @@ module Mihari
|
|
56
56
|
return "mail" if mail?
|
57
57
|
end
|
58
58
|
|
59
|
+
# @return [String, nil]
|
60
|
+
def detailed_type
|
61
|
+
return "md5" if md5?
|
62
|
+
return "sha1" if sha1?
|
63
|
+
return "sha256" if sha256?
|
64
|
+
return "sha512" if sha512?
|
65
|
+
|
66
|
+
type
|
67
|
+
end
|
68
|
+
|
59
69
|
# @return [String, nil]
|
60
70
|
def self.type(data)
|
61
71
|
new(data).type
|
62
72
|
end
|
63
73
|
|
74
|
+
# @return [String, nil]
|
75
|
+
def self.detailed_type(data)
|
76
|
+
new(data).detailed_type
|
77
|
+
end
|
78
|
+
|
64
79
|
private
|
65
80
|
|
66
81
|
# @return [true, false]
|
data/lib/mihari/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mihari
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.14.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Manabu Niseki
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-11-
|
11
|
+
date: 2019-11-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -474,9 +474,13 @@ files:
|
|
474
474
|
- lib/mihari/analyzers/crtsh.rb
|
475
475
|
- lib/mihari/analyzers/dnpedia.rb
|
476
476
|
- lib/mihari/analyzers/onyphe.rb
|
477
|
+
- lib/mihari/analyzers/passive_dns.rb
|
478
|
+
- lib/mihari/analyzers/passive_ssl.rb
|
477
479
|
- lib/mihari/analyzers/passivetotal.rb
|
480
|
+
- lib/mihari/analyzers/reverse_whois.rb
|
478
481
|
- lib/mihari/analyzers/securitytrails.rb
|
479
482
|
- lib/mihari/analyzers/securitytrails_domain_feed.rb
|
483
|
+
- lib/mihari/analyzers/sha256.rb
|
480
484
|
- lib/mihari/analyzers/shodan.rb
|
481
485
|
- lib/mihari/analyzers/urlscan.rb
|
482
486
|
- lib/mihari/analyzers/virustotal.rb
|