mihari 1.0.0 → 1.2.1

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: '099c3dece3c31a745979b619c361d3bcff09e67abb3214c32747a935d57be963'
4
- data.tar.gz: 1f777f2ca61721716e32e85846817a5183d11063573813adec757919bb27f457
3
+ metadata.gz: 5bd4fc32291966114c9c687f44c930d1974348cc61a36cf682f33efcc617118f
4
+ data.tar.gz: a7ed78b49a8b3fe3e9ea398d1e41d13c3ed9f3dd6c23ac2de4e1d8cd8328e59e
5
5
  SHA512:
6
- metadata.gz: b8e0babf78935a90d1d4d39493ed7db77d498697a1ea8d2bbdf3277745544a0f7a59de6dc444e93065f66c339b9c5208df408748194cb490ffe3901681a9aa0b
7
- data.tar.gz: 0b430d270f34f1fae64f384b672a4270500407e725f0f8f99bba278b134d74196fda894b4ed425ed21d363583da93e40648dce77b9ff39a9b0da07c7f5a7a5d2
6
+ metadata.gz: f752ce54d8cccc4b6f8c81a87939dabf707629ca1ce5c3244f7ae7a595e808b0a326dc068eac58f705b48b65c7d378aa22f7ee062bcce3d967a6e3518ea29974
7
+ data.tar.gz: 00110a28edd487a1f4f200f3f0fd93f28b8fd358de936651453b2caa75420a90b330f1605f3a8c2a3e36b362fc269a178b693f1752249768591dbb413dcaf555
@@ -1,8 +1,13 @@
1
1
  ---
2
- sudo: false
3
2
  language: ruby
4
3
  cache: bundler
4
+ services:
5
+ - postgresql
5
6
  rvm:
6
7
  - 2.6
7
8
  - 2.7
9
+ env:
10
+ - DATABASE=":memory:"
11
+ - DATABASE="postgresql://postgres@0.0.0.0:5432/travis_ci_test"
8
12
  before_install: gem install bundler -v 2.1
13
+ before_script: psql -c 'create database travis_ci_test;' -U postgres
data/README.md CHANGED
@@ -11,7 +11,7 @@ Mihari is a helper to run queries & manage results continuously. Mihari can be u
11
11
  ## How it works
12
12
 
13
13
  - Mihari makes a query against Shodan, Censys, VirusTotal, SecurityTrails, etc. and extracts artifacts (IP addresses, domains, URLs and hashes) from the results.
14
- - Mihari checks whether a DB (SQLite3) contains the artifacts or not.
14
+ - Mihari checks whether a DB (SQLite3 or PostgreSQL) contains the artifacts or not.
15
15
  - If it doesn't contain the artifacts:
16
16
  - Mihari creates an alert on TheHive. (Optional)
17
17
  - Mihari sends a notification to Slack. (Optional)
@@ -33,6 +33,17 @@ Mihari is a helper to run queries & manage results continuously. Mihari can be u
33
33
 
