mihari 1.2.1 → 1.4.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: 5bd4fc32291966114c9c687f44c930d1974348cc61a36cf682f33efcc617118f
4
- data.tar.gz: a7ed78b49a8b3fe3e9ea398d1e41d13c3ed9f3dd6c23ac2de4e1d8cd8328e59e
3
+ metadata.gz: 3739df12ff7fe35c98ad1dbd181fd8b300486443e36b7ed50bbbd8507a00eccf
4
+ data.tar.gz: 43e048cf9eb60f8c0e32cbd43b729e25fa86da2e09784dc24d52163260653988
5
5
  SHA512:
6
- metadata.gz: f752ce54d8cccc4b6f8c81a87939dabf707629ca1ce5c3244f7ae7a595e808b0a326dc068eac58f705b48b65c7d378aa22f7ee062bcce3d967a6e3518ea29974
7
- data.tar.gz: 00110a28edd487a1f4f200f3f0fd93f28b8fd358de936651453b2caa75420a90b330f1605f3a8c2a3e36b362fc269a178b693f1752249768591dbb413dcaf555
6
+ metadata.gz: f62b84ba24b7405b0977414c6c91c9d97219a77f5d166c46c83682613a99f19a17dfedd8768f560eed7c0e6d28d7ea343a332400512748551b518b8e09e038fd
7
+ data.tar.gz: 794a4b44504e01cbb8b772fb7d7f9e389b67895352e4552549cf02bb70827695d44424ba583059020394ea0eb620a58ef05c4e34bed78b9dabc842abad996516
data/README.md CHANGED
@@ -71,6 +71,7 @@ Mihari supports the following services by default.
71
71
  - [PassiveTotal](https://community.riskiq.com/)
72
72
  - [SecurityTrails](https://securitytrails.com/)
73
73
  - [Shodan](https://shodan.io)
74
+ - [Spyse](https://spyse.com)
74
75
  - [urlscan.io](https://urlscan.io)
75
76
  - [VirusTotal](http://virustotal.com)
76
77
  - [ZoomEye](https://zoomeye.org)
@@ -99,6 +100,7 @@ Commands:
99
100
  mihari securitytrails [IP|DOMAIN|EMAIL] # SecurityTrails lookup by an ip, domain or email
100
101
  mihari securitytrails_domain_feed [REGEXP] # SecurityTrails new domain feed search by a regexp
101
102
  mihari shodan [QUERY] # Shodan host search by a query
103
+ mihari spyse [QUERY] # Spyse search by a query
102
104
  mihari ssh_fingerprint [FINGERPRINT] # Cross search with search engines by an SSH fingerprint (e.g. dc:14:de:8e:d7:c1:15:43:23:82:25:81:d2:59:e8:c0)
103
105
  mihari status # Show the current configuration status
104
106
  mihari urlscan [QUERY] # urlscan search by a given query
@@ -221,8 +223,10 @@ Configuration can be done via environment variables or a YAML file.
221
223
  | SHODAN_API_KEY | Shodan API key | |
222
224
  | SLACK_CHANNEL | Slack channel name | `#general` |
223
225
  | SLACK_WEBHOOK_URL | Slack Webhook URL | |
226
+ | SPYSE_API_KEY | Spyse API key | |
224
227
  | THEHIVE_API_ENDPOINT | TheHive URL | |
225
228
  | THEHIVE_API_KEY | TheHive API key | |
229
+ | URLSCAN_API_KEY | urlscan.io API key | |
226
230
  | VIRUSTOTAL_API_KEY | VirusTotal API key | |
227
231
  | ZOOMEYE_PASSWORD | ZoomEye password | |
228
232
  | ZOOMEYE_USERNAMME | ZoomEye username | |
@@ -56,6 +56,7 @@ require "mihari/analyzers/pulsedive"
56
56
  require "mihari/analyzers/securitytrails_domain_feed"
57
57
  require "mihari/analyzers/securitytrails"
58
58
  require "mihari/analyzers/shodan"
59
+ require "mihari/analyzers/spyse"
59
60
  require "mihari/analyzers/urlscan"
60
61
  require "mihari/analyzers/virustotal"
61
62
  require "mihari/analyzers/zoomeye"
@@ -37,6 +37,10 @@ module Mihari
37
37
 
38
38
  def search_with_page(query, page: 1)
39
39
  api.host.search(query, page: page)
40
+ rescue ::BinaryEdge::Error => e
41
+ raise RetryableError, e if e.message.include?("Request time limit exceeded")
42
+
43
+ raise e
40
44
  end
41
45
 
42
46
  def search
@@ -45,6 +45,10 @@ 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
+ raise RetryableError, e if e.message.include?("request timed out")
50
+
51
+ raise e
48
52
  end
49
53
 
50
54
  def search
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spyse"
4
+ require "json"
5
+
6
+ module Mihari
7
+ module Analyzers
8
+ class Spyse < Base
9
+ attr_reader :query
10
+ attr_reader :type
11
+
12
+ attr_reader :title
13
+ attr_reader :description
14
+ attr_reader :tags
15
+
16
+ def initialize(query, title: nil, description: nil, tags: [], type: "domain")
17
+ super()
18
+
19
+ @query = query
20
+
21
+ @title = title || "Spyse lookup"
22
+ @description = description || "query = #{query}"
23
+ @tags = tags
24
+ @type = type
25
+ end
26
+
27
+ def artifacts
28
+ lookup || []
29
+ end
30
+
31
+ private
32
+
33
+ def search_params
34
+ @search_params ||= JSON.parse(query)
35
+ end
36
+
37
+ def config_keys
38
+ %w(spyse_api_key)
39
+ end
40
+
41
+ def api
42
+ @api ||= ::Spyse::API.new(Mihari.config.spyse_api_key)
43
+ end
44
+
45
+ def valid_type?
46
+ %w(ip domain cert).include? type
47
+ end
48
+
49
+ def domain_lookup
50
+ res = api.domain.search(search_params, limit: 100)
51
+ items = res.dig("data", "items") || []
52
+ items.map do |item|
53
+ item.dig("name")
54
+ end.uniq.compact
55
+ end
56
+
57
+ def ip_lookup
58
+ res = api.ip.search(search_params, limit: 100)
59
+ items = res.dig("data", "items") || []
60
+ items.map do |item|
61
+ item.dig("ip")
62
+ end.uniq.compact
63
+ end
64
+
65
+ def lookup
66
+ case type
67
+ when "domain"
68
+ domain_lookup
69
+ when "ip"
70
+ ip_lookup
71
+ else
72
+ raise InvalidInputError, "#{query}(type: #{type || 'unknown'}) is not supported." unless valid_type?
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -9,16 +9,33 @@ module Mihari
9
9
  attr_reader :description
10
10
  attr_reader :query
11
11
  attr_reader :tags
12
+
13
+ attr_reader :filter
12
14
  attr_reader :target_type
15
+ attr_reader :use_pro
16
+ attr_reader :use_similarity
13
17
 
14
- def initialize(query, title: nil, description: nil, tags: [], target_type: "url")
18
+ def initialize(
19
+ query,
20
+ description: nil,
21
+ filter: nil,
22
+ tags: [],
23
+ target_type: "url",
24
+ title: nil,
25
+ use_pro: false,
26
+ use_similarity: false
27
+ )
15
28
  super()
16
29
 
17
30
  @query = query
18
31
  @title = title || "urlscan lookup"
19
32
  @description = description || "query = #{query}"
20
33
  @tags = tags
34
+
35
+ @filter = filter
21
36
  @target_type = target_type
37
+ @use_pro = use_pro
38
+ @use_similarity = use_similarity
22
39
 
23
40
  raise InvalidInputError, "type should be url, domain or ip." unless valid_target_type?
24
41
  end
@@ -35,11 +52,18 @@ module Mihari
35
52
 
36
53
  private
37
54
 
55
+ def config_keys
56
+ %w(urlscan_api_key)
57
+ end
58
+
38
59
  def api
39
- @api ||= ::UrlScan::API.new
60
+ @api ||= ::UrlScan::API.new(Mihari.config.urlscan_api_key)
40
61
  end
41
62
 
42
63
  def search
64
+ return api.pro.similar(query) if use_similarity
65
+ return api.pro.search(query: query, filter: filter, size: 10_000) if use_pro
66
+
43
67
  api.search(query, size: 10_000)
44
68
  end
45
69
 
@@ -7,6 +7,10 @@ module Mihari
7
7
  class CLI < Thor
8
8
  class_option :config, type: :string, desc: "path to config file"
9
9
 
10
+ def self.exit_on_failure?
11
+ true
12
+ end
13
+
10
14
  desc "censys [QUERY]", "Censys IPv4 search by a query"
11
15
  method_option :title, type: :string, desc: "title"
12
16
  method_option :description, type: :string, desc: "description"
@@ -42,7 +46,10 @@ module Mihari
42
46
  method_option :title, type: :string, desc: "title"
43
47
  method_option :description, type: :string, desc: "description"
44
48
  method_option :tags, type: :array, desc: "tags"
49
+ method_option :filter, type: :string, desc: "filter for urlscan pro search"
45
50
  method_option :target_type, type: :string, default: "url", desc: "target type to fetch from lookup results (target type should be 'url', 'domain' or 'ip')"
51
+ method_option :use_pro, type: :boolean, default: false, desc: "use pro search API or not"
52
+ method_option :use_similarity, type: :boolean, default: false, desc: "use similarity API or not"
46
53
  def urlscan(query)
47
54
  with_error_handling do
48
55
  run_analyzer Analyzers::Urlscan, query: query, options: options
@@ -174,6 +181,17 @@ module Mihari
174
181
  end
175
182
  end
176
183
 
184
+ desc "spyse [QUERY]", "Spyse search by a query"
185
+ method_option :title, type: :string, desc: "title"
186
+ method_option :description, type: :string, desc: "description"
187
+ method_option :tags, type: :array, desc: "tags"
188
+ method_option :type, type: :string, desc: "type to search (ip or domain)", default: "doamin"
189
+ def spyse(query)
190
+ with_error_handling do
191
+ run_analyzer Analyzers::Spyse, query: query, options: options
192
+ end
193
+ end
194
+
177
195
  desc "passive_dns [IP|DOMAIN]", "Cross search with passive DNS services by an ip or domain"
178
196
  method_option :title, type: :string, desc: "title"
179
197
  method_option :description, type: :string, desc: "description"
@@ -20,8 +20,10 @@ module Mihari
20
20
  attr_accessor :shodan_api_key
21
21
  attr_accessor :slack_channel
22
22
  attr_accessor :slack_webhook_url
23
+ attr_accessor :spyse_api_key
23
24
  attr_accessor :thehive_api_endpoint
24
25
  attr_accessor :thehive_api_key
26
+ attr_accessor :urlscan_api_key
25
27
  attr_accessor :virustotal_api_key
26
28
  attr_accessor :zoomeye_password
27
29
  attr_accessor :zoomeye_username
@@ -49,8 +51,10 @@ module Mihari
49
51
  @shodan_api_key = ENV["SHODAN_API_KEY"]
50
52
  @slack_channel = ENV["SLACK_CHANNEL"]
51
53
  @slack_webhook_url = ENV["SLACK_WEBHOOK_URL"]
54
+ @spyse_api_key = ENV["SPYSE_API_KEY"]
52
55
  @thehive_api_endpoint = ENV["THEHIVE_API_ENDPOINT"]
53
56
  @thehive_api_key = ENV["THEHIVE_API_KEY"]
57
+ @urlscan_api_key = ENV["URLSCAN_API_KEY"]
54
58
  @virustotal_api_key = ENV["VIRUSTOTAL_API_KEY"]
55
59
  @zoomeye_password = ENV["ZOOMEYE_PASSWORD"]
56
60
  @zoomeye_username = ENV["ZOOMEYE_USERNAME"]
@@ -3,4 +3,5 @@
3
3
  module Mihari
4
4
  class Error < StandardError; end
5
5
  class InvalidInputError < Error; end
6
+ class RetryableError < Error; end
6
7
  end
@@ -7,7 +7,7 @@ module Mihari
7
7
  begin
8
8
  try += 1
9
9
  yield
10
- rescue Errno::ECONNRESET, Errno::ECONNABORTED, Errno::EPIPE, OpenSSL::SSL::SSLError, Timeout::Error, ::Shodan::Error => e
10
+ rescue Errno::ECONNRESET, Errno::ECONNABORTED, Errno::EPIPE, OpenSSL::SSL::SSLError, Timeout::Error, RetryableError => e
11
11
  sleep interval
12
12
  retry if try < times
13
13
  raise e
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Mihari
4
- VERSION = "1.2.1"
4
+ VERSION = "1.4.1"
5
5
  end
@@ -30,15 +30,15 @@ Gem::Specification.new do |spec|
30
30
  spec.add_development_dependency "fakefs", "~> 1.2"
31
31
  spec.add_development_dependency "pre-commit", "~> 0.39"
32
32
  spec.add_development_dependency "rake", "~> 13.0"
33
- spec.add_development_dependency "rspec", "~> 3.9"
34
- spec.add_development_dependency "rubocop", "~> 0.88"
35
- spec.add_development_dependency "rubocop-performance", "~> 1.7"
33
+ spec.add_development_dependency "rspec", "~> 3.10"
34
+ spec.add_development_dependency "rubocop", "~> 1.6.0"
35
+ spec.add_development_dependency "rubocop-performance", "~> 1.9"
36
36
  spec.add_development_dependency "timecop", "~> 0.9"
37
37
  spec.add_development_dependency "vcr", "~> 6.0"
38
- spec.add_development_dependency "webmock", "~> 3.8"
38
+ spec.add_development_dependency "webmock", "~> 3.10"
39
39
 
40
40
  spec.add_dependency "active_model_serializers", "~> 0.10"
41
- spec.add_dependency "activerecord", "~> 6.0"
41
+ spec.add_dependency "activerecord", "~> 6.1"
42
42
  spec.add_dependency "addressable", "~> 2.7"
43
43
  spec.add_dependency "binaryedge", "~> 0.1"
44
44
  spec.add_dependency "censu", "~> 0.2"
@@ -53,7 +53,7 @@ Gem::Specification.new do |spec|
53
53
  spec.add_dependency "net-ping", "~> 2.0"
54
54
  spec.add_dependency "onyphe", "~> 2.0"
55
55
  spec.add_dependency "otx_ruby", "~> 0.9"
56
- spec.add_dependency "parallel", "~> 1.19"
56
+ spec.add_dependency "parallel", "~> 1.20"
57
57
  spec.add_dependency "passive_circl", "~> 0.1"
58
58
  spec.add_dependency "passivetotalx", "~> 0.1"
59
59
  spec.add_dependency "pg", "~> 1.2"
@@ -62,9 +62,11 @@ Gem::Specification.new do |spec|
62
62
  spec.add_dependency "securitytrails", "~> 1.0"
63
63
  spec.add_dependency "shodanx", "~> 0.2"
64
64
  spec.add_dependency "slack-notifier", "~> 2.3"
65
+ spec.add_dependency "spysex", "~> 0.1"
65
66
  spec.add_dependency "sqlite3", "~> 1.4"
66
67
  spec.add_dependency "thor", "~> 1.0"
67
- spec.add_dependency "urlscan", "~> 0.5"
68
+ spec.add_dependency "thread_safe", "~> 0.3"
69
+ spec.add_dependency "urlscan", "~> 0.6"
68
70
  spec.add_dependency "virustotalx", "~> 1.1"
69
71
  spec.add_dependency "zoomeye-rb", "~> 0.1"
70
72
  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: 1.2.1
4
+ version: 1.4.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: 2020-08-10 00:00:00.000000000 Z
11
+ date: 2020-12-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -100,42 +100,42 @@ dependencies:
100
100
  requirements:
101
101
  - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: '3.9'
103
+ version: '3.10'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: '3.9'
110
+ version: '3.10'
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: rubocop
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
115
  - - "~>"
116
116
  - !ruby/object:Gem::Version
117
- version: '0.88'
117
+ version: 1.6.0
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
- version: '0.88'
124
+ version: 1.6.0
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: rubocop-performance
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
129
  - - "~>"
130
130
  - !ruby/object:Gem::Version
131
- version: '1.7'
131
+ version: '1.9'
132
132
  type: :development
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
136
  - - "~>"
137
137
  - !ruby/object:Gem::Version
138
- version: '1.7'
138
+ version: '1.9'
139
139
  - !ruby/object:Gem::Dependency
140
140
  name: timecop
141
141
  requirement: !ruby/object:Gem::Requirement
@@ -170,14 +170,14 @@ dependencies:
170
170
  requirements:
171
171
  - - "~>"
172
172
  - !ruby/object:Gem::Version
173
- version: '3.8'
173
+ version: '3.10'
174
174
  type: :development
175
175
  prerelease: false
176
176
  version_requirements: !ruby/object:Gem::Requirement
177
177
  requirements:
178
178
  - - "~>"
179
179
  - !ruby/object:Gem::Version
180
- version: '3.8'
180
+ version: '3.10'
181
181
  - !ruby/object:Gem::Dependency
182
182
  name: active_model_serializers
183
183
  requirement: !ruby/object:Gem::Requirement
@@ -198,14 +198,14 @@ dependencies:
198
198
  requirements:
199
199
  - - "~>"
200
200
  - !ruby/object:Gem::Version
201
- version: '6.0'
201
+ version: '6.1'
202
202
  type: :runtime
203
203
  prerelease: false
204
204
  version_requirements: !ruby/object:Gem::Requirement
205
205
  requirements:
206
206
  - - "~>"
207
207
  - !ruby/object:Gem::Version
208
- version: '6.0'
208
+ version: '6.1'
209
209
  - !ruby/object:Gem::Dependency
210
210
  name: addressable
211
211
  requirement: !ruby/object:Gem::Requirement
@@ -408,14 +408,14 @@ dependencies:
408
408
  requirements:
409
409
  - - "~>"
410
410
  - !ruby/object:Gem::Version
411
- version: '1.19'
411
+ version: '1.20'
412
412
  type: :runtime
413
413
  prerelease: false
414
414
  version_requirements: !ruby/object:Gem::Requirement
415
415
  requirements:
416
416
  - - "~>"
417
417
  - !ruby/object:Gem::Version
418
- version: '1.19'
418
+ version: '1.20'
419
419
  - !ruby/object:Gem::Dependency
420
420
  name: passive_circl
421
421
  requirement: !ruby/object:Gem::Requirement
@@ -528,6 +528,20 @@ dependencies:
528
528
  - - "~>"
529
529
  - !ruby/object:Gem::Version
530
530
  version: '2.3'
531
+ - !ruby/object:Gem::Dependency
532
+ name: spysex
533
+ requirement: !ruby/object:Gem::Requirement
534
+ requirements:
535
+ - - "~>"
536
+ - !ruby/object:Gem::Version
537
+ version: '0.1'
538
+ type: :runtime
539
+ prerelease: false
540
+ version_requirements: !ruby/object:Gem::Requirement
541
+ requirements:
542
+ - - "~>"
543
+ - !ruby/object:Gem::Version
544
+ version: '0.1'
531
545
  - !ruby/object:Gem::Dependency
532
546
  name: sqlite3
533
547
  requirement: !ruby/object:Gem::Requirement
@@ -556,20 +570,34 @@ dependencies:
556
570
  - - "~>"
557
571
  - !ruby/object:Gem::Version
558
572
  version: '1.0'
573
+ - !ruby/object:Gem::Dependency
574
+ name: thread_safe
575
+ requirement: !ruby/object:Gem::Requirement
576
+ requirements:
577
+ - - "~>"
578
+ - !ruby/object:Gem::Version
579
+ version: '0.3'
580
+ type: :runtime
581
+ prerelease: false
582
+ version_requirements: !ruby/object:Gem::Requirement
583
+ requirements:
584
+ - - "~>"
585
+ - !ruby/object:Gem::Version
586
+ version: '0.3'
559
587
  - !ruby/object:Gem::Dependency
560
588
  name: urlscan
561
589
  requirement: !ruby/object:Gem::Requirement
562
590
  requirements:
563
591
  - - "~>"
564
592
  - !ruby/object:Gem::Version
565
- version: '0.5'
593
+ version: '0.6'
566
594
  type: :runtime
567
595
  prerelease: false
568
596
  version_requirements: !ruby/object:Gem::Requirement
569
597
  requirements:
570
598
  - - "~>"
571
599
  - !ruby/object:Gem::Version
572
- version: '0.5'
600
+ version: '0.6'
573
601
  - !ruby/object:Gem::Dependency
574
602
  name: virustotalx
575
603
  requirement: !ruby/object:Gem::Requirement
@@ -642,6 +670,7 @@ files:
642
670
  - lib/mihari/analyzers/securitytrails.rb
643
671
  - lib/mihari/analyzers/securitytrails_domain_feed.rb
644
672
  - lib/mihari/analyzers/shodan.rb
673
+ - lib/mihari/analyzers/spyse.rb
645
674
  - lib/mihari/analyzers/ssh_fingerprint.rb
646
675
  - lib/mihari/analyzers/urlscan.rb
647
676
  - lib/mihari/analyzers/virustotal.rb
@@ -698,7 +727,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
698
727
  - !ruby/object:Gem::Version
699
728
  version: '0'
700
729
  requirements: []
701
- rubygems_version: 3.1.2
730
+ rubygems_version: 3.1.4
702
731
  signing_key:
703
732
  specification_version: 4
704
733
  summary: A framework for continuous malicious hosts monitoring.