mihari 0.12.0 → 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
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.