34
34
  ![img](https://github.com/ninoseki/mihari/raw/master/screenshots/misp.png)
35
35
 
36
+ ## Requirements
37
+
38
+ - Ruby 2.6+
39
+ - SQLite3
40
+ - libpq
41
+
42
+ ```bash
43
+ # For Debian / Ubuntu
44
+ apt-get install sqlite3 libsqlite3-dev libpq-dev
45
+ ```
46
+
36
47
  ## Installation
37
48
 
38
49
  ```bash
@@ -56,6 +67,7 @@ Mihari supports the following services by default.
56
67
  - [DN Pedia](https://dnpedia.com/)
57
68
  - [dnstwister](https://dnstwister.report/)
58
69
  - [Onyphe](https://onyphe.io)
70
+ - [OTX](https://otx.alienvault.com/)
59
71
  - [PassiveTotal](https://community.riskiq.com/)
60
72
  - [SecurityTrails](https://securitytrails.com/)
61
73
  - [Shodan](https://shodan.io)
@@ -78,6 +90,7 @@ Commands:
78
90
  mihari http_hash # Cross search with search engines by a hash of an HTTP response (SHA256, MD5 and MurmurHash3)
79
91
  mihari import_from_json # Give a JSON input via STDIN
80
92
  mihari onyphe [QUERY] # Onyphe datascan search by a query
93
+ mihari otx [IP|DOMAIN] # OTX lookup by an IP or domain
81
94
  mihari passive_dns [IP|DOMAIN] # Cross search with passive DNS services by an ip or domain
82
95
  mihari passive_ssl [SHA1] # Cross search with passive SSL services by an SHA1 certificate fingerprint
83
96
  mihari passivetotal [IP|DOMAIN|EMAIL|SHA1] # PassiveTotal lookup by an ip, domain, email or SHA1 certificate fingerprint
@@ -105,7 +118,7 @@ You can get aggregated results by using the following commands.
105
118
 
106
119
  | Command | Desc. |
107
120
  |-----------------|---------------------------------------------------------------------------------------------------------|
108
- | passive_dns | Passive DNS lookup with CIRCL passive DNS, PassiveTotal, Pulsedive, SecurityTrails and VirusTotal |
121
+ | passive_dns | Passive DNS lookup with CIRCL passive DNS, OTX, PassiveTotal, Pulsedive, SecurityTrails and VirusTotal |
109
122
  | passive_ssl | Passive SSL lookup with CIRCL passive SSL and PassiveTotal |
110
123
  | reverse_whois | Revese Whois lookup with PassiveTotal and SecurityTrails |
111
124
  | http_hash | HTTP response hash lookup with BinaryEdge(SHA256), Censys(SHA256), Onyphpe(MD5) and Shodan(MurmurHash3) |
@@ -189,29 +202,30 @@ The input is a JSON data should have `title`, `description` and `artifacts` key.
189
202
 
190
203
  Configuration can be done via environment variables or a YAML file.
191
204
 
192
- | Key | Description | Default |
193
- |------------------------|--------------------------------|-------------|
194
- | DATABASE | A path to the SQLite database | `mihari.db` |
195
- | BINARYEDGE_API_KEY | BinaryEdge API key | |
196
- | CENSYS_ID | Censys API ID | |
197
- | CENSYS_SECRET | Censys secret | |
198
- | CIRCL_PASSIVE_PASSWORD | CIRCL passive DNS/SSL password | |
199
- | CIRCL_PASSIVE_USERNAME | CIRCL passive DNS/SSL username | |
200
- | MISP_API_ENDPOINT | MISP URL | |
201
- | MISP_API_KEY | MISP API key | |
202
- | ONYPHE_API_KEY | Onyphe API key | |
203
- | PASSIVETOTAL_API_KEY | PassiveTotal API key | |
204
- | PASSIVETOTAL_USERNAME | PassiveTotal username | |
205
- | PULSEDIVE_API_KEY | Pulsedive API key | |
206
- | SECURITYTRAILS_API_KEY | SecurityTrails API key | |
207
- | SHODAN_API_KEY | Shodan API key | |
208
- | SLACK_CHANNEL | Slack channel name | `#general` |
209
- | SLACK_WEBHOOK_URL | Slack Webhook URL | |
210
- | THEHIVE_API_ENDPOINT | TheHive URL | |
211
- | THEHIVE_API_KEY | TheHive API key | |
212
- | VIRUSTOTAL_API_KEY | VirusTotal API key | |
213
- | ZOOMEYE_PASSWORD | ZoomEye password | |
214
- | ZOOMEYE_USERNAMME | ZoomEye username | |
205
+ | Key | Description | Default |
206
+ |------------------------|-------------------------------------------------------------------------------------------------|-------------|
207
+ | DATABASE | A path to the SQLite database or a DB URL (e.g. `postgres://postgres:pass@db.host:5432/somedb`) | `mihari.db` |
208
+ | BINARYEDGE_API_KEY | BinaryEdge API key | |
209
+ | CENSYS_ID | Censys API ID | |
210
+ | CENSYS_SECRET | Censys secret | |
211
+ | CIRCL_PASSIVE_PASSWORD | CIRCL passive DNS/SSL password | |
212
+ | CIRCL_PASSIVE_USERNAME | CIRCL passive DNS/SSL username | |
213
+ | MISP_API_ENDPOINT | MISP URL | |
214
+ | MISP_API_KEY | MISP API key | |
215
+ | ONYPHE_API_KEY | Onyphe API key | |
216
+ | OTX_API_KEY | OTX API key | |
217
+ | PASSIVETOTAL_API_KEY | PassiveTotal API key | |
218
+ | PASSIVETOTAL_USERNAME | PassiveTotal username | |
219
+ | PULSEDIVE_API_KEY | Pulsedive API key | |
220
+ | SECURITYTRAILS_API_KEY | SecurityTrails API key | |
221
+ | SHODAN_API_KEY | Shodan API key | |
222
+ | SLACK_CHANNEL | Slack channel name | `#general` |
223
+ | SLACK_WEBHOOK_URL | Slack Webhook URL | |
224
+ | THEHIVE_API_ENDPOINT | TheHive URL | |
225
+ | THEHIVE_API_KEY | TheHive API key | |
226
+ | VIRUSTOTAL_API_KEY | VirusTotal API key | |
227
+ | ZOOMEYE_PASSWORD | ZoomEye password | |
228
+ | ZOOMEYE_USERNAMME | ZoomEye username | |
215
229
 
216
230
  Instead of using environment variables, you can use a YAML file for configuration.
217
231
 
@@ -1,5 +1,5 @@
1
- FROM ruby:2.6-alpine3.10
2
- RUN apk --no-cache add git build-base ruby-dev \
1
+ FROM ruby:2.7-alpine3.10
2
+ RUN apk --no-cache add git build-base ruby-dev sqlite-dev postgresql-dev \
3
3
  && cd /tmp/ \
4
4
  && git clone https://github.com/ninoseki/mihari.git \
5
5
  && cd mihari \
@@ -50,6 +50,7 @@ require "mihari/analyzers/crtsh"
50
50
  require "mihari/analyzers/dnpedia"
51
51
  require "mihari/analyzers/dnstwister"
52
52
  require "mihari/analyzers/onyphe"
53
+ require "mihari/analyzers/otx"
53
54
  require "mihari/analyzers/passivetotal"
54
55
  require "mihari/analyzers/pulsedive"
55
56
  require "mihari/analyzers/securitytrails_domain_feed"
@@ -71,9 +72,9 @@ require "mihari/notifiers/slack"
71
72
  require "mihari/notifiers/exception_notifier"
72
73
 
73
74
  require "mihari/emitters/base"
75
+ require "mihari/emitters/database"
74
76
  require "mihari/emitters/misp"
75
77
  require "mihari/emitters/slack"
76
- require "mihari/emitters/sqlite"
77
78
  require "mihari/emitters/stdout"
78
79
  require "mihari/emitters/the_hive"
79
80
 
@@ -2,17 +2,21 @@
2
2
 
3
3
  module Mihari
4
4
  class AlertViewer
5
- attr_reader :limit
5
+ def list(title: nil, source: nil, tag: nil, limit: 5)
6
+ limit = limit.to_i
7
+ raise ArgumentError, "limit should be bigger than zero" unless limit.positive?
6
8
 
7
- def initialize(limit: 5)
8
- @limit = limit.to_i
9
- raise ArgumentError, "limit should be bigger than zero" unless @limit.positive?
10
- end
9
+ relation = Alert.includes(:tags, :artifacts)
10
+ relation = relation.where(title: title) if title
11
+ relation = relation.where(source: source) if source
12
+ relation = relation.where(tags: { name: tag } ) if tag
11
13
 
12
- def list
13
- alerts = Alert.order(id: :desc).limit(limit).includes(:tags, :artifacts)
14
+ alerts = relation.limit(limit).order(id: :desc)
14
15
  alerts.map do |alert|
15
- AlertSerializer.new(alert).as_json
16
+ json = AlertSerializer.new(alert).as_json
17
+ json[:artifacts] = (json.dig(:artifacts) || []).map { |artifact_| artifact_.dig(:data) }
18
+ json[:tags] = (json.dig(:tags) || []).map { |tag_| tag_.dig(:name) }
19
+ json
16
20
  end
17
21
  end
18
22
  end
@@ -52,7 +52,7 @@ module Mihari
52
52
  end
53
53
 
54
54
  def config_keys
55
- [Mihari.config.binaryedge_api_key]
55
+ %w(binaryedge_api_key)
56
56
  end
57
57
 
58
58
  def api
@@ -86,7 +86,7 @@ module Mihari
86
86
  end
87
87
 
88
88
  def config_keys
89
- [Mihari.config.censys_id, Mihari.config.censys_secret]
89
+ %w(censys_id censys_secret)
90
90
  end
91
91
 
92
92
  def api
@@ -27,7 +27,7 @@ module Mihari
27
27
  private
28
28
 
29
29
  def config_keys
30
- [Mihari.config.circl_passive_password, Mihari.config.circl_passive_username]
30
+ %w(circl_passive_password circl_passive_username)
31
31
  end
32
32
 
33
33
  def api
@@ -35,7 +35,7 @@ module Mihari
35
35
  PAGE_SIZE = 10
36
36
 
37
37
  def config_keys
38
- [Mihari.config.onyphe_api_key]
38
+ %w(onyphe_api_key)
39
39
  end
40
40
 
41
41
  def api
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "otx_ruby"
4
+
5
+ module Mihari
6
+ module Analyzers
7
+ class OTX < Base
8
+ attr_reader :query
9
+ attr_reader :type
10
+
11
+ attr_reader :title
12
+ attr_reader :description
13
+ attr_reader :tags
14
+
15
+ def initialize(query, title: nil, description: nil, tags: [])
16
+ super()
17
+
18
+ @query = query
19
+ @type = TypeChecker.type(query)
20
+
21
+ @title = title || "OTX lookup"
22
+ @description = description || "query = #{query}"
23
+ @tags = tags
24
+ end
25
+
26
+ def artifacts
27
+ lookup || []
28
+ end
29
+
30
+ private
31
+
32
+ def config_keys
33
+ %w(otx_api_key)
34
+ end
35
+
36
+ def domain_client
37
+ @domain_client ||= ::OTX::Domain.new(Mihari.config.otx_api_key)
38
+ end
39
+
40
+ def ip_client
41
+ @ip_client ||= ::OTX::IP.new(Mihari.config.otx_api_key)
42
+ end
43
+
44
+ def valid_type?
45
+ %w(ip domain).include? type
46
+ end
47
+
48
+ def lookup
49
+ case type
50
+ when "domain"
51
+ domain_lookup
52
+ when "ip"
53
+ ip_lookup
54
+ else
55
+ raise InvalidInputError, "#{query}(type: #{type || 'unknown'}) is not supported." unless valid_type?
56
+ end
57
+ end
58
+
59
+ def domain_lookup
60
+ records = domain_client.get_passive_dns(query)
61
+ records.map do |record|
62
+ record.address if record.record_type == "A"
63
+ end.compact.uniq
64
+ end
65
+
66
+ def ip_lookup
67
+ records = ip_client.get_passive_dns(query)
68
+ records.map do |record|
69
+ record.hostname if record.record_type == "A"
70
+ end.compact.uniq
71
+ end
72
+ end
73
+ end
74
+ end
@@ -14,6 +14,7 @@ module Mihari
14
14
 
15
15
  ANALYZERS = [
16
16
  Mihari::Analyzers::CIRCL,
17
+ Mihari::Analyzers::OTX,
17
18
  Mihari::Analyzers::PassiveTotal,
18
19
  Mihari::Analyzers::Pulsedive,
19
20
  Mihari::Analyzers::SecurityTrails,
@@ -55,7 +56,7 @@ module Mihari
55
56
  analyzer.artifacts
56
57
  rescue ArgumentError, InvalidInputError => _e
57
58
  nil
58
- rescue ::PassiveCIRCL::Error, ::PassiveTotal::Error, ::Pulsedive::ResponseError, ::SecurityTrails::Error, ::VirusTotal::Error => _e
59
+ rescue Faraday::Error, ::PassiveCIRCL::Error, ::PassiveTotal::Error, ::Pulsedive::ResponseError, ::SecurityTrails::Error, ::VirusTotal::Error => _e
59
60
  nil
60
61
  end
61
62
  end
@@ -30,7 +30,7 @@ module Mihari
30
30
  private
31
31
 
32
32
  def config_keys
33
- [Mihari.config.passivetotal_username, Mihari.config.passivetotal_api_key]
33
+ %w(passivetotal_username passivetotal_api_key)
34
34
  end
35
35
 
36
36
  def api
@@ -30,7 +30,7 @@ module Mihari
30
30
  private
31
31
 
32
32
  def config_keys
33
- [Mihari.config.pulsedive_api_key]
33
+ %w(pulsedive_api_key)
34
34
  end
35
35
 
36
36
  def api
@@ -30,7 +30,7 @@ module Mihari
30
30
  private
31
31
 
32
32
  def config_keys
33
- [Mihari.config.securitytrails_api_key]
33
+ %w(securitytrails_api_key)
34
34
  end
35
35
 
36
36
  def api
@@ -32,7 +32,7 @@ module Mihari
32
32
  private
33
33
 
34
34
  def config_keys
35
- [Mihari.config.securitytrails_api_key]
35
+ %w(securitytrails_api_key)
36
36
  end
37
37
 
38
38
  def api
@@ -36,7 +36,7 @@ module Mihari
36
36
  PAGE_SIZE = 100
37
37
 
38
38
  def config_keys
39
- [Mihari.config.shodan_api_key]
39
+ %w(shodan_api_key)
40
40
  end
41
41
 
42
42
  def api
@@ -30,7 +30,7 @@ module Mihari
30
30
  private
31
31
 
32
32
  def config_keys
33
- [Mihari.config.virustotal_api_key]
33
+ %w(virustotal_api_key)
34
34
  end
35
35
 
36
36
  def api
@@ -41,7 +41,7 @@ module Mihari
41
41
  end
42
42
 
43
43
  def config_keys
44
- [Mihari.config.zoomeye_password, Mihari.config.zoomeye_username]
44
+ %w(zoomeye_password zoomeye_username)
45
45
  end
46
46
 
47
47
  def api
@@ -164,6 +164,16 @@ module Mihari
164
164
  end
165
165
  end
166
166
 
167
+ desc "otx [IP|DOMAIN]", "OTX lookup by an IP or domain"
168
+ method_option :title, type: :string, desc: "title"
169
+ method_option :description, type: :string, desc: "description"
170
+ method_option :tags, type: :array, desc: "tags"
171
+ def otx(domain)
172
+ with_error_handling do
173
+ run_analyzer Analyzers::OTX, query: refang(domain), options: options
174
+ end
175
+ end
176
+
167
177
  desc "passive_dns [IP|DOMAIN]", "Cross search with passive DNS services by an ip or domain"
168
178
  method_option :title, type: :string, desc: "title"
169
179
  method_option :description, type: :string, desc: "description"
@@ -249,10 +259,15 @@ module Mihari
249
259
 
250
260
  desc "alerts", "Show the alerts on TheHive"
251
261
  method_option :limit, type: :string, default: "5", desc: "Number of alerts to show (or 'all' to show all the alerts)"
262
+ method_option :title, type: :string, desc: "Title to filter"
263
+ method_option :source, type: :string, desc: "Source to filter"
264
+ method_option :tag, type: :string, desc: "Tag to filter"
252
265
  def alerts
253
266
  with_error_handling do
254
- viewer = AlertViewer.new(limit: options["limit"])
255
- alerts = viewer.list
267
+ load_configuration
268
+
269
+ viewer = AlertViewer.new
270
+ alerts = viewer.list(limit: options["limit"], title: options["title"], source: options["source"], tag: options[:tag])
256
271
  puts JSON.pretty_generate(alerts)
257
272
  end
258
273
  end
@@ -261,6 +276,7 @@ module Mihari
261
276
  def status
262
277
  with_error_handling do
263
278
  load_configuration
279
+
264
280
  puts JSON.pretty_generate(Status.check)
265
281
  end
266
282
  end
@@ -286,7 +302,10 @@ module Mihari
286
302
 
287
303
  def load_configuration
288
304
  config = options["config"]
289
- Config.load_configuration(config) if config
305
+ return unless config
306
+
307
+ Config.load_from_yaml(config)
308
+ Database.connect
290
309
  end
291
310
 
292
311
  def run_analyzer(analyzer_class, query:, options:)
@@ -12,6 +12,7 @@ module Mihari
12
12
  attr_accessor :misp_api_endpoint
13
13
  attr_accessor :misp_api_key
14
14
  attr_accessor :onyphe_api_key
15
+ attr_accessor :otx_api_key
15
16
  attr_accessor :passivetotal_api_key
16
17
  attr_accessor :passivetotal_username
17
18
  attr_accessor :pulsedive_api_key
@@ -40,6 +41,7 @@ module Mihari
40
41
  @misp_api_endpoint = ENV["MISP_API_ENDPOINT"]
41
42
  @misp_api_key = ENV["MISP_API_KEY"]
42
43
  @onyphe_api_key = ENV["ONYPHE_API_KEY"]
44
+ @otx_api_key = ENV["OTX_API_KEY"]
43
45
  @passivetotal_api_key = ENV["PASSIVETOTAL_API_KEY"]
44
46
  @passivetotal_username = ENV["PASSIVETOTAL_USERNAME"]
45
47
  @pulsedive_api_key = ENV["PULSEDIVE_API_KEY"]
@@ -3,7 +3,7 @@
3
3
  module Mihari
4
4
  module Configurable
5
5
  def configured?
6
- config_keys.all? { |key| !key.nil? }
6
+ config_keys.all? { |key| Mihari.config.send(key) }
7
7
  end
8
8
 
9
9
  def configuration_status
@@ -2,11 +2,6 @@
2
2
 
3
3
  require "active_record"
4
4
 
5
- ActiveRecord::Base.establish_connection(
6
- adapter: "sqlite3",
7
- database: Mihari.config.database
8
- )
9
-
10
5
  class InitialSchema < ActiveRecord::Migration[6.0]
11
6
  def change
12
7
  create_table :tags, if_not_exists: true do |t|
@@ -37,9 +32,37 @@ class InitialSchema < ActiveRecord::Migration[6.0]
37
32
  end
38
33
  end
39
34
 
40
- begin
41
- ActiveRecord::Migration.verbose = false
42
- InitialSchema.migrate(:up)
43
- rescue StandardError
44
- # Do nothing
35
+ def adapter
36
+ return "postgresql" if Mihari.config.database.start_with?("postgresql://", "postgres://")
37
+
38
+ "sqlite3"
45
39
  end
40
+
41
+ module Mihari
42
+ class Database
43
+ class << self
44
+ def connect
45
+ case adapter
46
+ when "postgresql"
47
+ ActiveRecord::Base.establish_connection(Mihari.config.database)
48
+ else
49
+ ActiveRecord::Base.establish_connection(
50
+ adapter: adapter,
51
+ database: Mihari.config.database
52
+ )
53
+ end
54
+
55
+ ActiveRecord::Migration.verbose = false
56
+ InitialSchema.migrate(:up)
57
+ rescue StandardError
58
+ # Do nothing
59
+ end
60
+
61
+ def destroy!
62
+ InitialSchema.migrate(:down) if ActiveRecord::Base.connected?
63
+ end
64
+ end
65
+ end
66
+ end
67
+
68
+ Mihari::Database.connect
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Mihari
4
4
  module Emitters
5
- class SQLite < Base
5
+ class Database < Base
6
6
  def valid?
7
7
  true
8
8
  end
@@ -35,7 +35,7 @@ module Mihari
35
35
  private
36
36
 
37
37
  def config_keys
38
- [Mihari.config.misp_api_endpoint, Mihari.config.misp_api_key]
38
+ %w(misp_api_endpoint misp_api_key)
39
39
  end
40
40
 
41
41
  def build_attribute(artifact)
@@ -4,6 +4,8 @@ require "slack-notifier"
4
4
  require "digest/sha2"
5
5
  require "mem"
6
6
 
7
+ require "mihari/slack_monkeypatch"
8
+
7
9
  module Mihari
8
10
  module Emitters
9
11
  class Attachment
@@ -135,7 +137,7 @@ module Mihari
135
137
  private
136
138
 
137
139
  def config_keys
138
- [Mihari.config.slack_webhook_url]
140
+ %w(slack_webhook_url)
139
141
  end
140
142
  end
141
143
  end
@@ -27,7 +27,7 @@ module Mihari
27
27
  private
28
28
 
29
29
  def config_keys
30
- [Mihari.config.thehive_api_endpoint, Mihari.config.thehive_api_key]
30
+ %w(thehive_api_endpoint thehive_api_key)
31
31
  end
32
32
 
33
33
  def api
@@ -1,5 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "slack-notifier"
4
+ require "mihari/slack_monkeypatch"
5
+
3
6
  module Mihari
4
7
  module Notifiers
5
8
  class Slack < Base
@@ -7,10 +7,10 @@ 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 => _e
10
+ rescue Errno::ECONNRESET, Errno::ECONNABORTED, Errno::EPIPE, OpenSSL::SSL::SSLError, Timeout::Error, ::Shodan::Error => e
11
11
  sleep interval
12
12
  retry if try < times
13
- raise
13
+ raise e
14
14
  end
15
15
  end
16
16
  end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Slack
4
+ class Notifier
5
+ module Util
6
+ class LinkFormatter
7
+ class << self
8
+ def format(string, opts = {})
9
+ # Resolve warning in Ruby 2.7
10
+ LinkFormatter.new(string, **opts).formatted
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Mihari
4
- VERSION = "1.0.0"
4
+ VERSION = "1.2.1"
5
5
  end
@@ -26,15 +26,15 @@ Gem::Specification.new do |spec|
26
26
 
27
27
  spec.add_development_dependency "bundler", "~> 2.1"
28
28
  spec.add_development_dependency "coveralls", "~> 0.8"
29
- spec.add_development_dependency "execjs", "~> 2.0"
29
+ spec.add_development_dependency "execjs", "~> 2.7"
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
33
  spec.add_development_dependency "rspec", "~> 3.9"
34
- spec.add_development_dependency "rubocop", "~> 0.82"
35
- spec.add_development_dependency "rubocop-performance", "~> 1.5"
34
+ spec.add_development_dependency "rubocop", "~> 0.88"
35
+ spec.add_development_dependency "rubocop-performance", "~> 1.7"
36
36
  spec.add_development_dependency "timecop", "~> 0.9"
37
- spec.add_development_dependency "vcr", "~> 5.1"
37
+ spec.add_development_dependency "vcr", "~> 6.0"
38
38
  spec.add_development_dependency "webmock", "~> 3.8"
39
39
 
40
40
  spec.add_dependency "active_model_serializers", "~> 0.10"
@@ -52,9 +52,11 @@ Gem::Specification.new do |spec|
52
52
  spec.add_dependency "murmurhash3", "~> 0.1"
53
53
  spec.add_dependency "net-ping", "~> 2.0"
54
54
  spec.add_dependency "onyphe", "~> 2.0"
55
+ spec.add_dependency "otx_ruby", "~> 0.9"
55
56
  spec.add_dependency "parallel", "~> 1.19"
56
57
  spec.add_dependency "passive_circl", "~> 0.1"
57
58
  spec.add_dependency "passivetotalx", "~> 0.1"
59
+ spec.add_dependency "pg", "~> 1.2"
58
60
  spec.add_dependency "public_suffix", "~> 4.0"
59
61
  spec.add_dependency "pulsedive", "~> 0.1"
60
62
  spec.add_dependency "securitytrails", "~> 1.0"
@@ -0,0 +1,5 @@
1
+ {
2
+ "extends": [
3
+ "config:base"
4
+ ]
5
+ }
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.0.0
4
+ version: 1.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Manabu Niseki
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-05-03 00:00:00.000000000 Z
11
+ date: 2020-08-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -44,14 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '2.0'
47
+ version: '2.7'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '2.0'
54
+ version: '2.7'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: fakefs
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -114,28 +114,28 @@ dependencies:
114
114
  requirements:
115
115
  - - "~>"
116
116
  - !ruby/object:Gem::Version
117
- version: '0.82'
117
+ version: '0.88'
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.82'
124
+ version: '0.88'
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.5'
131
+ version: '1.7'
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.5'
138
+ version: '1.7'
139
139
  - !ruby/object:Gem::Dependency
140
140
  name: timecop
141
141
  requirement: !ruby/object:Gem::Requirement
@@ -156,14 +156,14 @@ dependencies:
156
156
  requirements:
157
157
  - - "~>"
158
158
  - !ruby/object:Gem::Version
159
- version: '5.1'
159
+ version: '6.0'
160
160
  type: :development
161
161
  prerelease: false
162
162
  version_requirements: !ruby/object:Gem::Requirement
163
163
  requirements:
164
164
  - - "~>"
165
165
  - !ruby/object:Gem::Version
166
- version: '5.1'
166
+ version: '6.0'
167
167
  - !ruby/object:Gem::Dependency
168
168
  name: webmock
169
169
  requirement: !ruby/object:Gem::Requirement
@@ -388,6 +388,20 @@ dependencies:
388
388
  - - "~>"
389
389
  - !ruby/object:Gem::Version
390
390
  version: '2.0'
391
+ - !ruby/object:Gem::Dependency
392
+ name: otx_ruby
393
+ requirement: !ruby/object:Gem::Requirement
394
+ requirements:
395
+ - - "~>"
396
+ - !ruby/object:Gem::Version
397
+ version: '0.9'
398
+ type: :runtime
399
+ prerelease: false
400
+ version_requirements: !ruby/object:Gem::Requirement
401
+ requirements:
402
+ - - "~>"
403
+ - !ruby/object:Gem::Version
404
+ version: '0.9'
391
405
  - !ruby/object:Gem::Dependency
392
406
  name: parallel
393
407
  requirement: !ruby/object:Gem::Requirement
@@ -430,6 +444,20 @@ dependencies:
430
444
  - - "~>"
431
445
  - !ruby/object:Gem::Version
432
446
  version: '0.1'
447
+ - !ruby/object:Gem::Dependency
448
+ name: pg
449
+ requirement: !ruby/object:Gem::Requirement
450
+ requirements:
451
+ - - "~>"
452
+ - !ruby/object:Gem::Version
453
+ version: '1.2'
454
+ type: :runtime
455
+ prerelease: false
456
+ version_requirements: !ruby/object:Gem::Requirement
457
+ requirements:
458
+ - - "~>"
459
+ - !ruby/object:Gem::Version
460
+ version: '1.2'
433
461
  - !ruby/object:Gem::Dependency
434
462
  name: public_suffix
435
463
  requirement: !ruby/object:Gem::Requirement
@@ -605,6 +633,7 @@ files:
605
633
  - lib/mihari/analyzers/free_text.rb
606
634
  - lib/mihari/analyzers/http_hash.rb
607
635
  - lib/mihari/analyzers/onyphe.rb
636
+ - lib/mihari/analyzers/otx.rb
608
637
  - lib/mihari/analyzers/passive_dns.rb
609
638
  - lib/mihari/analyzers/passive_ssl.rb
610
639
  - lib/mihari/analyzers/passivetotal.rb
@@ -622,9 +651,9 @@ files:
622
651
  - lib/mihari/configurable.rb
623
652
  - lib/mihari/database.rb
624
653
  - lib/mihari/emitters/base.rb
654
+ - lib/mihari/emitters/database.rb
625
655
  - lib/mihari/emitters/misp.rb
626
656
  - lib/mihari/emitters/slack.rb
627
- - lib/mihari/emitters/sqlite.rb
628
657
  - lib/mihari/emitters/stdout.rb
629
658
  - lib/mihari/emitters/the_hive.rb
630
659
  - lib/mihari/errors.rb
@@ -640,10 +669,12 @@ files:
640
669
  - lib/mihari/serializers/alert.rb
641
670
  - lib/mihari/serializers/artifact.rb
642
671
  - lib/mihari/serializers/tag.rb
672
+ - lib/mihari/slack_monkeypatch.rb
643
673
  - lib/mihari/status.rb
644
674
  - lib/mihari/type_checker.rb
645
675
  - lib/mihari/version.rb
646
676
  - mihari.gemspec
677
+ - renovate.json
647
678
  - screenshots/alert.png
648
679
  - screenshots/eyecatch.png
649
680
  - screenshots/misp.png
@@ -652,7 +683,7 @@ homepage: https://github.com/ninoseki/mihari
652
683
  licenses:
653
684
  - MIT
654
685
  metadata: {}
655
- post_install_message:
686
+ post_install_message:
656
687
  rdoc_options: []
657
688
  require_paths:
658
689
  - lib
@@ -668,7 +699,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
668
699
  version: '0'
669
700
  requirements: []
670
701
  rubygems_version: 3.1.2
671
- signing_key:
702
+ signing_key:
672
703
  specification_version: 4
673
704
  summary: A framework for continuous malicious hosts monitoring.
674
705
  test_files: []