mihari 0.17.4 → 1.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +3 -0
- data/.rubocop.yml +155 -0
- data/.travis.yml +7 -1
- data/Gemfile +2 -0
- data/README.md +41 -72
- data/config/pre_commit.yml +3 -0
- data/docker/Dockerfile +1 -1
- data/lib/mihari.rb +12 -8
- data/lib/mihari/alert_viewer.rb +16 -34
- data/lib/mihari/analyzers/base.rb +7 -19
- data/lib/mihari/analyzers/basic.rb +3 -1
- data/lib/mihari/analyzers/binaryedge.rb +3 -3
- data/lib/mihari/analyzers/censys.rb +2 -2
- data/lib/mihari/analyzers/circl.rb +2 -2
- data/lib/mihari/analyzers/onyphe.rb +3 -3
- data/lib/mihari/analyzers/passivetotal.rb +2 -2
- data/lib/mihari/analyzers/pulsedive.rb +2 -2
- data/lib/mihari/analyzers/securitytrails.rb +2 -2
- data/lib/mihari/analyzers/securitytrails_domain_feed.rb +2 -2
- data/lib/mihari/analyzers/shodan.rb +2 -2
- data/lib/mihari/analyzers/virustotal.rb +2 -2
- data/lib/mihari/analyzers/zoomeye.rb +2 -2
- data/lib/mihari/cli.rb +13 -4
- data/lib/mihari/config.rb +68 -2
- data/lib/mihari/configurable.rb +1 -1
- data/lib/mihari/database.rb +68 -0
- data/lib/mihari/emitters/base.rb +1 -1
- data/lib/mihari/emitters/database.rb +29 -0
- data/lib/mihari/emitters/misp.rb +8 -1
- data/lib/mihari/emitters/slack.rb +4 -2
- data/lib/mihari/emitters/stdout.rb +2 -1
- data/lib/mihari/emitters/the_hive.rb +28 -14
- data/lib/mihari/models/alert.rb +11 -0
- data/lib/mihari/models/artifact.rb +27 -0
- data/lib/mihari/models/tag.rb +10 -0
- data/lib/mihari/models/tagging.rb +10 -0
- data/lib/mihari/notifiers/slack.rb +7 -4
- data/lib/mihari/serializers/alert.rb +12 -0
- data/lib/mihari/serializers/artifact.rb +9 -0
- data/lib/mihari/serializers/tag.rb +9 -0
- data/lib/mihari/slack_monkeypatch.rb +16 -0
- data/lib/mihari/status.rb +1 -1
- data/lib/mihari/type_checker.rb +1 -1
- data/lib/mihari/version.rb +1 -1
- data/mihari.gemspec +13 -6
- metadata +140 -36
- data/lib/mihari/artifact.rb +0 -36
- data/lib/mihari/cache.rb +0 -35
- data/lib/mihari/the_hive.rb +0 -42
- data/lib/mihari/the_hive/alert.rb +0 -25
- data/lib/mihari/the_hive/artifact.rb +0 -33
- data/lib/mihari/the_hive/base.rb +0 -14
data/lib/mihari/artifact.rb
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Mihari
|
4
|
-
class Artifact
|
5
|
-
attr_reader :data
|
6
|
-
|
7
|
-
#
|
8
|
-
# @param [String] data
|
9
|
-
# @param [String, nil] message
|
10
|
-
#
|
11
|
-
def initialize(data, message: nil)
|
12
|
-
@data = data
|
13
|
-
@message = message
|
14
|
-
end
|
15
|
-
|
16
|
-
# @return [String, nil]
|
17
|
-
def data_type
|
18
|
-
TypeChecker.type data
|
19
|
-
end
|
20
|
-
|
21
|
-
# @return [String]
|
22
|
-
def message
|
23
|
-
@mesasge || data
|
24
|
-
end
|
25
|
-
|
26
|
-
# @return [true, false]
|
27
|
-
def valid?
|
28
|
-
!data_type.nil?
|
29
|
-
end
|
30
|
-
|
31
|
-
# @return [Hash]
|
32
|
-
def to_h
|
33
|
-
{ data: data, data_type: data_type, message: message }
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
data/lib/mihari/cache.rb
DELETED
@@ -1,35 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "lightly"
|
4
|
-
|
5
|
-
module Mihari
|
6
|
-
class Cache
|
7
|
-
DEFAULT_CACHE_DIR = "/tmp/mihari"
|
8
|
-
|
9
|
-
def initialize
|
10
|
-
@data = Lightly.new(life: "7d", dir: DEFAULT_CACHE_DIR)
|
11
|
-
end
|
12
|
-
|
13
|
-
def cached?(key)
|
14
|
-
return false unless @data.enabled?
|
15
|
-
|
16
|
-
begin
|
17
|
-
@data.cached? key
|
18
|
-
rescue Errno::ENOENT => _e
|
19
|
-
false
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def save(*keys)
|
24
|
-
return unless @data.enabled?
|
25
|
-
|
26
|
-
begin
|
27
|
-
keys.flatten.each do |key|
|
28
|
-
@data.save key, true
|
29
|
-
end
|
30
|
-
rescue Errno::ENOENT => _e
|
31
|
-
nil
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
data/lib/mihari/the_hive.rb
DELETED
@@ -1,42 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "net/ping"
|
4
|
-
require "uri"
|
5
|
-
|
6
|
-
module Mihari
|
7
|
-
class TheHive
|
8
|
-
attr_reader :artifact
|
9
|
-
attr_reader :alert
|
10
|
-
|
11
|
-
def initialize
|
12
|
-
@artifact = Artifact.new
|
13
|
-
@alert = Alert.new
|
14
|
-
end
|
15
|
-
|
16
|
-
# @return [true, false]
|
17
|
-
def valid?
|
18
|
-
api_endpont? && api_key? && ping?
|
19
|
-
end
|
20
|
-
|
21
|
-
private
|
22
|
-
|
23
|
-
# @return [true, false]
|
24
|
-
def api_endpont?
|
25
|
-
ENV.key? "THEHIVE_API_ENDPOINT"
|
26
|
-
end
|
27
|
-
|
28
|
-
# @return [true, false]
|
29
|
-
def api_key?
|
30
|
-
ENV.key? "THEHIVE_API_KEY"
|
31
|
-
end
|
32
|
-
|
33
|
-
def ping?
|
34
|
-
base_url = ENV.fetch("THEHIVE_API_ENDPOINT")
|
35
|
-
base_url = base_url.end_with?("/") ? base_url[0..-2] : base_url
|
36
|
-
url = "#{base_url}/index.html"
|
37
|
-
|
38
|
-
http = Net::Ping::HTTP.new(url)
|
39
|
-
http.ping?
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
@@ -1,25 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Mihari
|
4
|
-
class TheHive
|
5
|
-
class Alert < Base
|
6
|
-
# @return [Array]
|
7
|
-
def list(range: "all", sort: "-date")
|
8
|
-
alerts = api.alert.search({ source: "mihari" }, range: range, sort: sort)
|
9
|
-
alerts.sort_by { |alert| -alert.dig("createdAt") }
|
10
|
-
end
|
11
|
-
|
12
|
-
# @return [Hash]
|
13
|
-
def create(title:, description:, artifacts:, tags: [])
|
14
|
-
api.alert.create(
|
15
|
-
title: title,
|
16
|
-
description: description,
|
17
|
-
artifacts: artifacts,
|
18
|
-
tags: tags,
|
19
|
-
type: "external",
|
20
|
-
source: "mihari"
|
21
|
-
)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
@@ -1,33 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Mihari
|
4
|
-
class TheHive
|
5
|
-
class Artifact < Base
|
6
|
-
# @return [Array]
|
7
|
-
def search(data:, data_type:, range: "all")
|
8
|
-
api.artifact.search({ data: data, data_type: data_type }, range: range)
|
9
|
-
end
|
10
|
-
|
11
|
-
# @return [Array]
|
12
|
-
def search_all(data:, range: "all")
|
13
|
-
api.artifact.search({ data: data }, range: range)
|
14
|
-
end
|
15
|
-
|
16
|
-
# @return [true, false]
|
17
|
-
def exists?(data:, data_type:)
|
18
|
-
res = search(data: data, data_type: data_type, range: "0-1")
|
19
|
-
!res.empty?
|
20
|
-
end
|
21
|
-
|
22
|
-
# @return [Array<Mihari::Artifact>]
|
23
|
-
def find_non_existing_artifacts(artifacts)
|
24
|
-
data = artifacts.map(&:data)
|
25
|
-
results = search_all(data: data)
|
26
|
-
keys = results.map { |result| result.dig("data") }.compact.uniq
|
27
|
-
artifacts.reject do |artifact|
|
28
|
-
keys.include? artifact.data
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|