mihari 1.0.1 → 1.1.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: 44cc5eea0746aa47918f5102cf4834fcd436b67f371b37f8a1e4fe6999902c82
4
- data.tar.gz: e0dd701f1d5b705239d73125ca8865fa15c949d4b62cb59a2c9beef8e01e363d
3
+ metadata.gz: 46761bb6c390e76763b5b76c711cd222a08735bb3e539862bb2cac211d44bfc3
4
+ data.tar.gz: 19cdc765f98da35dd299038ce8f310ce30cd4a7903a2c56344e97631fdf32f87
5
5
  SHA512:
6
- metadata.gz: 36722428cc688eaefd3f293f1de99db20b8671945082b1d5f1d08d61c9b977491e46f45122311010650d80b1f0077dd7ec9323e304c02fdcf9c4fc1b22c66672
7
- data.tar.gz: ad9e0603040bc4069194df7f21c0963e096beaa3e6e2ac13ea0d66803217619b885f3afef4624c0c45ae4282c64f8bda905bf61d8c564f9aef8c7a5b33bb2dca
6
+ metadata.gz: eda0f8f7537c6a9a456c225545bc615d3573f4789ce9b411faf3fc83cf155417adac87bd043e605303874199d24395f2a71e06275cae5909b9e2fb95221e4651
7
+ data.tar.gz: 38a9250b72efb654b1e8c10904077f205838a7d61742f3e545cef26d3703a161c60b77c1459ee10fd0d2fa814e1b234663fd13132cc2d406833aaf6d51519de8
data/.travis.yml CHANGED
@@ -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)
@@ -189,29 +189,29 @@ The input is a JSON data should have `title`, `description` and `artifacts` key.
189
189
 
190
190
  Configuration can be done via environment variables or a YAML file.
