mihari 0.17.0 → 0.17.1

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: 0a5030ba15be3b81b4a71d9f38f3a0305d023dcddb3121e0c700a0cb82f1dcd9
4
- data.tar.gz: fc4f48e49a363550d165367e7aba0e3802535f3b13bcb32304d71a82eab256c7
3
+ metadata.gz: e28756adc591b441b67579ca8e4a0e7fcaadc1cf332a3c9e57e01438c19d6554
4
+ data.tar.gz: 0c9bf23eb782882354b6332878a41168293b4957724a27b2beab077f3caf3256
5
5
  SHA512:
6
- metadata.gz: 79487f0a7350c6299d159a32d7bc9655ac76934c2f2d224b059de59f128c18c4b23725269687cc3bd777d111c7245100f0b735d7011be997fc1bfed293b9f7b1
7
- data.tar.gz: 3071b839707180910cd1286041696b9f6b768abff4bb6e9a724ce553945118edb26784c70c848f0f5f888e1be7854c9e0b6d6a1645c8019d726926c10bda065f
6
+ metadata.gz: a91dc83d7a9988df7aff4b1ad90029c67223dfa717354a4c00fcba40e01b409ff77aba4c07969cc767dafa4d89bc6a5d9af807099665245ff0a578f3df4ae6cd
7
+ data.tar.gz: 34d6cc2546ce6b9e1a0b5918ec2a14dcf3f8f692222d950a7c27a7f28206308f78c0c40c66487108e5bcedfd70b25bbc9fa9f478862bf390aa041249ab3d31a9
@@ -4,4 +4,4 @@ language: ruby
4
4
  cache: bundler
5
5
  rvm:
6
6
  - 2.6
