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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f8c53264f15a01502a5a872c013db461b718655608941c88af53c0424261de76
4
- data.tar.gz: 1f6146bce1c0eaacfcd688cb33794f974433f8418d7f8eb38513ef338b5914ac
3
+ metadata.gz: c45276dc9bbc108475c4db517d7bf0e7e809c85de3ee3e7f6141df444e1890db
4
+ data.tar.gz: 90f9bc7cfa1d25a1186b98b3418069b0c8e30bde28bdb2ebd3ded6930e48b015
5
5
  SHA512:
6
- metadata.gz: f8e79477f488c81f84a9c594bbcfec1e50aa60b66f3e8c0f8a7e71672efc22cceb0ddbd62330b9962e091878f364c9a0475356b54b1924465cd433579530a4f9
7
- data.tar.gz: 966b523e74b2769501a613c2b4adeda2d521791a8b6376fb6e47dc8d60fe1b41316e077cb1bc4a95a630397f398b345c5f12d56298581128714c60b2076a7de3
6
+ metadata.gz: fa740d55a2fad831f1bf18aeae5aa2695b00c8cc92f09512ebd1c178eaa66083cb65309c4ccd6b2e2e81db450fb21c213d556ad6d5974f7e9037eb814fe75a20
7
+ data.tar.gz: 03edf15c5fe58fe9b237829510eda124fc91507a6f9903a5f2ecccef275e29ceb94d30a73a4cfc9485a3ca1905c406b58fd87655c4d0ec4d05514755ca768e22
@@ -3,5 +3,5 @@ sudo: false
3
3
  language: ruby
4
4
  cache: bundler
5
5
  rvm:
6
- - 2.6.1
6
+ - 2.6
7
7
  before_install: gem install bundler -v 2.0.1
data/README.md CHANGED
@@ -51,12 +51,25 @@ docker pull ninoseki/mihari
51
51
 
52
52
  ## Basic usage
53
53
 
54
- mihari supports Censys, Shodan, Onyphe, urlscan, SecurityTrails, crt.sh, CIRCL passive DNS/SSL, PassiveTotal, VirusTotal and ZoomEye by default.
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 zoommeye [QUERY] # ZoomEye lookup by a given query
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 |
@@ -35,6 +35,8 @@ require "mihari/the_hive"
35
35
 
36
36
  require "mihari/analyzers/base"
37
37
  require "mihari/analyzers/basic"
38
+
39
+ require "mihari/analyzers/binaryedge"
38
40
  require "mihari/analyzers/censys"
39
41
  require "mihari/analyzers/circl"
40
42
  require "mihari/analyzers/crtsh"
@@ -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
- result = search
24
- return [] unless result
23
+ results = search
24
+ return [] unless results
25
25
 
26
- results = result.dig("results") || []
27
- results.map { |e| e.dig("ip") }.compact
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
- api.datascan(query)
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(&:ip)
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(&:hostname).compact.uniq
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(&:hostname).compact.uniq
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 * 100
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
- res = _host_lookup(query)
68
- total = res.dig("total").to_f
69
- max = (total / 10.0).ceil
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
- res = _web_lookup(query)
88
- total = res.dig("total").to_f
89
- max = (total / 10.0).ceil
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
@@ -120,7 +120,7 @@ module Mihari
120
120
  end
121
121
  end
122
122
 
123
- desc "zoommeye [QUERY]", "ZoomEye lookup by a given query"
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Mihari
4
- VERSION = "0.12.0"
4
+ VERSION = "0.13.0"
5
5
  end
@@ -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.2"
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.2"
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.0"
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.12.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-17 00:00:00.000000000 Z
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.2'
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.2'
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.2'
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.2'
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.0'
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.0'
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.6
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.