mihari 1.0.0 → 1.2.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: '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: []