mihari 0.1.0 → 0.2.0

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: a60ee7c7a40195a7b6b49484ce1df99926278721bd77603b6c9d0f3a952c4ac2
4
- data.tar.gz: 5c51449f1c2c3a7e14f745490c2bee6f2d18c3f5e5eaafc25a2ba55b15e83e12
3
+ metadata.gz: 777180f61db321707c6f72c02256fd9e2da24d5cc45f66430d8666a1baf36601
4
+ data.tar.gz: 888a4dea9f82823635b9c45418102a57ad60865bf769ddffbc14582d6244efe1
5
5
  SHA512:
6
- metadata.gz: dba9abb2e8c856bd2fc814daf4d7d4b5d63912d707c6e4e1225dc8ecb3d7f07067d6e8764509013a99621902fb24d7a74c8dd8a5dcbde00ec2469075799458db
7
- data.tar.gz: 53f255209c397224a7250c5adc6323c1e99a833426f9304649c779751f0299a898c28c9b911289bf941ebed8b8ab0b61c9aef298153acf3fe269a9e9044b58e5
6
+ metadata.gz: 54c3574805ccd106646d4a75841d79d0ae8da6b1d1062b92d7d202439b15254772e625e6d64aeacc384c7727bc756f3452281ed1bf51ddc0a47df92c7f5873f5
7
+ data.tar.gz: 616b4e01a4af3454c9e1d9e5dad4834d553facff5981a462f371991ff391539335b76114652def78d19c64d10583e6bff9fa7ba2a5e475dc79f79065338916cd
data/README.md CHANGED
@@ -12,27 +12,35 @@ mihari(`見張り`) is a framework for continuous malicious hosts (C2 / landing
12
12
  - mihari creates an alert with the artifacts on the TheHive instance.
13
13
  - mihari sends a notification to Slack. (Optional)
14
14
 
15
+ ### Screenshots
16
+
17
+ - TheHive alert example
18
+
19
+ ![img](./screenshots/alert.png)
20
+
21
+ - Slack notification example
22
+
23
+ ![img](./screenshots/slack.png)
24
+
15
25
  ## Installation
16
26
 
17
27
  ```bash
18
28
  gem install mihari
19
29
  ```
20
30
 
21
- ## Configuration
22
-
23
- All configuration is done via ENV variables.
31
+ ## Basic usage
24
32
 
25
- | Key | Desc. | Required or optional |
26
- |----------------------|--------------------|--------------------------------|
27
- | THEHIVE_API_ENDPOINT | TheHive URL | Required |
28
- | THEHIVE_API_KEY | TheHive API key | Required |
29
- | SLACK_WEBHOOK_URL | Slack Webhook URL | Optional |
30
- | SLACK_CHANNEL | Slack channel name | Optional (default: `#general`) |
31
- | CENSYS_ID | CENSYS API ID | Optional |
32
- | CENSYS_SECRET | CENSYS secret | Optional |
33
- | SHODAN_API_KEY | Shodan API key | Optional |
33
+ mihari supports Censys, Shodan and Onyphe by default.
34
34
 
35
- ## Basic usage
35
+ ```bash
36
+ $ mihari
37
+ Commands:
38
+ mihari censys [QUERY] # Censys IPv4 lookup by a given query
39
+ mihari help [COMMAND] # Describe available commands or one specific command
40
+ mihari import_from_json # Give a JSON input via STDIN
41
+ mihari onyphe [QUERY] # Onyphe datascan lookup by a given query
42
+ mihari shodan [QUERY] # Shodan host lookup by a given query
43
+ ```
36
44
 
37
45
  ### Censys
38
46
 
@@ -46,6 +54,12 @@ mihari censys "YOUR_QUERY"
46
54
  mihari shodan "YOUR QUERY"
47
55
  ```
48
56
 
57
+ ### Onyphe
58
+
59
+ ```bash
60
+ mihari onyphe "YOUR QUERY"
61
+ ```
62
+
49
63
  ### Import from JSON
50
64
 
51
65
  ```bash
@@ -68,6 +82,21 @@ The input is a JSON data should have `title`, `description` and `artifacts` key.
68
82
  | description | A description of an alert |
69
83
  | artifacts | An array of artifacts (supported data types: ip, domain, url, email, hash) |
70
84
 
85
+ ## Configuration
86
+
87
+ All configuration is done via ENV variables.
88
+
89
+ | Key | Desc. | Required or optional |
90
+ |----------------------|--------------------|--------------------------------|
91
+ | THEHIVE_API_ENDPOINT | TheHive URL | Required |
92
+ | THEHIVE_API_KEY | TheHive API key | Required |
93
+ | SLACK_WEBHOOK_URL | Slack Webhook URL | Optional |
94
+ | SLACK_CHANNEL | Slack channel name | Optional (default: `#general`) |
95
+ | CENSYS_ID | Censys API ID | Optional |
96
+ | CENSYS_SECRET | Censys secret | Optional |
97
+ | SHODAN_API_KEY | Shodan API key | Optional |
98
+ | ONYPHE_API_KEY | Onyphe API key | Optional |
99
+
71
100
  ## How to create a custom analyzer
72
101
 
73
102
  Create a class which extends `Mihari::Analyzers::Base` and implements the following methods.
@@ -25,6 +25,7 @@ require "mihari/the_hive"
25
25
  require "mihari/analyzers/base"
26
26
  require "mihari/analyzers/basic"
27
27
  require "mihari/analyzers/censys"
28
+ require "mihari/analyzers/onyphe"
28
29
  require "mihari/analyzers/shodan"
29
30
 
30
31
  require "mihari/notifiers/base"
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "onyphe"
4
+
5
+ module Mihari
6
+ module Analyzers
7
+ class Onyphe < Base
8
+ attr_reader :api
9
+ attr_reader :title
10
+ attr_reader :description
11
+ attr_reader :query
12
+
13
+ def initialize(query)
14
+ super()
15
+
16
+ @api = ::Onyphe::API.new
17
+ @query = query
18
+ @title = "Onyphe lookup"
19
+ @description = "Query: #{query}"
20
+ end
21
+
22
+ def artifacts
23
+ result = search
24
+ return [] unless result
25
+
26
+ results = result.dig("results") || []
27
+ results.map { |e| e.dig("ip") }.compact
28
+ end
29
+
30
+ private
31
+
32
+ def search
33
+ api.datascan(query)
34
+ rescue ::Onyphe::Error => _e
35
+ nil
36
+ end
37
+ end
38
+ end
39
+ end
@@ -1,12 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "open-uri"
4
- require "json"
3
+ require "shodan"
5
4
 
6
5
  module Mihari
7
6
  module Analyzers
8
7
  class Shodan < Base
9
- attr_reader :api_key
8
+ attr_reader :api
10
9
  attr_reader :title
11
10
  attr_reader :description
12
11
  attr_reader :query
@@ -14,10 +13,7 @@ module Mihari
14
13
  def initialize(query)
15
14
  super()
16
15
 
17
- api_key = ENV.fetch("SHODAN_API_KEY", nil)
18
- raise ArgumentError, "SHODAN_API_KEY is required" unless api_key
19
-
20
- @api_key = api_key
16
+ @api = ::Shodan::API.new
21
17
  @query = query
22
18
  @title = "Shodan lookup"
23
19
  @description = "Query: #{query}"
@@ -36,12 +32,9 @@ module Mihari
36
32
  private
37
33
 
38
34
  def search
39
- uri = URI("https://api.shodan.io/shodan/host/search?key=#{api_key}&query=#{query}")
40
- begin
41
- JSON.parse uri.read
42
- rescue OpenURI::HTTPError
43
- nil
44
- end
35
+ api.host.search(query)
36
+ rescue ::Shodan::Error => _e
37
+ nil
45
38
  end
46
39
  end
47
40
  end
@@ -5,7 +5,7 @@ require "json"
5
5
 
6
6
  module Mihari
7
7
  class CLI < Thor
8
- desc "censys [QUERY]", "Censys lookup by a given query"
8
+ desc "censys [QUERY]", "Censys IPv4 lookup by a given query"
9
9
  def censys(query)
10
10
  with_error_handling do
11
11
  censys = Analyzers::Censys.new(query)
@@ -13,7 +13,7 @@ module Mihari
13
13
  end
14
14
  end
15
15
 
16
- desc "shodan [QUERY]", "Shodan lookup by a given query"
16
+ desc "shodan [QUERY]", "Shodan host lookup by a given query"
17
17
  def shodan(query)
18
18
  with_error_handling do
19
19
  shodan = Analyzers::Shodan.new(query)
@@ -21,6 +21,14 @@ module Mihari
21
21
  end
22
22
  end
23
23
 
24
+ desc "onyphe [QUERY]", "Onyphe datascan lookup by a given query"
25
+ def onyphe(query)
26
+ with_error_handling do
27
+ onyphe = Analyzers::Onyphe.new(query)
28
+ onyphe.run
29
+ end
30
+ end
31
+
24
32
  desc "import_from_json", "Give a JSON input via STDIN"
25
33
  def import_from_json(input = nil)
26
34
  json = input || STDIN.gets.chomp
@@ -51,7 +59,7 @@ module Mihari
51
59
 
52
60
  def parse_as_json(input)
53
61
  JSON.parse input
54
- rescue JSON::ParserError => _
62
+ rescue JSON::ParserError => e
55
63
  nil
56
64
  end
57
65
 
@@ -2,10 +2,13 @@
2
2
 
3
3
  require "slack/incoming/webhooks"
4
4
  require "digest/sha2"
5
+ require "mem"
5
6
 
6
7
  module Mihari
7
8
  module Notifiers
8
9
  class Attachment
10
+ include Mem
11
+
9
12
  attr_reader :data, :data_type
10
13
 
11
14
  def initialize(data:, data_type:)
@@ -13,8 +16,53 @@ module Mihari
13
16
  @data_type = data_type
14
17
  end
15
18
 
19
+ def vt_link
20
+ return nil unless _vt_link
21
+
22
+ {
23
+ fallback: "VT link",
24
+ title: data,
25
+ title_link: _vt_link,
26
+ footer: "virustotal.com",
27
+ footer_icon: "http://www.google.com/s2/favicons?domain=virustotal.com"
28
+ }
29
+ end
30
+
31
+ def urlscan_link
32
+ return nil unless _urlscan_link
33
+
34
+ {
35
+ fallback: "urlscan.io link",
36
+ title: data,
37
+ title_link: _urlscan_link,
38
+ footer: "urlscan.io",
39
+ footer_icon: "http://www.google.com/s2/favicons?domain=urlscan.io"
40
+ }
41
+ end
42
+
43
+ # @return [Array]
44
+ def to_a
45
+ [vt_link, urlscan_link].compact
46
+ end
47
+
48
+ private
49
+
16
50
  # @return [String]
17
- def link
51
+ def _urlscan_link
52
+ case data_type
53
+ when "ip"
54
+ "https://urlscan.io/ip/#{data}"
55
+ when "domain"
56
+ "https://urlscan.io/domain/#{data}"
57
+ when "url"
58
+ uri = URI(data)
59
+ "https://urlscan.io/domain/#{uri.hostname}"
60
+ end
61
+ end
62
+ memoize :_urlscan_link
63
+
64
+ # @return [String]
65
+ def _vt_link
18
66
  case data_type
19
67
  when "hash"
20
68
  "https://www.virustotal.com/#/file/#{data}"
@@ -26,23 +74,9 @@ module Mihari
26
74
  "https://www.virustotal.com/#/url/#{sha256}"
27
75
  when "mail"
28
76
  "https://www.virustotal.com/#/search/#{data}"
29
- else
30
- ""
31
77
  end
32
78
  end
33
-
34
- # @return [Hash]
35
- def to_h
36
- {
37
- fallback: "VT link",
38
- title: data,
39
- title_link: link,
40
- footer: "virustotal.com",
41
- footer_icon: "http://www.google.com/s2/favicons?domain=virustotal.com"
42
- }
43
- end
44
-
45
- private
79
+ memoize :_vt_link
46
80
 
47
81
  # @return [String]
48
82
  def sha256
@@ -72,8 +106,8 @@ module Mihari
72
106
 
73
107
  def to_attachments(artifacts)
74
108
  artifacts.map do |artifact|
75
- Attachment.new(data: artifact.data, data_type: artifact.data_type).to_h
76
- end
109
+ Attachment.new(data: artifact.data, data_type: artifact.data_type).to_a
110
+ end.flatten
77
111
  end
78
112
 
79
113
  def notify(title:, description:, artifacts:)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Mihari
4
- VERSION = "0.1.0"
4
+ VERSION = "0.2.0"
5
5
  end
@@ -36,7 +36,9 @@ Gem::Specification.new do |spec|
36
36
  spec.add_dependency "email_address", "~> 0.1"
37
37
  spec.add_dependency "hachi", "~> 0.1"
38
38
  spec.add_dependency "mem", "~> 0.1"
39
+ spec.add_dependency "onyphe", "~> 0.2"
39
40
  spec.add_dependency "public_suffix", "~> 3.0"
41
+ spec.add_dependency "shodanx", "~> 0.1"
40
42
  spec.add_dependency "slack-incoming-webhooks", "~> 0.2"
41
43
  spec.add_dependency "thor", "~> 0.19"
42
44
  end
Binary file
Binary file
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.1.0
4
+ version: 0.2.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: 2019-04-23 00:00:00.000000000 Z
11
+ date: 2019-05-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -164,6 +164,20 @@ dependencies:
164
164
  - - "~>"
165
165
  - !ruby/object:Gem::Version
166
166
  version: '0.1'
167
+ - !ruby/object:Gem::Dependency
168
+ name: onyphe
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - "~>"
172
+ - !ruby/object:Gem::Version
173
+ version: '0.2'
174
+ type: :runtime
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - "~>"
179
+ - !ruby/object:Gem::Version
180
+ version: '0.2'
167
181
  - !ruby/object:Gem::Dependency
168
182
  name: public_suffix
169
183
  requirement: !ruby/object:Gem::Requirement
@@ -178,6 +192,20 @@ dependencies:
178
192
  - - "~>"
179
193
  - !ruby/object:Gem::Version
180
194
  version: '3.0'
195
+ - !ruby/object:Gem::Dependency
196
+ name: shodanx
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - "~>"
200
+ - !ruby/object:Gem::Version
201
+ version: '0.1'
202
+ type: :runtime
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - "~>"
207
+ - !ruby/object:Gem::Version
208
+ version: '0.1'
181
209
  - !ruby/object:Gem::Dependency
182
210
  name: slack-incoming-webhooks
183
211
  requirement: !ruby/object:Gem::Requirement
@@ -230,6 +258,7 @@ files:
230
258
  - lib/mihari/analyzers/base.rb
231
259
  - lib/mihari/analyzers/basic.rb
232
260
  - lib/mihari/analyzers/censys.rb
261
+ - lib/mihari/analyzers/onyphe.rb
233
262
  - lib/mihari/analyzers/shodan.rb
234
263
  - lib/mihari/artifact.rb
235
264
  - lib/mihari/cli.rb
@@ -241,6 +270,8 @@ files:
241
270
  - lib/mihari/type_checker.rb
242
271
  - lib/mihari/version.rb
243
272
  - mihari.gemspec
273
+ - screenshots/alert.png
274
+ - screenshots/slack.png
244
275
  homepage: https://github.com/ninoseki/mihari
245
276
  licenses:
246
277
  - MIT