7
- before_install: gem install bundler -v 2.0.1
7
+ before_install: gem install bundler -v 2.1
data/README.md CHANGED
@@ -6,22 +6,22 @@
6
6
  [![Coverage Status](https://coveralls.io/repos/github/ninoseki/mihari/badge.svg?branch=master)](https://coveralls.io/github/ninoseki/mihari?branch=master)
7
7
  [![CodeFactor](https://www.codefactor.io/repository/github/ninoseki/mihari/badge)](https://www.codefactor.io/repository/github/ninoseki/mihari)
8
8
 
9
- mihari(`見張り`) is a sidekick tool for [TheHive](https://github.com/TheHive-Project/TheHive) for monitoring malicious hosts (C2 / landing page / phishing, etc.) continuously.
9
+ Mihari is a sidekick tool for [TheHive](https://github.com/TheHive-Project/TheHive) for monitoring malicious hosts (C2 / landing page / phishing, etc.) continuously.
10
10
 
11
11
  ## How it works
12
12
 
13
- - mihari makes a query against Shodan, Censys, VirusTotal, SecurityTrails, etc. and extracts artifacts from the results.
14
- - mihari checks whether TheHive contains the artifacts or not.
13
+ - Mihari makes a query against Shodan, Censys, VirusTotal, SecurityTrails, etc. and extracts artifacts from the results.
14
+ - Mihari checks whether TheHive contains the artifacts or not.
15
15
  - If it doesn't contain the artifacts:
16
- - mihari creates an alert on TheHive.
17
- - mihari sends a notification to Slack. (Optional)
18
- - mihari creates an event on MISP. (Optional)
16
+ - Mihari creates an alert on TheHive.
17
+ - Mihari sends a notification to Slack. (Optional)
18
+ - Mihari creates an event on MISP. (Optional)
19
19
 
20
20
  ![img](https://github.com/ninoseki/mihari/raw/master/screenshots/eyecatch.png)
21
21
 
22
22
  Check this blog post for more details: [Continuous C2 hunting with Censys, Shodan, Onyphe and TheHive](https://hackmd.io/s/SkUaSrqoE).
23
23
 
24
- You can use mihari without TheHive. But note that mihari depends on TheHive to manage artifacts. It means mihari might make duplications when without TheHive.
24
+ You can use mihari without TheHive but note that mihari depends on TheHive to manage artifacts. It means mihari might make duplications when without TheHive.
25
25
 
26
26
  ### Screenshots
27
27
 
@@ -51,7 +51,7 @@ docker pull ninoseki/mihari
51
51
 
52
52
  ## Basic usage
53
53
 
54
- mihari supports the following services by default.
54
+ Mihari supports the following services by default.
55
55
 
56
56
  - [BinaryEdge](https://www.binaryedge.io/)
57
57
  - [Censys](http://censys.io)
@@ -96,11 +96,14 @@ Commands:
96
96
  mihari virustotal [IP|DOMAIN] # VirusTotal resolutions lookup by an ip or domain
97
97
  mihari zoomeye [QUERY] # ZoomEye search by a query
98
98
 
99
+ Options:
100
+ [--config=CONFIG] # path to config file
101
+
99
102
  ```
100
103
 
101
104
  ### Cross searches
102
105
 
103
- mihari has cross search features. A cross search is a search across a number of services.
106
+ Mihari has cross search features. A cross search is a search across a number of services.
104
107
 
105
108
  You can get aggregated results by using the following commands.
106
109
 
@@ -224,7 +227,7 @@ The input is a JSON data should have `title`, `description` and `artifacts` key.
224
227
 
225
228
  ## Configuration
226
229
 
227
- All configuration is done via ENV variables.
230
+ Configuration can be done via environment variables or a YAML file.
228
231
 
229
232
  | Key | Desc. | Required or optional |
230
233
  |------------------------|--------------------------------|--------------------------------|
@@ -249,6 +252,20 @@ All configuration is done via ENV variables.
249
252
  | ZOOMEYE_USERNAMME | ZoomEye username | Optional |
250
253
  | ZOOMEYE_PASSWORD | ZoomEye password | Optional |
251
254
 
255
+ Instead of using environment variables, you can use a YAML file for configuration.
256
+
257
+ ```bash
258
+ mihari virustotal 1.1.1.1 --config /path/to/yaml.yml
259
+ ```
260
+
261
+ The YAML file should be a hash like below:
262
+
263
+ ```yaml
264
+ thehive_api_endpoint: https://localhost
265
+ thehive_api_key: foo
266
+ virustotal_api_key: foo
267
+ ```
268
+
252
269
  You can check the configuration status via `status` command.
253
270
 
254
271
  ```bash
@@ -299,7 +316,7 @@ See `/examples` for more.
299
316
 
300
317
  ## Caching
301
318
 
302
- mihari caches execution results in `/tmp/mihari` and the default cache duration is 7 days. If you want to clear the cache, please clear `/tmp/mihari`.
319
+ Mihari caches execution results in `/tmp/mihari` and the default cache duration is 7 days. If you want to clear the cache, please clear `/tmp/mihari`.
303
320
 
304
321
  ## Using it with Docker
305
322
 
@@ -24,6 +24,7 @@ require "mihari/errors"
24
24
 
25
25
  require "mihari/artifact"
26
26
  require "mihari/cache"
27
+ require "mihari/config"
27
28
  require "mihari/type_checker"
28
29
 
29
30
  require "mihari/html"
@@ -43,8 +43,6 @@ module Mihari
43
43
  else
44
44
  raise InvalidInputError, "#{@query}(type: #{@type || 'unknown'}) is not supported."
45
45
  end
46
- rescue ::PassiveCIRCL::Error => _e
47
- nil
48
46
  end
49
47
 
50
48
  def passive_dns_lookup
@@ -35,8 +35,6 @@ module Mihari
35
35
  rows.map do |row|
36
36
  [row.dig("name"), row.dig("zoneid")].join(".")
37
37
  end
38
- rescue ::DNPedia::Error => _e
39
- nil
40
38
  end
41
39
  end
42
40
  end
@@ -55,8 +55,6 @@ module Mihari
55
55
  Parallel.map(domains) do |domain|
56
56
  resolvable?(domain) ? domain : nil
57
57
  end.compact
58
- rescue ::DNSTwister::Error => _e
59
- nil
60
58
  end
61
59
  end
62
60
  end
@@ -54,8 +54,6 @@ module Mihari
54
54
  else
55
55
  raise InvalidInputError, "#{query}(type: #{type || 'unknown'}) is not supported." unless valid_type?
56
56
  end
57
- rescue ::PassiveTotal::Error => _e
58
- nil
59
57
  end
60
58
 
61
59
  def passive_dns_lookup
@@ -51,8 +51,6 @@ module Mihari
51
51
  (properties.dig("dns") || []).map do |property|
52
52
  property.dig("value") if ["A", "PTR"].include?(property.dig("name"))
53
53
  end.compact
54
- rescue ::Pulsedive::ResponseError => _e
55
- nil
56
54
  end
57
55
  end
58
56
  end
@@ -52,8 +52,6 @@ module Mihari
52
52
  else
53
53
  raise InvalidInputError, "#{query}(type: #{type || 'unknown'}) is not supported." unless valid_type?
54
54
  end
55
- rescue ::SecurityTrails::Error => _e
56
- nil
57
55
  end
58
56
 
59
57
  def domain_lookup
@@ -53,8 +53,6 @@ module Mihari
53
53
  new_domains.select do |domain|
54
54
  regexp.match? domain
55
55
  end
56
- rescue ::SecurityTrails::Error => _e
57
- nil
58
56
  end
59
57
 
60
58
  def new_domains
@@ -45,8 +45,6 @@ module Mihari
45
45
 
46
46
  def search_with_page(query, page: 1)
47
47
  api.host.search(query, page: page)
48
- rescue ::Shodan::Error => _e
49
- nil
50
48
  end
51
49
 
52
50
  def search
@@ -41,8 +41,6 @@ module Mihari
41
41
 
42
42
  def search
43
43
  api.search(query, size: 10_000)
44
- rescue ::UrlScan::ResponseError => _e
45
- nil
46
44
  end
47
45
 
48
46
  def valid_target_type?
@@ -50,16 +50,10 @@ module Mihari
50
50
  else
51
51
  raise InvalidInputError, "#{indicator}(type: #{type || 'unknown'}) is not supported." unless valid_type?
52
52
  end
53
- rescue ::VirusTotal::Error => _e
54
- nil
55
53
  end
56
54
 
57
55
  def domain_lookup
58
- begin
59
- res = api.domain.resolutions(indicator)
60
- rescue ::VirusTotal::Error => _e
61
- return nil
62
- end
56
+ res = api.domain.resolutions(indicator)
63
57
 
64
58
  data = res.dig("data") || []
65
59
  data.map do |item|
@@ -68,11 +62,7 @@ module Mihari
68
62
  end
69
63
 
70
64
  def ip_lookup
71
- begin
72
- res = api.ip_address.resolutions(indicator)
73
- rescue ::VirusTotal::Error => _e
74
- return nil
75
- end
65
+ res = api.ip_address.resolutions(indicator)
76
66
 
77
67
  data = res.dig("data") || []
78
68
  data.map do |item|
@@ -5,6 +5,8 @@ require "json"
5
5
 
6
6
  module Mihari
7
7
  class CLI < Thor
8
+ class_option :config, type: :string, desc: "path to config file"
9
+
8
10
  desc "censys [QUERY]", "Censys IPv4 search by a query"
9
11
  method_option :title, type: :string, desc: "title"
10
12
  method_option :description, type: :string, desc: "description"
@@ -280,15 +282,29 @@ module Mihari
280
282
  %w(title description artifacts).all? { |key| json.key? key }
281
283
  end
282
284
 
285
+ def load_configuration
286
+ config = options["config"]
287
+ Config.load_from_yaml(config) if config
288
+ end
289
+
283
290
  def run_analyzer(analyzer_class, query:, options:)
291
+ load_configuration
292
+
284
293
  options = symbolize_hash_keys(options)
294
+ options = normalize_options(options)
285
295
 
286
296
  analyzer = analyzer_class.new(query, **options)
287
297
  analyzer.run
288
298
  end
289
299
 
290
300
  def symbolize_hash_keys(hash)
291
- hash.map{ |k, v| [k.to_sym, v] }.to_h
301
+ hash.map { |k, v| [k.to_sym, v] }.to_h
302
+ end
303
+
304
+ def normalize_options(options)
305
+ # Delete :config because it is not intended to use for running an analyzer
306
+ options.delete(:config)
307
+ options
292
308
  end
293
309
 
294
310
  def refang(indicator)
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "yaml"
4
+
5
+ module Mihari
6
+ class Config
7
+ class << self
8
+ def load_from_yaml(path)
9
+ raise ArgumentError, "#{path} does not exist." unless File.exist?(path)
10
+
11
+ data = File.read(path)
12
+ begin
13
+ yaml = YAML.safe_load(data)
14
+ rescue TypeError => _e
15
+ return
16
+ end
17
+
18
+ yaml.each do |key, value|
19
+ ENV[key.upcase] = value
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Mihari
4
- VERSION = "0.17.0"
4
+ VERSION = "0.17.1"
5
5
  end
@@ -24,7 +24,7 @@ Gem::Specification.new do |spec|
24
24
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
25
25
  spec.require_paths = ["lib"]
26
26
 
27
- spec.add_development_dependency "bundler", "~> 2.0"
27
+ spec.add_development_dependency "bundler", "~> 2.1"
28
28
  spec.add_development_dependency "coveralls", "~> 0.8"
29
29
  spec.add_development_dependency "fakefs", "~> 0.20"
30
30
  spec.add_development_dependency "rake", "~> 13.0"
@@ -46,7 +46,7 @@ Gem::Specification.new do |spec|
46
46
  spec.add_dependency "misp", "~> 0.1"
47
47
  spec.add_dependency "murmurhash3", "~> 0.1"
48
48
  spec.add_dependency "net-ping", "~> 2.0"
49
- spec.add_dependency "onyphe", "~> 1.0"
49
+ spec.add_dependency "onyphe", "~> 1.1"
50
50
  spec.add_dependency "parallel", "~> 1.19"
51
51
  spec.add_dependency "passive_circl", "~> 0.1"
52
52
  spec.add_dependency "passivetotalx", "~> 0.1"
@@ -55,8 +55,8 @@ Gem::Specification.new do |spec|
55
55
  spec.add_dependency "securitytrails", "~> 1.0"
56
56
  spec.add_dependency "shodanx", "~> 0.2"
57
57
  spec.add_dependency "slack-notifier", "~> 2.3"
58
- spec.add_dependency "thor", "~> 0.20"
59
- spec.add_dependency "urlscan", "~> 0.4"
58
+ spec.add_dependency "thor", "~> 1.0"
59
+ spec.add_dependency "urlscan", "~> 0.5"
60
60
  spec.add_dependency "virustotalx", "~> 1.1"
61
61
  spec.add_dependency "zoomeye-rb", "~> 0.1"
62
62
  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.17.0
4
+ version: 0.17.1
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-12-11 00:00:00.000000000 Z
11
+ date: 2019-12-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '2.0'
19
+ version: '2.1'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '2.0'
26
+ version: '2.1'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: coveralls
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -310,14 +310,14 @@ dependencies:
310
310
  requirements:
311
311
  - - "~>"
312
312
  - !ruby/object:Gem::Version
313
- version: '1.0'
313
+ version: '1.1'
314
314
  type: :runtime
315
315
  prerelease: false
316
316
  version_requirements: !ruby/object:Gem::Requirement
317
317
  requirements:
318
318
  - - "~>"
319
319
  - !ruby/object:Gem::Version
320
- version: '1.0'
320
+ version: '1.1'
321
321
  - !ruby/object:Gem::Dependency
322
322
  name: parallel
323
323
  requirement: !ruby/object:Gem::Requirement
@@ -436,28 +436,28 @@ dependencies:
436
436
  requirements:
437
437
  - - "~>"
438
438
  - !ruby/object:Gem::Version
439
- version: '0.20'
439
+ version: '1.0'
440
440
  type: :runtime
441
441
  prerelease: false
442
442
  version_requirements: !ruby/object:Gem::Requirement
443
443
  requirements:
444
444
  - - "~>"
445
445
  - !ruby/object:Gem::Version
446
- version: '0.20'
446
+ version: '1.0'
447
447
  - !ruby/object:Gem::Dependency
448
448
  name: urlscan
449
449
  requirement: !ruby/object:Gem::Requirement
450
450
  requirements:
451
451
  - - "~>"
452
452
  - !ruby/object:Gem::Version
453
- version: '0.4'
453
+ version: '0.5'
454
454
  type: :runtime
455
455
  prerelease: false
456
456
  version_requirements: !ruby/object:Gem::Requirement
457
457
  requirements:
458
458
  - - "~>"
459
459
  - !ruby/object:Gem::Version
460
- version: '0.4'
460
+ version: '0.5'
461
461
  - !ruby/object:Gem::Dependency
462
462
  name: virustotalx
463
463
  requirement: !ruby/object:Gem::Requirement
@@ -534,6 +534,7 @@ files:
534
534
  - lib/mihari/artifact.rb
535
535
  - lib/mihari/cache.rb
536
536
  - lib/mihari/cli.rb
537
+ - lib/mihari/config.rb
537
538
  - lib/mihari/configurable.rb
538
539
  - lib/mihari/emitters/base.rb
539
540
  - lib/mihari/emitters/misp.rb