191
191
 
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 | |
192
+ | Key | Description | Default |
193
+ |------------------------|-------------------------------------------------------------------------------------------------|-------------|
194
+ | DATABASE | A path to the SQLite database or a DB URL (e.g. `postgres://postgres:pass@db.host:5432/somedb`) | `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 | |
215
215
 
216
216
  Instead of using environment variables, you can use a YAML file for configuration.
217
217
 
data/docker/Dockerfile CHANGED
@@ -1,12 +1,12 @@
1
1
  FROM ruby:2.6-alpine3.10
2
- RUN apk --no-cache add git build-base ruby-dev \
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 \
6
6
  && gem build mihari.gemspec -o mihari.gem \
7
7
  && gem install mihari.gem \
8
8
  && rm -rf /tmp/mihari \
9
- && apk del --purge git build-base ruby-dev
9
+ && apk del --purge git build-base ruby-dev sqlite-dev postgresql-dev
10
10
 
11
11
  ENTRYPOINT ["mihari"]
12
12
 
data/lib/mihari.rb CHANGED
@@ -71,9 +71,9 @@ require "mihari/notifiers/slack"
71
71
  require "mihari/notifiers/exception_notifier"
72
72
 
73
73
  require "mihari/emitters/base"
74
+ require "mihari/emitters/database"
74
75
  require "mihari/emitters/misp"
75
76
  require "mihari/emitters/slack"
76
- require "mihari/emitters/sqlite"
77
77
  require "mihari/emitters/stdout"
78
78
  require "mihari/emitters/the_hive"
79
79
 
@@ -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
@@ -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
data/lib/mihari/cli.rb CHANGED
@@ -249,10 +249,15 @@ module Mihari
249
249
 
250
250
  desc "alerts", "Show the alerts on TheHive"
251
251
  method_option :limit, type: :string, default: "5", desc: "Number of alerts to show (or 'all' to show all the alerts)"
252
+ method_option :title, type: :string, desc: "Title to filter"
253
+ method_option :source, type: :string, desc: "Source to filter"
254
+ method_option :tag, type: :string, desc: "Tag to filter"
252
255
  def alerts
253
256
  with_error_handling do
254
- viewer = AlertViewer.new(limit: options["limit"])
255
- alerts = viewer.list
257
+ load_configuration
258
+
259
+ viewer = AlertViewer.new
260
+ alerts = viewer.list(limit: options["limit"], title: options["title"], source: options["source"], tag: options[:tag])
256
261
  puts JSON.pretty_generate(alerts)
257
262
  end
258
263
  end
@@ -261,6 +266,7 @@ module Mihari
261
266
  def status
262
267
  with_error_handling do
263
268
  load_configuration
269
+
264
270
  puts JSON.pretty_generate(Status.check)
265
271
  end
266
272
  end
@@ -289,8 +295,7 @@ module Mihari
289
295
  return unless config
290
296
 
291
297
  Config.load_from_yaml(config)
292
- # reload database settings
293
- load File.expand_path("./database.rb", __dir__)
298
+ Database.connect
294
299
  end
295
300
 
296
301
  def run_analyzer(analyzer_class, query:, options:)
@@ -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)
@@ -135,7 +135,7 @@ module Mihari
135
135
  private
136
136
 
137
137
  def config_keys
138
- [Mihari.config.slack_webhook_url]
138
+ %w(slack_webhook_url)
139
139
  end
140
140
  end
141
141
  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,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Mihari
4
- VERSION = "1.0.1"
4
+ VERSION = "1.1.0"
5
5
  end
data/mihari.gemspec CHANGED
@@ -31,7 +31,6 @@ Gem::Specification.new do |spec|
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
34
  spec.add_development_dependency "rubocop-performance", "~> 1.5"
36
35
  spec.add_development_dependency "timecop", "~> 0.9"
37
36
  spec.add_development_dependency "vcr", "~> 5.1"
@@ -55,6 +54,7 @@ Gem::Specification.new do |spec|
55
54
  spec.add_dependency "parallel", "~> 1.19"
56
55
  spec.add_dependency "passive_circl", "~> 0.1"
57
56
  spec.add_dependency "passivetotalx", "~> 0.1"
57
+ spec.add_dependency "pg", "~> 1.2"
58
58
  spec.add_dependency "public_suffix", "~> 4.0"
59
59
  spec.add_dependency "pulsedive", "~> 0.1"
60
60
  spec.add_dependency "securitytrails", "~> 1.0"
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.1
4
+ version: 1.1.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: 2020-05-03 00:00:00.000000000 Z
11
+ date: 2020-05-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -108,20 +108,6 @@ dependencies:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
110
  version: '3.9'
111
- - !ruby/object:Gem::Dependency
112
- name: rubocop
113
- requirement: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - "~>"
116
- - !ruby/object:Gem::Version
117
- version: '0.82'
118
- type: :development
119
- prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- requirements:
122
- - - "~>"
123
- - !ruby/object:Gem::Version
124
- version: '0.82'
125
111
  - !ruby/object:Gem::Dependency
126
112
  name: rubocop-performance
127
113
  requirement: !ruby/object:Gem::Requirement
@@ -430,6 +416,20 @@ dependencies:
430
416
  - - "~>"
431
417
  - !ruby/object:Gem::Version
432
418
  version: '0.1'
419
+ - !ruby/object:Gem::Dependency
420
+ name: pg
421
+ requirement: !ruby/object:Gem::Requirement
422
+ requirements:
423
+ - - "~>"
424
+ - !ruby/object:Gem::Version
425
+ version: '1.2'
426
+ type: :runtime
427
+ prerelease: false
428
+ version_requirements: !ruby/object:Gem::Requirement
429
+ requirements:
430
+ - - "~>"
431
+ - !ruby/object:Gem::Version
432
+ version: '1.2'
433
433
  - !ruby/object:Gem::Dependency
434
434
  name: public_suffix
435
435
  requirement: !ruby/object:Gem::Requirement
@@ -622,9 +622,9 @@ files:
622
622
  - lib/mihari/configurable.rb
623
623
  - lib/mihari/database.rb
624
624
  - lib/mihari/emitters/base.rb
625
+ - lib/mihari/emitters/database.rb
625
626
  - lib/mihari/emitters/misp.rb
626
627
  - lib/mihari/emitters/slack.rb
627
- - lib/mihari/emitters/sqlite.rb
628
628
  - lib/mihari/emitters/stdout.rb
629
629
  - lib/mihari/emitters/the_hive.rb
630
630
  - lib/mihari/errors.rb