mihari 0.8.2 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +89 -3
- data/docker/Dockerfile +11 -0
- data/lib/mihari.rb +1 -0
- data/lib/mihari/analyzers/base.rb +11 -1
- data/lib/mihari/emitters/misp.rb +84 -0
- data/lib/mihari/version.rb +1 -1
- data/mihari.gemspec +2 -0
- data/screenshots/misp.png +0 -0
- metadata +33 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a1801d9d520fb6de9a4a27d17145b775b074f87e7e1ff88fcb7c50d5630d19e4
|
4
|
+
data.tar.gz: 886708647767e1d5d5a7aaaf7bfd9aca8d25bc714f7f2faf72e0c2c2c4b3073f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 727703b118506f0b310ed1422a757f669748057bd6b4bdb091c638d716209c5ff220088c1396c91924ca275c6fb959e2014f80cb5b9ecbdf72eee23025cf2a7d
|
7
|
+
data.tar.gz: 150c88bac7b129001b109b1966dc527eda5a7e734438507028e5e2a79f74d1884d6cf98d63a4142a8c45f37f501093a7214187aac88265d9a15a9e6f3d24d03e
|
data/README.md
CHANGED
@@ -9,14 +9,18 @@ mihari(`見張り`) is a sidekick tool for [TheHive](https://github.com/TheHive-
|
|
9
9
|
|
10
10
|
## How it works
|
11
11
|
|
12
|
-
- mihari
|
12
|
+
- mihari makes a query against Shodan, Censys, VirusTotal, SecurityTrails, etc. and extracts artifacts from the query results.
|
13
|
+
- mihari checks whether a TheHive instance contains the artifacts or not.
|
13
14
|
- If it doesn't contain the artifacts:
|
14
15
|
- mihari creates an alert with the artifacts on the TheHive instance.
|
15
16
|
- mihari sends a notification to Slack. (Optional)
|
17
|
+
- mihari creates an event on MISP. (Optional)
|
16
18
|
|
17
19
|
![img](./screenshots/eyecatch.png)
|
18
20
|
|
19
|
-
Check this blog post for more detail: [Continuous C2 hunting with Censys, Shodan, Onyphe and TheHive](https://hackmd.io/s/SkUaSrqoE)
|
21
|
+
Check this blog post for more detail: [Continuous C2 hunting with Censys, Shodan, Onyphe and TheHive](https://hackmd.io/s/SkUaSrqoE).
|
22
|
+
|
23
|
+
You can use mihari without TheHive. But note that mihari depends on TheHive to manage artifacts. It means mihari might make duplications when without TheHive.
|
20
24
|
|
21
25
|
### Screenshots
|
22
26
|
|
@@ -28,12 +32,22 @@ Check this blog post for more detail: [Continuous C2 hunting with Censys, Shodan
|
|
28
32
|
|
29
33
|
![img](./screenshots/slack.png)
|
30
34
|
|
35
|
+
- MISP event example
|
36
|
+
|
37
|
+
![img](./screenshots/misp.png)
|
38
|
+
|
31
39
|
## Installation
|
32
40
|
|
33
41
|
```bash
|
34
42
|
gem install mihari
|
35
43
|
```
|
36
44
|
|
45
|
+
Or you can use this tool with Docker.
|
46
|
+
|
47
|
+
```bash
|
48
|
+
docker pull ninoseki/mihari
|
49
|
+
```
|
50
|
+
|
37
51
|
## Basic usage
|
38
52
|
|
39
53
|
mihari supports Censys, Shodan, Onyphe, urlscan, SecurityTrails, crt.sh and VirusTotal by default.
|
@@ -56,6 +70,52 @@ Commands:
|
|
56
70
|
|
57
71
|
```
|
58
72
|
|
73
|
+
### Example usages
|
74
|
+
|
75
|
+
```bash
|
76
|
+
# Censys lookup for PANDA C2
|
77
|
+
$ mihari censys '("PANDA" AND "SMAdmin" AND "layui")' --title "PANDA C2"
|
78
|
+
{
|
79
|
+
"title": "PANDA C2",
|
80
|
+
"description": "query = (\"PANDA\" AND \"SMAdmin\" AND \"layui\")",
|
81
|
+
"artifacts": [
|
82
|
+
"154.223.165.223",
|
83
|
+
"154.194.2.31",
|
84
|
+
"45.114.127.119",
|
85
|
+
"..."
|
86
|
+
],
|
87
|
+
"tags": []
|
88
|
+
}
|
89
|
+
|
90
|
+
# VirusTotal passive DNS lookup for a FAKESPY host
|
91
|
+
$ mihari virustotal "jppost-hi.top" --title "FAKESPY host passive DNS results"
|
92
|
+
{
|
93
|
+
"title": "FAKESPY host passive DNS results",
|
94
|
+
"description": "indicator = jppost-hi.top",
|
95
|
+
"artifacts": [
|
96
|
+
"185.22.152.28",
|
97
|
+
"192.236.200.44",
|
98
|
+
"193.148.69.12",
|
99
|
+
"..."
|
100
|
+
],
|
101
|
+
"tags": []
|
102
|
+
}
|
103
|
+
|
104
|
+
# SecurityTrails domain feed lookup for finding (possibly) Apple phishing websites
|
105
|
+
mihari securitytrails_domain_feed "apple-" --type new
|
106
|
+
{
|
107
|
+
"title": "SecurityTrails domain feed lookup",
|
108
|
+
"description": "Regexp = /apple-/",
|
109
|
+
"artifacts": [
|
110
|
+
"apple-sign.online",
|
111
|
+
"apple-log-in.com",
|
112
|
+
"apple-locator-id.info",
|
113
|
+
"..."
|
114
|
+
],
|
115
|
+
"tags": []
|
116
|
+
}
|
117
|
+
```
|
118
|
+
|
59
119
|
### Import from JSON
|
60
120
|
|
61
121
|
```bash
|
@@ -88,6 +148,8 @@ All configuration is done via ENV variables.
|
|
88
148
|
|------------------------|------------------------|--------------------------------|
|
89
149
|
| THEHIVE_API_ENDPOINT | TheHive URL | Required |
|
90
150
|
| THEHIVE_API_KEY | TheHive API key | Required |
|
151
|
+
| MISP_API_ENDPOINT | MISP URL | Optional |
|
152
|
+
| MISP_API_KEY | MISP API key | Optional |
|
91
153
|
| SLACK_WEBHOOK_URL | Slack Webhook URL | Optional |
|
92
154
|
| SLACK_CHANNEL | Slack channel name | Optional (default: `#general`) |
|
93
155
|
| CENSYS_ID | Censys API ID | Optional |
|
@@ -97,7 +159,7 @@ All configuration is done via ENV variables.
|
|
97
159
|
| SHODAN_API_KEY | Shodan API key | Optional |
|
98
160
|
| VIRUSTOTAL_API_KEY | VirusTotal API key | Optional |
|
99
161
|
|
100
|
-
## How to create a custom
|
162
|
+
## How to create a custom script
|
101
163
|
|
102
164
|
Create a class which extends `Mihari::Analyzers::Base` and implements the following methods.
|
103
165
|
|
@@ -143,6 +205,30 @@ See `/examples` for more.
|
|
143
205
|
|
144
206
|
mihari caches execution results in `/tmp/mihari` and the default cache duration is 7 days. If you want to clear the cache, please clear `/tmp/mihari`.
|
145
207
|
|
208
|
+
## Using it with Docker
|
209
|
+
|
210
|
+
```bash
|
211
|
+
$ docker run --rm ninoseki/mihari
|
212
|
+
Commands:
|
213
|
+
mihari alerts # Show the alerts on TheHive
|
214
|
+
mihari censys [QUERY] # Censys IPv4 lookup by a given...
|
215
|
+
mihari crtsh [QUERY] # crt.sh lookup by a given query
|
216
|
+
mihari help [COMMAND] # Describe available commands o...
|
217
|
+
mihari import_from_json # Give a JSON input via STDIN
|
218
|
+
mihari onyphe [QUERY] # Onyphe datascan lookup by a g...
|
219
|
+
mihari securitytrails [IP|DOMAIN] # SecurityTrails resolutions lo...
|
220
|
+
mihari securitytrails_domain_feed [REGEXP] # SecurityTrails new domain fee...
|
221
|
+
mihari shodan [QUERY] # Shodan host lookup by a given...
|
222
|
+
mihari status # Show the current configuratio...
|
223
|
+
mihari urlscan [QUERY] # urlscan lookup by a given query
|
224
|
+
mihari virustotal [IP|DOMAIN] # VirusTotal resolutions lookup...
|
225
|
+
|
226
|
+
# Note that you should pass configurations via environment variables
|
227
|
+
$ docker run --rm ninoseki/mihari -e THEHIVE_API_ENDPOINT="http://THEHIVE_URL" -e THEHIVE_API_KEY="API KEY" mihari
|
228
|
+
# or
|
229
|
+
$ docker run --rm ninoseki/mihari --env-file ~/.mihari.env mihari
|
230
|
+
```
|
231
|
+
|
146
232
|
## License
|
147
233
|
|
148
234
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/docker/Dockerfile
ADDED
data/lib/mihari.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "parallel"
|
4
|
+
|
3
5
|
module Mihari
|
4
6
|
module Analyzers
|
5
7
|
class Base
|
@@ -29,7 +31,9 @@ module Mihari
|
|
29
31
|
end
|
30
32
|
|
31
33
|
def run
|
32
|
-
|
34
|
+
set_unique_artifacts
|
35
|
+
|
36
|
+
Parallel.each(Mihari.emitters) do |emitter_class|
|
33
37
|
emitter = emitter_class.new
|
34
38
|
next unless emitter.valid?
|
35
39
|
|
@@ -64,6 +68,12 @@ module Mihari
|
|
64
68
|
|
65
69
|
@unique_artifacts ||= @the_hive.artifact.find_non_existing_artifacts(uncached_artifacts)
|
66
70
|
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def set_unique_artifacts
|
75
|
+
unique_artifacts
|
76
|
+
end
|
67
77
|
end
|
68
78
|
end
|
69
79
|
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "misp"
|
4
|
+
require "net/ping"
|
5
|
+
|
6
|
+
module Mihari
|
7
|
+
module Emitters
|
8
|
+
class MISP < Base
|
9
|
+
# @return [true, false]
|
10
|
+
def valid?
|
11
|
+
api_endpoint? && api_key? && ping?
|
12
|
+
end
|
13
|
+
|
14
|
+
def emit(title:, description:, artifacts:, tags: [])
|
15
|
+
event = ::MISP::Event.new(info: title)
|
16
|
+
|
17
|
+
artifacts.each do |artifact|
|
18
|
+
event.attributes << build_attribute(artifact)
|
19
|
+
end
|
20
|
+
|
21
|
+
tags.each do |tag|
|
22
|
+
event.add_tag name: tag
|
23
|
+
end
|
24
|
+
|
25
|
+
event.create
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def build_attribute(artifact)
|
31
|
+
::MISP::Attribute.new(value: artifact.data, type: to_misp_type(type: artifact.data_type, value: artifact.data))
|
32
|
+
end
|
33
|
+
|
34
|
+
def hash_type(value)
|
35
|
+
case value.length
|
36
|
+
when 32
|
37
|
+
"md5"
|
38
|
+
when 40
|
39
|
+
"sha1"
|
40
|
+
when 64
|
41
|
+
"sha256"
|
42
|
+
when 128
|
43
|
+
"sha512"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def to_misp_type(type:, value:)
|
48
|
+
type = type.to_sym
|
49
|
+
table = {
|
50
|
+
ip: "ip-dst",
|
51
|
+
mail: "email-dst",
|
52
|
+
url: "url",
|
53
|
+
domain: "domain",
|
54
|
+
}
|
55
|
+
return table[type] if table.key?(type)
|
56
|
+
|
57
|
+
hash_type value
|
58
|
+
end
|
59
|
+
|
60
|
+
def create_attribute(artifact)
|
61
|
+
artifact.data_type
|
62
|
+
end
|
63
|
+
|
64
|
+
def api_endpoint?
|
65
|
+
api_endpoint = ::MISP.configuration.api_endpoint
|
66
|
+
!api_endpoint.nil? && !api_endpoint.empty?
|
67
|
+
end
|
68
|
+
|
69
|
+
def api_key?
|
70
|
+
api_key = ::MISP.configuration.api_key
|
71
|
+
!api_key.nil? && !api_key.empty?
|
72
|
+
end
|
73
|
+
|
74
|
+
def ping?
|
75
|
+
base_url = ::MISP.configuration.api_endpoint
|
76
|
+
base_url = base_url.end_with?("/") ? base_url[0..-2] : base_url
|
77
|
+
url = "#{base_url}/users/login"
|
78
|
+
|
79
|
+
http = Net::Ping::HTTP.new(url)
|
80
|
+
http.ping?
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
data/lib/mihari/version.rb
CHANGED
data/mihari.gemspec
CHANGED
@@ -40,8 +40,10 @@ Gem::Specification.new do |spec|
|
|
40
40
|
spec.add_dependency "hachi", "~> 0.2"
|
41
41
|
spec.add_dependency "lightly", "~> 0.3"
|
42
42
|
spec.add_dependency "mem", "~> 0.1"
|
43
|
+
spec.add_dependency "misp", "~> 0.1"
|
43
44
|
spec.add_dependency "net-ping", "~> 2.0"
|
44
45
|
spec.add_dependency "onyphe", "~> 0.2"
|
46
|
+
spec.add_dependency "parallel", "~> 1.17"
|
45
47
|
spec.add_dependency "public_suffix", "~> 4.0"
|
46
48
|
spec.add_dependency "securitytrails", "~> 0.2"
|
47
49
|
spec.add_dependency "shodanx", "~> 0.2"
|
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.
|
4
|
+
version: 0.9.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-09-
|
11
|
+
date: 2019-09-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -220,6 +220,20 @@ dependencies:
|
|
220
220
|
- - "~>"
|
221
221
|
- !ruby/object:Gem::Version
|
222
222
|
version: '0.1'
|
223
|
+
- !ruby/object:Gem::Dependency
|
224
|
+
name: misp
|
225
|
+
requirement: !ruby/object:Gem::Requirement
|
226
|
+
requirements:
|
227
|
+
- - "~>"
|
228
|
+
- !ruby/object:Gem::Version
|
229
|
+
version: '0.1'
|
230
|
+
type: :runtime
|
231
|
+
prerelease: false
|
232
|
+
version_requirements: !ruby/object:Gem::Requirement
|
233
|
+
requirements:
|
234
|
+
- - "~>"
|
235
|
+
- !ruby/object:Gem::Version
|
236
|
+
version: '0.1'
|
223
237
|
- !ruby/object:Gem::Dependency
|
224
238
|
name: net-ping
|
225
239
|
requirement: !ruby/object:Gem::Requirement
|
@@ -248,6 +262,20 @@ dependencies:
|
|
248
262
|
- - "~>"
|
249
263
|
- !ruby/object:Gem::Version
|
250
264
|
version: '0.2'
|
265
|
+
- !ruby/object:Gem::Dependency
|
266
|
+
name: parallel
|
267
|
+
requirement: !ruby/object:Gem::Requirement
|
268
|
+
requirements:
|
269
|
+
- - "~>"
|
270
|
+
- !ruby/object:Gem::Version
|
271
|
+
version: '1.17'
|
272
|
+
type: :runtime
|
273
|
+
prerelease: false
|
274
|
+
version_requirements: !ruby/object:Gem::Requirement
|
275
|
+
requirements:
|
276
|
+
- - "~>"
|
277
|
+
- !ruby/object:Gem::Version
|
278
|
+
version: '1.17'
|
251
279
|
- !ruby/object:Gem::Dependency
|
252
280
|
name: public_suffix
|
253
281
|
requirement: !ruby/object:Gem::Requirement
|
@@ -363,6 +391,7 @@ files:
|
|
363
391
|
- Rakefile
|
364
392
|
- bin/console
|
365
393
|
- bin/setup
|
394
|
+
- docker/Dockerfile
|
366
395
|
- examples/ipinfo_hosted_domains.rb
|
367
396
|
- examples/vt_passive_dns.rb
|
368
397
|
- exe/mihari
|
@@ -382,6 +411,7 @@ files:
|
|
382
411
|
- lib/mihari/cache.rb
|
383
412
|
- lib/mihari/cli.rb
|
384
413
|
- lib/mihari/emitters/base.rb
|
414
|
+
- lib/mihari/emitters/misp.rb
|
385
415
|
- lib/mihari/emitters/slack.rb
|
386
416
|
- lib/mihari/emitters/stdout.rb
|
387
417
|
- lib/mihari/emitters/the_hive.rb
|
@@ -399,6 +429,7 @@ files:
|
|
399
429
|
- mihari.gemspec
|
400
430
|
- screenshots/alert.png
|
401
431
|
- screenshots/eyecatch.png
|
432
|
+
- screenshots/misp.png
|
402
433
|
- screenshots/slack.png
|
403
434
|
homepage: https://github.com/ninoseki/mihari
|
404
435
|
licenses:
|