mihari 0.15.0 → 0.16.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: 720fd6a91aeb9dad3ad3ad37129b6f810da8dd66f6e007638471c52c7050313b
4
- data.tar.gz: 276123ca8645e124110c5f7cf9012481846344188ac0173792f9f2d16c5ea351
3
+ metadata.gz: b70407115db8ca6adbc35ecc24971e2b62d7726e5f226b56dc9323679634aa85
4
+ data.tar.gz: 681bb8f07a46cd3dcb6205a3699d4b2b205f3ac3e22b527af6ac79bddb1a4f70
5
5
  SHA512:
6
- metadata.gz: f4cdeaf7a7040a72ab30795c0ac2d446c13c1ceee3352384382c4faa912b6f8293db9ee3d69a08b72c84b206fc8a99e98df9253cc050196ea48d188497e3df9c
7
- data.tar.gz: da6e803d6c250be258cb0cb542cbb2255f413c6199a43dfd728f4f347129087b27857d36b8039d23ad475603c73dbe1e2b36ccd4f110eb02d44f0a7f02bc1f7a
6
+ metadata.gz: 3d5e0327c338fe14398a570fb4b028613a3ffd374bbd88046fc5993fd61071ddd73ab2b8e3535ea7613a3a0f10b43f0552799ab66cc0532296d4962247784582
7
+ data.tar.gz: 986e547c7c821ccd47cb0634eab643a908dba8a76a302564228c3da74cefe6c223fa6f79f6911f12b012aa9da19d68691d5025b5fe72b4888a8bee6809f7c9b6
data/README.md CHANGED
@@ -17,7 +17,7 @@ mihari(`見張り`) is a sidekick tool for [TheHive](https://github.com/TheHive-
17
17
  - mihari sends a notification to Slack. (Optional)
18
18
  - mihari creates an event on MISP. (Optional)
19
19
 
20
- ![img](https://github.com/ninoseki/mihari/blob/master/screenshots/eyecatch.png)
20
+ ![img](https://github.com/ninoseki/mihari/raw/master/screenshots/eyecatch.png)
21
21
 
22
22
  Check this blog post for more details: [Continuous C2 hunting with Censys, Shodan, Onyphe and TheHive](https://hackmd.io/s/SkUaSrqoE).
23
23
 
@@ -71,7 +71,7 @@ Commands:
71
71
  mihari alerts # Show the alerts on TheHive
72
72
  mihari binaryedge [QUERY] # BinaryEdge host search by a query
73
73
  mihari censys [QUERY] # Censys IPv4 search by a query
74
- mihari circl [DOMAIN|SHA1] # CIRCL passive DNS/SSL lookup by a domain / SHA1 certificate fingerprint
74
+ mihari circl [DOMAIN|SHA1] # CIRCL passive DNS/SSL lookup by a domain or SHA1 certificate fingerprint
75
75
  mihari crtsh [QUERY] # crt.sh search by a query
76
76
  mihari dnpedia [QUERY] # DNPedia domain search by a query
77
77
  mihari free_text [TEXT] # Cross search with search engines by a free text
@@ -79,14 +79,15 @@ Commands:
79
79
  mihari http_hash # Cross search with search engines by a hash of an HTTP response (SHA256, MD5 and MurmurHash3)
80
80
  mihari import_from_json # Give a JSON input via STDIN
81
81
  mihari onyphe [QUERY] # Onyphe datascan search by a query
82
- mihari passive_dns [IP|Domain] # Cross search with passive DNS services by an ip / domain
82
+ mihari passive_dns [IP|DOMAIN] # Cross search with passive DNS services by an ip or domain
83
83
  mihari passive_ssl [SHA1] # Cross search with passive SSL services by an SHA1 certificate fingerprint
84
- mihari passivetotal [IP|DOMAIN|EMAIL|SHA1] # PassiveTotal lookup by an ip / domain / email / SHA1 certificate fingerprint
85
- mihari reverse_whois [email] # Cross search with reverse whois services by an email
84
+ mihari passivetotal [IP|DOMAIN|EMAIL|SHA1] # PassiveTotal lookup by an ip, domain, email or SHA1 certificate fingerprint
85
+ mihari pulsedive [IP|DOMAIN] # Pulsedive lookup by an ip or domain
86
+ mihari reverse_whois [EMAIL] # Cross search with reverse whois services by an email
86
87
  mihari securitytrails [IP|DOMAIN|EMAIL] # SecurityTrails lookup by an ip, domain or email
87
88
  mihari securitytrails_domain_feed [REGEXP] # SecurityTrails new domain feed search by a regexp
88
89
  mihari shodan [QUERY] # Shodan host search by a query
89
- mihari ssh_fingerprint [FINGERPRINT] # Cross search with search engines by an SSH fingerprint
90
+ 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)
90
91
  mihari status # Show the current configuration status
91
92
  mihari urlscan [QUERY] # urlscan search by a given query
92
93
  mihari virustotal [IP|DOMAIN] # VirusTotal resolutions lookup by an ip or domain
@@ -102,13 +103,49 @@ You can get aggregated results by using the following commands.
102
103
 
103
104
  | Command | Desc. |
104
105
  | --------------- | ------------------------------------------------------------------------------------------------------- |
105
- | passive_dns | Passive DNS lookup with CIRCL passive DNS, PassiveTotal, SecurityTrails and VirusTotal |
106
+ | passive_dns | Passive DNS lookup with CIRCL passive DNS, PassiveTotal, Pulsedive, SecurityTrails and VirusTotal |
106
107
  | passive_ssl | Passive SSL lookup with CIRCL passive SSL and PassiveTotal |
107
108
  | reverse_whois | Revese Whois lookup with PassiveTotal and SecurityTrails |
108
109
  | http_hash | HTTP response hash lookup with BinaryEdge(SHA256), Censys(SHA256), Onyphpe(MD5) and Shodan(MurmurHash3) |
109
110
  | free_text | Free text lookup with BinaryEdge and Censys |
110
111
  | ssh_fingerprint | SSH fingerprint lookup with BinaryEdge and Shodan |
111
112
 
113
+ #### http_hash command
114
+
115
+ The usage of `http_hash` command is a little bit tricky.
116
+
117
+ ```bash
118
+ $ mihari help http_hash
119
+ Usage:
120
+ mihari http_hash
121
+
122
+ Options:
123
+ [--title=TITLE] # title
124
+ [--description=DESCRIPTION] # description
125
+ [--tags=one two three] # tags
126
+ [--md5=MD5] # MD5 hash
127
+ [--sha256=SHA256] # SHA256 hash
128
+ [--mmh3=N] # MurmurHash3 hash
129
+
130
+ Cross search with search engines by a hash of an HTTP response (SHA256, MD5 and MurmurHash3)
131
+
132
+ ```
133
+
134
+ There are 2 ways to use this command.
135
+
136
+ First one is passing `--md5`, `--sha256` and `--mmh3` parameters.
137
+
138
+ ```bash
139
+ mihari http_hash --md5=881191f7736b5b8cfad5959ca99d2a51 --sha256=b064187ebdc51721708ad98cd89dacc346017cb0fb0457d530032d387f1ff20e --mmh3=-1467534799
140
+ ```
141
+
142
+ Another one is passing `--html` parameter. In this case, hashes of an HTML file are automatically calculated.
143
+
144
+ ```bash
145
+ wget http://example.com -O /tmp/index.html
146
+ mihari http_hash --html /tmp/index.html
147
+ ```
148
+
112
149
  ### Example usages
113
150
 
114
151
  ```bash
@@ -202,6 +239,7 @@ All configuration is done via ENV variables.
202
239
  | ONYPHE_API_KEY | Onyphe API key | Optional |
203
240
  | PASSIVETOTAL_API_KEY | PassiveTotal API key | Optional |
204
241
  | PASSIVETOTAL_USERNAME | PassiveTotal username | Optional |
242
+ | PULSEDIVE_API_KEY | Pulsedive API key | Optional |
205
243
  | SECURITYTRAILS_API_KEY | SecurityTrails API key | Optional |
206
244
  | SHODAN_API_KEY | Shodan API key | Optional |
207
245
  | VIRUSTOTAL_API_KEY | VirusTotal API key | Optional |
@@ -26,6 +26,8 @@ require "mihari/artifact"
26
26
  require "mihari/cache"
27
27
  require "mihari/type_checker"
28
28
 
29
+ require "mihari/html"
30
+
29
31
  require "mihari/configurable"
30
32
  require "mihari/retriable"
31
33
 
@@ -44,6 +46,7 @@ require "mihari/analyzers/crtsh"
44
46
  require "mihari/analyzers/dnpedia"
45
47
  require "mihari/analyzers/onyphe"
46
48
  require "mihari/analyzers/passivetotal"
49
+ require "mihari/analyzers/pulsedive"
47
50
  require "mihari/analyzers/securitytrails_domain_feed"
48
51
  require "mihari/analyzers/securitytrails"
49
52
  require "mihari/analyzers/shodan"
@@ -9,17 +9,22 @@ module Mihari
9
9
  attr_reader :sha256
10
10
  attr_reader :mmh3
11
11
 
12
+ attr_reader :html
13
+
12
14
  attr_reader :title
13
15
  attr_reader :description
14
16
  attr_reader :tags
15
17
 
16
- def initialize(_query, md5: nil, sha256: nil, mmh3: nil, title: nil, description: nil, tags: [])
18
+ def initialize(_query, md5: nil, sha256: nil, mmh3: nil, html: nil, title: nil, description: nil, tags: [])
17
19
  super()
18
20
 
19
21
  @md5 = md5
20
22
  @sha256 = sha256
21
23
  @mmh3 = mmh3
22
24
 
25
+ @html = html
26
+ load_from_html
27
+
23
28
  @title = title || "HTTP hash cross search"
24
29
  @description = description || "query = #{query}"
25
30
  @tags = tags
@@ -37,6 +42,17 @@ module Mihari
37
42
  [md5, sha256, mmh3].compact.any?
38
43
  end
39
44
 
45
+ def load_from_html
46
+ return unless html
47
+
48
+ html_file = HTML.new(html)
49
+ return unless html_file.exists?
50
+
51
+ @md5 = html_file.md5
52
+ @sha256 = html_file.sha256
53
+ @mmh3 = html_file.mmh3
54
+ end
55
+
40
56
  def query
41
57
  [
42
58
  md5 ? "md5:#{md5}" : nil,
@@ -15,6 +15,7 @@ module Mihari
15
15
  ANALYZERS = [
16
16
  Mihari::Analyzers::CIRCL,
17
17
  Mihari::Analyzers::PassiveTotal,
18
+ Mihari::Analyzers::Pulsedive,
18
19
  Mihari::Analyzers::SecurityTrails,
19
20
  Mihari::Analyzers::VirusTotal,
20
21
  ].freeze
@@ -54,7 +55,7 @@ module Mihari
54
55
  analyzer.artifacts
55
56
  rescue ArgumentError, InvalidInputError => _e
56
57
  nil
57
- rescue ::PassiveCIRCL::Error, ::PassiveTotal::Error, ::SecurityTrails::Error, ::VirusTotal::Error => _e
58
+ rescue ::PassiveCIRCL::Error, ::PassiveTotal::Error, ::Pulsedive::ResponseError, ::SecurityTrails::Error, ::VirusTotal::Error => _e
58
59
  nil
59
60
  end
60
61
  end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pulsedive"
4
+
5
+ module Mihari
6
+ module Analyzers
7
+ class Pulsedive < 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 || "Pulsedive 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(PULSEDIVE_API_KEY)
34
+ end
35
+
36
+ def api
37
+ @api ||= ::Pulsedive::API.new
38
+ end
39
+
40
+ def valid_type?
41
+ %w(ip domain).include? type
42
+ end
43
+
44
+ def lookup
45
+ raise InvalidInputError, "#{query}(type: #{type || 'unknown'}) is not supported." unless valid_type?
46
+
47
+ indicator = api.indicator.get_by_value(query)
48
+ iid = indicator.dig("iid")
49
+
50
+ properties = api.indicator.get_properties_by_id(iid)
51
+ (properties.dig("dns") || []).map do |property|
52
+ property.dig("value") if ["A", "PTR"].include?(property.dig("name"))
53
+ end.compact
54
+ rescue ::Pulsedive::ResponseError => _e
55
+ nil
56
+ end
57
+ end
58
+ end
59
+ end
@@ -100,7 +100,7 @@ module Mihari
100
100
  end
101
101
  end
102
102
 
103
- desc "circl [DOMAIN|SHA1]", "CIRCL passive DNS/SSL lookup by a domain / SHA1 certificate fingerprint"
103
+ desc "circl [DOMAIN|SHA1]", "CIRCL passive DNS/SSL lookup by a domain or SHA1 certificate fingerprint"
104
104
  method_option :title, type: :string, desc: "title"
105
105
  method_option :description, type: :string, desc: "description"
106
106
  method_option :tags, type: :array, desc: "tags"
@@ -110,7 +110,7 @@ module Mihari
110
110
  end
111
111
  end
112
112
 
113
- desc "passivetotal [IP|DOMAIN|EMAIL|SHA1]", "PassiveTotal lookup by an ip / domain / email / SHA1 certificate fingerprint"
113
+ desc "passivetotal [IP|DOMAIN|EMAIL|SHA1]", "PassiveTotal lookup by an ip, domain, email or SHA1 certificate fingerprint"
114
114
  method_option :title, type: :string, desc: "title"
115
115
  method_option :description, type: :string, desc: "description"
116
116
  method_option :tags, type: :array, desc: "tags"
@@ -141,13 +141,23 @@ module Mihari
141
141
  end
142
142
  end
143
143
 
144
- desc "passive_dns [IP|Domain]", "Cross search with passive DNS services by an ip / domain"
144
+ desc "pulsedive [IP|DOMAIN]", "Pulsedive lookup by an ip or domain"
145
+ method_option :title, type: :string, desc: "title"
146
+ method_option :description, type: :string, desc: "description"
147
+ method_option :tags, type: :array, desc: "tags"
148
+ def pulsedive(indiactor)
149
+ with_error_handling do
150
+ run_analyzer Analyzers::Pulsedive, query: refang(indiactor), options: options
151
+ end
152
+ end
153
+
154
+ desc "passive_dns [IP|DOMAIN]", "Cross search with passive DNS services by an ip or domain"
145
155
  method_option :title, type: :string, desc: "title"
146
156
  method_option :description, type: :string, desc: "description"
147
157
  method_option :tags, type: :array, desc: "tags"
148
158
  def passive_dns(query)
149
159
  with_error_handling do
150
- run_analyzer Analyzers::PassiveDNS, query: query, options: options
160
+ run_analyzer Analyzers::PassiveDNS, query: refang(query), options: options
151
161
  end
152
162
  end
153
163
 
@@ -161,7 +171,7 @@ module Mihari
161
171
  end
162
172
  end
163
173
 
164
- desc "reverse_whois [email]", "Cross search with reverse whois services by an email"
174
+ desc "reverse_whois [EMAIL]", "Cross search with reverse whois services by an email"
165
175
  method_option :title, type: :string, desc: "title"
166
176
  method_option :description, type: :string, desc: "description"
167
177
  method_option :tags, type: :array, desc: "tags"
@@ -178,6 +188,7 @@ module Mihari
178
188
  method_option :md5, type: :string, desc: "MD5 hash"
179
189
  method_option :sha256, type: :string, desc: "SHA256 hash"
180
190
  method_option :mmh3, type: :numeric, desc: "MurmurHash3 hash"
191
+ method_option :html, type: :string, desc: "path to an HTML file"
181
192
  def http_hash
182
193
  with_error_handling do
183
194
  run_analyzer Analyzers::HTTPHash, query: nil, options: options
@@ -194,7 +205,7 @@ module Mihari
194
205
  end
195
206
  end
196
207
 
197
- desc "ssh_fingerprint [FINGERPRINT]", "Cross search with search engines by an SSH fingerprint"
208
+ desc "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)"
198
209
  method_option :title, type: :string, desc: "title"
199
210
  method_option :description, type: :string, desc: "description"
200
211
  method_option :tags, type: :array, desc: "tags"
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "digest/sha2"
4
+ require "murmurhash3"
5
+
6
+ module Mihari
7
+ class HTML
8
+ attr_reader :path
9
+
10
+ def initialize(path)
11
+ @path = path
12
+ end
13
+
14
+ def exists?
15
+ return false unless path
16
+
17
+ File.exist? path
18
+ end
19
+
20
+ def sha256
21
+ Digest::SHA256.hexdigest data
22
+ end
23
+
24
+ def md5
25
+ Digest::MD5.hexdigest data
26
+ end
27
+
28
+ def mmh3
29
+ hash = MurmurHash3::V32.str_hash(data)
30
+ if (hash & 0x80000000).zero?
31
+ hash
32
+ else
33
+ -((hash ^ 0xFFFFFFFF) + 1)
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ def data
40
+ File.read path
41
+ end
42
+ end
43
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Mihari
4
- VERSION = "0.15.0"
4
+ VERSION = "0.16.0"
5
5
  end
@@ -43,12 +43,14 @@ Gem::Specification.new do |spec|
43
43
  spec.add_dependency "lightly", "~> 0.3"
44
44
  spec.add_dependency "mem", "~> 0.1"
45
45
  spec.add_dependency "misp", "~> 0.1"
46
+ spec.add_dependency "murmurhash3", "~> 0.1"
46
47
  spec.add_dependency "net-ping", "~> 2.0"
47
48
  spec.add_dependency "onyphe", "~> 1.0"
48
49
  spec.add_dependency "parallel", "~> 1.19"
49
50
  spec.add_dependency "passive_circl", "~> 0.1"
50
51
  spec.add_dependency "passivetotalx", "~> 0.1"
51
52
  spec.add_dependency "public_suffix", "~> 4.0"
53
+ spec.add_dependency "pulsedive", "~> 0.1"
52
54
  spec.add_dependency "securitytrails", "~> 1.0"
53
55
  spec.add_dependency "shodanx", "~> 0.2"
54
56
  spec.add_dependency "slack-notifier", "~> 2.3"
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.15.0
4
+ version: 0.16.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-11-15 00:00:00.000000000 Z
11
+ date: 2019-11-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -262,6 +262,20 @@ dependencies:
262
262
  - - "~>"
263
263
  - !ruby/object:Gem::Version
264
264
  version: '0.1'
265
+ - !ruby/object:Gem::Dependency
266
+ name: murmurhash3
267
+ requirement: !ruby/object:Gem::Requirement
268
+ requirements:
269
+ - - "~>"
270
+ - !ruby/object:Gem::Version
271
+ version: '0.1'
272
+ type: :runtime
273
+ prerelease: false
274
+ version_requirements: !ruby/object:Gem::Requirement
275
+ requirements:
276
+ - - "~>"
277
+ - !ruby/object:Gem::Version
278
+ version: '0.1'
265
279
  - !ruby/object:Gem::Dependency
266
280
  name: net-ping
267
281
  requirement: !ruby/object:Gem::Requirement
@@ -346,6 +360,20 @@ dependencies:
346
360
  - - "~>"
347
361
  - !ruby/object:Gem::Version
348
362
  version: '4.0'
363
+ - !ruby/object:Gem::Dependency
364
+ name: pulsedive
365
+ requirement: !ruby/object:Gem::Requirement
366
+ requirements:
367
+ - - "~>"
368
+ - !ruby/object:Gem::Version
369
+ version: '0.1'
370
+ type: :runtime
371
+ prerelease: false
372
+ version_requirements: !ruby/object:Gem::Requirement
373
+ requirements:
374
+ - - "~>"
375
+ - !ruby/object:Gem::Version
376
+ version: '0.1'
349
377
  - !ruby/object:Gem::Dependency
350
378
  name: securitytrails
351
379
  requirement: !ruby/object:Gem::Requirement
@@ -479,6 +507,7 @@ files:
479
507
  - lib/mihari/analyzers/passive_dns.rb
480
508
  - lib/mihari/analyzers/passive_ssl.rb
481
509
  - lib/mihari/analyzers/passivetotal.rb
510
+ - lib/mihari/analyzers/pulsedive.rb
482
511
  - lib/mihari/analyzers/reverse_whois.rb
483
512
  - lib/mihari/analyzers/securitytrails.rb
484
513
  - lib/mihari/analyzers/securitytrails_domain_feed.rb
@@ -497,6 +526,7 @@ files:
497
526
  - lib/mihari/emitters/stdout.rb
498
527
  - lib/mihari/emitters/the_hive.rb
499
528
  - lib/mihari/errors.rb
529
+ - lib/mihari/html.rb
500
530
  - lib/mihari/notifiers/base.rb
501
531
  - lib/mihari/notifiers/exception_notifier.rb
502
532
  - lib/mihari/notifiers/slack.rb