mihari 0.12.0 → 0.13.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/.travis.yml +1 -1
- data/README.md +16 -2
- data/lib/mihari.rb +2 -0
- data/lib/mihari/analyzers/base.rb +1 -1
- data/lib/mihari/analyzers/binaryedge.rb +63 -0
- data/lib/mihari/analyzers/onyphe.rb +21 -5
- data/lib/mihari/analyzers/securitytrails.rb +7 -7
- data/lib/mihari/analyzers/shodan.rb +3 -1
- data/lib/mihari/analyzers/zoomeye.rb +14 -14
- data/lib/mihari/cli.rb +11 -1
- data/lib/mihari/version.rb +1 -1
- data/mihari.gemspec +4 -3
- metadata +24 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c45276dc9bbc108475c4db517d7bf0e7e809c85de3ee3e7f6141df444e1890db
|
4
|
+
data.tar.gz: 90f9bc7cfa1d25a1186b98b3418069b0c8e30bde28bdb2ebd3ded6930e48b015
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fa740d55a2fad831f1bf18aeae5aa2695b00c8cc92f09512ebd1c178eaa66083cb65309c4ccd6b2e2e81db450fb21c213d556ad6d5974f7e9037eb814fe75a20
|
7
|
+
data.tar.gz: 03edf15c5fe58fe9b237829510eda124fc91507a6f9903a5f2ecccef275e29ceb94d30a73a4cfc9485a3ca1905c406b58fd87655c4d0ec4d05514755ca768e22
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -51,12 +51,25 @@ docker pull ninoseki/mihari
|
|
51
51
|
|
52
52
|
## Basic usage
|
53
53
|
|
54
|
-
mihari supports
|
54
|
+
mihari supports the following services by default.
|
55
|
+
|
56
|
+
- [BinaryEdge](https://www.binaryedge.io/)
|
57
|
+
- [Censys](http://censys.io)
|
58
|
+
- [CIRCL passive DNS](https://www.circl.lu/services/passive-dns/) / [passive SSL](https://www.circl.lu/services/passive-ssl/)
|
59
|
+
- [crt.sh](https://crt.sh/)
|
60
|
+
- [Onyphe](https://onyphe.io)
|
61
|
+
- [PassiveTotal](https://community.riskiq.com/)
|
62
|
+
- [SecurityTrails](https://securitytrails.com/)
|
63
|
+
- [Shodan](https://shodan.io)
|
64
|
+
- [urlscan.io](https://urlscan.io)
|
65
|
+
- [VirusTotal](http://virustotal.com)
|
66
|
+
- [ZoomEye](https://zoomeye.org)
|
55
67
|
|
56
68
|
```bash
|
57
69
|
$ mihari
|
58
70
|
Commands:
|
59
71
|
mihari alerts # Show the alerts on TheHive
|
72
|
+
mihari binaryedge [QUERY] # BinaryEdge lookup by a given query
|
60
73
|
mihari censys [QUERY] # Censys IPv4 lookup by a given query
|
61
74
|
mihari circl [DOMAIN|SHA1] # CIRCL passive DNS/SSL lookup by a given domain / SHA1 certificate fingerprint
|
62
75
|
mihari crtsh [QUERY] # crt.sh lookup by a given query
|
@@ -71,7 +84,7 @@ Commands:
|
|
71
84
|
mihari status # Show the current configuration status
|
72
85
|
mihari urlscan [QUERY] # urlscan lookup by a given query
|
73
86
|
mihari virustotal [IP|DOMAIN] # VirusTotal resolutions lookup by a given ip or domain
|
74
|
-
mihari
|
87
|
+
mihari zoomeye [QUERY] # ZoomEye lookup by a given query
|
75
88
|
|
76
89
|
```
|
77
90
|
|
@@ -160,6 +173,7 @@ All configuration is done via ENV variables.
|
|
160
173
|
| MISP_API_KEY | MISP API key | Optional |
|
161
174
|
| SLACK_WEBHOOK_URL | Slack Webhook URL | Optional |
|
162
175
|
| SLACK_CHANNEL | Slack channel name | Optional (default: `#general`) |
|
176
|
+
| BINARYEDGE_API_KEY | BinaryEdge API key | Optional |
|
163
177
|
| CENSYS_ID | Censys API ID | Optional |
|
164
178
|
| CENSYS_SECRET | Censys secret | Optional |
|
165
179
|
| CIRCL_PASSIVE_PASSWORD | CIRCL passive DNS/SSL password | Optional |
|
data/lib/mihari.rb
CHANGED
@@ -60,7 +60,7 @@ module Mihari
|
|
60
60
|
|
61
61
|
# @return [Array<Mihari::Artifact>]
|
62
62
|
def normalized_artifacts
|
63
|
-
@normalized_artifacts ||= artifacts.map do |artifact|
|
63
|
+
@normalized_artifacts ||= artifacts.compact.uniq.map do |artifact|
|
64
64
|
artifact.is_a?(Artifact) ? artifact : Artifact.new(artifact)
|
65
65
|
end.select(&:valid?)
|
66
66
|
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "binaryedge"
|
4
|
+
|
5
|
+
module Mihari
|
6
|
+
module Analyzers
|
7
|
+
class BinaryEdge < Base
|
8
|
+
attr_reader :title
|
9
|
+
attr_reader :description
|
10
|
+
attr_reader :query
|
11
|
+
attr_reader :tags
|
12
|
+
|
13
|
+
def initialize(query, title: nil, description: nil, tags: [])
|
14
|
+
super()
|
15
|
+
|
16
|
+
@query = query
|
17
|
+
@title = title || "BinaryEdge lookup"
|
18
|
+
@description = description || "query = #{query}"
|
19
|
+
@tags = tags
|
20
|
+
end
|
21
|
+
|
22
|
+
def artifacts
|
23
|
+
results = search
|
24
|
+
return [] unless results || results.empty?
|
25
|
+
|
26
|
+
results.map do |result|
|
27
|
+
events = result.dig("events") || []
|
28
|
+
events.map do |event|
|
29
|
+
event.dig "origin", "ip"
|
30
|
+
end.compact
|
31
|
+
end.flatten.compact.uniq
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
PAGE_SIZE = 20
|
37
|
+
|
38
|
+
def search_with_page(query, page: 1)
|
39
|
+
api.host.search(query, page: page)
|
40
|
+
end
|
41
|
+
|
42
|
+
def search
|
43
|
+
responses = []
|
44
|
+
(1..Float::INFINITY).each do |page|
|
45
|
+
res = search_with_page(query, page: page)
|
46
|
+
total = res.dig("total").to_i
|
47
|
+
|
48
|
+
responses << res
|
49
|
+
break if total <= page * PAGE_SIZE
|
50
|
+
end
|
51
|
+
responses
|
52
|
+
end
|
53
|
+
|
54
|
+
def config_keys
|
55
|
+
%w(BINARYEDGE_API_KEY)
|
56
|
+
end
|
57
|
+
|
58
|
+
def api
|
59
|
+
@api ||= ::BinaryEdge::API.new
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -20,15 +20,20 @@ module Mihari
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def artifacts
|
23
|
-
|
24
|
-
return [] unless
|
23
|
+
results = search
|
24
|
+
return [] unless results
|
25
25
|
|
26
|
-
|
27
|
-
|
26
|
+
flat_results = results.map do |result|
|
27
|
+
result.dig("results")
|
28
|
+
end.flatten.compact
|
29
|
+
|
30
|
+
flat_results.map { |result| result.dig("ip") }.compact.uniq
|
28
31
|
end
|
29
32
|
|
30
33
|
private
|
31
34
|
|
35
|
+
PAGE_SIZE = 10
|
36
|
+
|
32
37
|
def config_keys
|
33
38
|
%w(ONYPHE_API_KEY)
|
34
39
|
end
|
@@ -37,8 +42,19 @@ module Mihari
|
|
37
42
|
@api ||= ::Onyphe::API.new
|
38
43
|
end
|
39
44
|
|
45
|
+
def search_with_page(query, page: 1)
|
46
|
+
api.datascan(query, page: page)
|
47
|
+
end
|
48
|
+
|
40
49
|
def search
|
41
|
-
|
50
|
+
responses = []
|
51
|
+
(1..Float::INFINITY).each do |page|
|
52
|
+
res = search_with_page(query, page: page)
|
53
|
+
responses << res
|
54
|
+
total = res.dig("total").to_i
|
55
|
+
break if total <= page * PAGE_SIZE
|
56
|
+
end
|
57
|
+
responses
|
42
58
|
end
|
43
59
|
end
|
44
60
|
end
|
@@ -57,23 +57,23 @@ module Mihari
|
|
57
57
|
end
|
58
58
|
|
59
59
|
def domain_lookup
|
60
|
-
result = api.history.get_all_dns_history(query, "a")
|
61
|
-
records = result.records || []
|
60
|
+
result = api.history.get_all_dns_history(query, type: "a")
|
61
|
+
records = result.dig("records") || []
|
62
62
|
records.map do |record|
|
63
|
-
(record.values || []).map(
|
63
|
+
(record.dig("values") || []).map { |value| value.dig("ip") }
|
64
64
|
end.flatten.compact.uniq
|
65
65
|
end
|
66
66
|
|
67
67
|
def ip_lookup
|
68
68
|
result = api.domains.search( filter: { ipv4: query })
|
69
|
-
records = result.records || []
|
70
|
-
records.map(
|
69
|
+
records = result.dig("records") || []
|
70
|
+
records.map { |record| record.dig("hostname") }.compact.uniq
|
71
71
|
end
|
72
72
|
|
73
73
|
def mail_lookup
|
74
74
|
result = api.domains.search( filter: { whois_email: query })
|
75
|
-
records = result.records || []
|
76
|
-
records.map(
|
75
|
+
records = result.dig("records") || []
|
76
|
+
records.map { |record| record.dig("hostname") }.compact.uniq
|
77
77
|
end
|
78
78
|
end
|
79
79
|
end
|
@@ -33,6 +33,8 @@ module Mihari
|
|
33
33
|
|
34
34
|
private
|
35
35
|
|
36
|
+
PAGE_SIZE = 100
|
37
|
+
|
36
38
|
def config_keys
|
37
39
|
%w(SHODAN_API_KEY)
|
38
40
|
end
|
@@ -54,7 +56,7 @@ module Mihari
|
|
54
56
|
break unless res
|
55
57
|
|
56
58
|
responses << res
|
57
|
-
break if res.dig("total").to_i <= page *
|
59
|
+
break if res.dig("total").to_i <= page * PAGE_SIZE
|
58
60
|
end
|
59
61
|
responses
|
60
62
|
end
|
@@ -34,6 +34,8 @@ module Mihari
|
|
34
34
|
|
35
35
|
private
|
36
36
|
|
37
|
+
PAGE_SIZE = 10
|
38
|
+
|
37
39
|
def valid_type?
|
38
40
|
%w(host web).include? type
|
39
41
|
end
|
@@ -63,14 +65,13 @@ module Mihari
|
|
63
65
|
|
64
66
|
def host_lookup
|
65
67
|
responses = []
|
68
|
+
(1..Float::INFINITY).each do |page|
|
69
|
+
res = _host_lookup(query, page: page)
|
70
|
+
break unless res
|
66
71
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
responses << res
|
71
|
-
|
72
|
-
(2..max).each do |page|
|
73
|
-
responses << _host_lookup(query, page: page)
|
72
|
+
total = res.dig("total").to_i
|
73
|
+
responses << res
|
74
|
+
break if total <= page * PAGE_SIZE
|
74
75
|
end
|
75
76
|
convert_responses responses.compact
|
76
77
|
end
|
@@ -83,14 +84,13 @@ module Mihari
|
|
83
84
|
|
84
85
|
def web_lookup
|
85
86
|
responses = []
|
87
|
+
(1..Float::INFINITY).each do |page|
|
88
|
+
res = _web_lookup(query, page: page)
|
89
|
+
break unless res
|
86
90
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
responses << res
|
91
|
-
|
92
|
-
(2..max).each do |page|
|
93
|
-
responses << _web_lookup(query, page: page)
|
91
|
+
total = res.dig("total").to_i
|
92
|
+
responses << res
|
93
|
+
break if total <= page * PAGE_SIZE
|
94
94
|
end
|
95
95
|
convert_responses responses.compact
|
96
96
|
end
|
data/lib/mihari/cli.rb
CHANGED
@@ -120,7 +120,7 @@ module Mihari
|
|
120
120
|
end
|
121
121
|
end
|
122
122
|
|
123
|
-
desc "
|
123
|
+
desc "zoomeye [QUERY]", "ZoomEye lookup by a given query"
|
124
124
|
method_option :title, type: :string, desc: "title"
|
125
125
|
method_option :description, type: :string, desc: "description"
|
126
126
|
method_option :tags, type: :array, desc: "tags"
|
@@ -131,6 +131,16 @@ module Mihari
|
|
131
131
|
end
|
132
132
|
end
|
133
133
|
|
134
|
+
desc "binaryedge [QUERY]", "BinaryEdge lookup by a given query"
|
135
|
+
method_option :title, type: :string, desc: "title"
|
136
|
+
method_option :description, type: :string, desc: "description"
|
137
|
+
method_option :tags, type: :array, desc: "tags"
|
138
|
+
def binaryedge(query)
|
139
|
+
with_error_handling do
|
140
|
+
run_analyzer Analyzers::BinaryEdge, query: query, options: options
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
134
144
|
desc "import_from_json", "Give a JSON input via STDIN"
|
135
145
|
def import_from_json(input = nil)
|
136
146
|
with_error_handling do
|
data/lib/mihari/version.rb
CHANGED
data/mihari.gemspec
CHANGED
@@ -34,6 +34,7 @@ Gem::Specification.new do |spec|
|
|
34
34
|
spec.add_development_dependency "webmock", "~> 3.7"
|
35
35
|
|
36
36
|
spec.add_dependency "addressable", "~> 2.7"
|
37
|
+
spec.add_dependency "binaryedge", "~> 0.1"
|
37
38
|
spec.add_dependency "censu", "~> 0.2"
|
38
39
|
spec.add_dependency "crtsh-rb", "~> 0.1"
|
39
40
|
spec.add_dependency "dnpedia", "~> 0.1"
|
@@ -43,16 +44,16 @@ Gem::Specification.new do |spec|
|
|
43
44
|
spec.add_dependency "mem", "~> 0.1"
|
44
45
|
spec.add_dependency "misp", "~> 0.1"
|
45
46
|
spec.add_dependency "net-ping", "~> 2.0"
|
46
|
-
spec.add_dependency "onyphe", "~> 0
|
47
|
+
spec.add_dependency "onyphe", "~> 1.0"
|
47
48
|
spec.add_dependency "parallel", "~> 1.18"
|
48
49
|
spec.add_dependency "passive_circl", "~> 0.1"
|
49
50
|
spec.add_dependency "passivetotalx", "~> 0.1"
|
50
51
|
spec.add_dependency "public_suffix", "~> 4.0"
|
51
|
-
spec.add_dependency "securitytrails", "~> 0
|
52
|
+
spec.add_dependency "securitytrails", "~> 1.0"
|
52
53
|
spec.add_dependency "shodanx", "~> 0.2"
|
53
54
|
spec.add_dependency "slack-notifier", "~> 2.3"
|
54
55
|
spec.add_dependency "thor", "~> 0.20"
|
55
56
|
spec.add_dependency "urlscan", "~> 0.4"
|
56
|
-
spec.add_dependency "virustotalx", "~> 1.
|
57
|
+
spec.add_dependency "virustotalx", "~> 1.1"
|
57
58
|
spec.add_dependency "zoomeye-rb", "~> 0.1"
|
58
59
|
end
|
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.13.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-10-
|
11
|
+
date: 2019-10-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -136,6 +136,20 @@ dependencies:
|
|
136
136
|
- - "~>"
|
137
137
|
- !ruby/object:Gem::Version
|
138
138
|
version: '2.7'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: binaryedge
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - "~>"
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0.1'
|
146
|
+
type: :runtime
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - "~>"
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0.1'
|
139
153
|
- !ruby/object:Gem::Dependency
|
140
154
|
name: censu
|
141
155
|
requirement: !ruby/object:Gem::Requirement
|
@@ -268,14 +282,14 @@ dependencies:
|
|
268
282
|
requirements:
|
269
283
|
- - "~>"
|
270
284
|
- !ruby/object:Gem::Version
|
271
|
-
version: '0
|
285
|
+
version: '1.0'
|
272
286
|
type: :runtime
|
273
287
|
prerelease: false
|
274
288
|
version_requirements: !ruby/object:Gem::Requirement
|
275
289
|
requirements:
|
276
290
|
- - "~>"
|
277
291
|
- !ruby/object:Gem::Version
|
278
|
-
version: '0
|
292
|
+
version: '1.0'
|
279
293
|
- !ruby/object:Gem::Dependency
|
280
294
|
name: parallel
|
281
295
|
requirement: !ruby/object:Gem::Requirement
|
@@ -338,14 +352,14 @@ dependencies:
|
|
338
352
|
requirements:
|
339
353
|
- - "~>"
|
340
354
|
- !ruby/object:Gem::Version
|
341
|
-
version: '0
|
355
|
+
version: '1.0'
|
342
356
|
type: :runtime
|
343
357
|
prerelease: false
|
344
358
|
version_requirements: !ruby/object:Gem::Requirement
|
345
359
|
requirements:
|
346
360
|
- - "~>"
|
347
361
|
- !ruby/object:Gem::Version
|
348
|
-
version: '0
|
362
|
+
version: '1.0'
|
349
363
|
- !ruby/object:Gem::Dependency
|
350
364
|
name: shodanx
|
351
365
|
requirement: !ruby/object:Gem::Requirement
|
@@ -408,14 +422,14 @@ dependencies:
|
|
408
422
|
requirements:
|
409
423
|
- - "~>"
|
410
424
|
- !ruby/object:Gem::Version
|
411
|
-
version: '1.
|
425
|
+
version: '1.1'
|
412
426
|
type: :runtime
|
413
427
|
prerelease: false
|
414
428
|
version_requirements: !ruby/object:Gem::Requirement
|
415
429
|
requirements:
|
416
430
|
- - "~>"
|
417
431
|
- !ruby/object:Gem::Version
|
418
|
-
version: '1.
|
432
|
+
version: '1.1'
|
419
433
|
- !ruby/object:Gem::Dependency
|
420
434
|
name: zoomeye-rb
|
421
435
|
requirement: !ruby/object:Gem::Requirement
|
@@ -454,6 +468,7 @@ files:
|
|
454
468
|
- lib/mihari/alert_viewer.rb
|
455
469
|
- lib/mihari/analyzers/base.rb
|
456
470
|
- lib/mihari/analyzers/basic.rb
|
471
|
+
- lib/mihari/analyzers/binaryedge.rb
|
457
472
|
- lib/mihari/analyzers/censys.rb
|
458
473
|
- lib/mihari/analyzers/circl.rb
|
459
474
|
- lib/mihari/analyzers/crtsh.rb
|
@@ -510,7 +525,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
510
525
|
- !ruby/object:Gem::Version
|
511
526
|
version: '0'
|
512
527
|
requirements: []
|
513
|
-
rubygems_version: 3.0.
|
528
|
+
rubygems_version: 3.0.3
|
514
529
|
signing_key:
|
515
530
|
specification_version: 4
|
516
531
|
summary: A framework for continuous malicious hosts monitoring.
|