mihari 0.15.0 → 0.16.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: 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