mihari 5.1.0 → 5.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/lib/mihari/analyzers/binaryedge.rb +9 -7
  3. data/lib/mihari/analyzers/censys.rb +3 -5
  4. data/lib/mihari/analyzers/circl.rb +4 -6
  5. data/lib/mihari/analyzers/crtsh.rb +6 -7
  6. data/lib/mihari/analyzers/dnpedia.rb +3 -7
  7. data/lib/mihari/analyzers/dnstwister.rb +3 -5
  8. data/lib/mihari/analyzers/feed.rb +12 -10
  9. data/lib/mihari/analyzers/greynoise.rb +3 -5
  10. data/lib/mihari/analyzers/onyphe.rb +3 -4
  11. data/lib/mihari/analyzers/otx.rb +1 -3
  12. data/lib/mihari/analyzers/passivetotal.rb +5 -7
  13. data/lib/mihari/analyzers/pulsedive.rb +5 -7
  14. data/lib/mihari/analyzers/shodan.rb +3 -9
  15. data/lib/mihari/analyzers/urlscan.rb +7 -6
  16. data/lib/mihari/analyzers/virustotal.rb +4 -6
  17. data/lib/mihari/analyzers/virustotal_intelligence.rb +4 -5
  18. data/lib/mihari/analyzers/zoomeye.rb +4 -10
  19. data/lib/mihari/clients/base.rb +53 -0
  20. data/lib/mihari/clients/binaryedge.rb +33 -0
  21. data/lib/mihari/clients/censys.rb +42 -0
  22. data/lib/mihari/clients/circl.rb +59 -0
  23. data/lib/mihari/clients/crtsh.rb +31 -0
  24. data/lib/mihari/clients/dnpedia.rb +64 -0
  25. data/lib/mihari/clients/dnstwister.rb +40 -0
  26. data/lib/mihari/clients/greynoise.rb +29 -0
  27. data/lib/mihari/clients/misp.rb +24 -0
  28. data/lib/mihari/clients/onyphe.rb +23 -0
  29. data/lib/mihari/clients/otx.rb +29 -0
  30. data/lib/mihari/clients/passivetotal.rb +65 -0
  31. data/lib/mihari/clients/publsedive.rb +39 -0
  32. data/lib/mihari/clients/shodan.rb +30 -0
  33. data/lib/mihari/clients/the_hive.rb +28 -0
  34. data/lib/mihari/clients/urlscan.rb +31 -0
  35. data/lib/mihari/clients/virustotal.rb +56 -0
  36. data/lib/mihari/clients/zoomeye.rb +68 -0
  37. data/lib/mihari/emitters/misp.rb +13 -20
  38. data/lib/mihari/emitters/the_hive.rb +3 -5
  39. data/lib/mihari/emitters/webhook.rb +2 -2
  40. data/lib/mihari/feed/reader.rb +14 -11
  41. data/lib/mihari/http.rb +29 -21
  42. data/lib/mihari/mixins/retriable.rb +3 -1
  43. data/lib/mihari/schemas/analyzer.rb +5 -4
  44. data/lib/mihari/version.rb +1 -1
  45. data/lib/mihari.rb +21 -0
  46. data/mihari.gemspec +13 -20
  47. metadata +51 -244
  48. data/lib/mihari/analyzers/clients/otx.rb +0 -36
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "misp"
4
-
5
3
  module Mihari
6
4
  module Emitters
7
5
  class MISP < Base
@@ -16,11 +14,6 @@ module Mihari
16
14
 
17
15
  @url = kwargs[:url] || Mihari.config.misp_url
18
16
  @api_key = kwargs[:api_key] || Mihari.config.misp_api_key
19
-
20
- ::MISP.configure do |config|
21
- config.api_endpoint = url
22
- config.api_key = api_key
23
- end
24
17
  end
25
18
 
26
19
  # @return [Boolean]
@@ -50,17 +43,13 @@ module Mihari
50
43
  def emit(rule:, artifacts:, **_options)
51
44
  return if artifacts.empty?
52
45
 
53
- event = ::MISP::Event.new(info: rule.title)
54
-
55
- artifacts.each do |artifact|
56
- event.attributes << build_attribute(artifact)
57
- end
58
-
59
- rule.tags.each do |tag|
60
- event.add_tag name: tag
61
- end
62
-
63
- event.create
46
+ client.create_event({
47
+ Event: {
48
+ info: rule.title
49
+ },
50
+ Attribute: artifacts.map { |artifact| build_attribute(artifact) },
51
+ Tag: rule.tags.map { |tag| { name: tag } }
52
+ })
64
53
  end
65
54
 
66
55
  private
@@ -69,15 +58,19 @@ module Mihari
69
58
  %w[misp_url misp_api_key]
70
59
  end
71
60
 
61
+ def client
62
+ @client ||= Clients::MISP.new(url, api_key: api_key)
63
+ end
64
+
72
65
  #
73
66
  # Build a MISP attribute
74
67
  #
75
68
  # @param [Mihari::Artifact] artifact
76
69
  #
77
- # @return [::MISP::Attribute]
70
+ # @return [Hash]
78
71
  #
79
72
  def build_attribute(artifact)
80
- ::MISP::Attribute.new(value: artifact.data, type: to_misp_type(type: artifact.data_type, value: artifact.data))
73
+ { value: artifact.data, type: to_misp_type(type: artifact.data_type, value: artifact.data) }
81
74
  end
82
75
 
83
76
  #
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "hachi"
4
-
5
3
  module Mihari
6
4
  module Emitters
7
5
  class TheHive < Base
@@ -50,7 +48,7 @@ module Mihari
50
48
  return if artifacts.empty?
51
49
 
52
50
  payload = payload(rule: rule, artifacts: artifacts)
53
- api.alert.create(**payload)
51
+ client.alert(payload)
54
52
  end
55
53
 
56
54
  #
@@ -79,8 +77,8 @@ module Mihari
79
77
  %w[thehive_url thehive_api_key]
80
78
  end
81
79
 
82
- def api
83
- @api ||= Hachi::API.new(api_endpoint: url, api_key: api_key, api_version: normalized_api_version)
80
+ def client
81
+ @client ||= Clients::TheHive.new(url, api_key: api_key, api_version: normalized_api_version)
84
82
  end
85
83
 
86
84
  #
@@ -77,13 +77,13 @@ module Mihari
77
77
  payload_ = payload_as_string(artifacts: artifacts, rule: rule)
78
78
  payload = JSON.parse(payload_)
79
79
 
80
- client = Mihari::HTTP.new(url, headers: headers, payload: payload)
80
+ client = Mihari::HTTP.new(url, headers: headers)
81
81
 
82
82
  case method
83
83
  when "GET"
84
84
  res = client.get
85
85
  when "POST"
86
- res = client.post
86
+ res = client.post(json: payload)
87
87
  end
88
88
 
89
89
  res
@@ -6,25 +6,28 @@ require "insensitive_hash"
6
6
  module Mihari
7
7
  module Feed
8
8
  class Reader
9
- attr_reader :uri, :http_request_headers, :http_request_method, :http_request_payload
9
+ attr_reader :url, :headers, :params, :json, :data, :method
10
10
 
11
- def initialize(uri, http_request_headers: {}, http_request_method: "GET", http_request_payload_type: nil, http_request_payload: {})
12
- @uri = Addressable::URI.parse(uri)
13
- @http_request_headers = http_request_headers.insensitive
14
- @http_request_method = http_request_method
15
- @http_request_payload = http_request_payload
11
+ def initialize(url, headers: {}, method: "GET", params: nil, json: nil, data: nil)
12
+ @url = Addressable::URI.parse(url)
13
+ @headers = headers.insensitive
14
+ @method = method
16
15
 
17
- http_request_headers["content-type"] = http_request_payload_type if http_request_payload_type
16
+ @params = params
17
+ @json = json
18
+ @data = data
19
+
20
+ headers["content-type"] = "application/json" unless json.nil?
18
21
  end
19
22
 
20
23
  def read
21
- return read_file(uri.path) if uri.scheme == "file"
24
+ return read_file(url.path) if url.scheme == "file"
22
25
 
23
26
  res = nil
24
- client = HTTP.new(uri, headers: http_request_headers, payload: http_request_payload)
27
+ client = HTTP.new(url, headers: headers)
25
28
 
26
- res = client.get if http_request_method == "GET"
27
- res = client.post if http_request_method == "POST"
29
+ res = client.get(params: params) if method == "GET"
30
+ res = client.post(params: params, json: json, data: data) if method == "POST"
28
31
 
29
32
  return [] if res.nil?
30
33
 
data/lib/mihari/http.rb CHANGED
@@ -4,54 +4,62 @@ require "insensitive_hash"
4
4
 
5
5
  module Mihari
6
6
  class HTTP
7
- attr_reader :url, :headers, :payload
7
+ # @return [String]
8
+ attr_reader :url
8
9
 
9
- def initialize(url, headers: {}, payload: {})
10
+ # @return [Hash]
11
+ attr_reader :headers
12
+
13
+ def initialize(url, headers: {})
10
14
  @url = url.is_a?(URI) ? url : URI(url.to_s)
11
15
  @headers = headers.insensitive
12
- @payload = payload
13
16
  end
14
17
 
15
18
  #
16
19
  # Make a GET request
17
20
  #
21
+ # @param [Hash, nil] params
22
+ #
18
23
  # @return [Net::HTTPResponse]
19
24
  #
20
- def get
25
+ def get(params: nil)
21
26
  new_url = url.deep_dup
22
- new_url.query = Addressable::URI.form_encode(payload) unless payload.empty?
27
+ new_url.query = Addressable::URI.form_encode(params) unless (params || {}).empty?
23
28
 
24
29
  get = Net::HTTP::Get.new(new_url)
25
30
  request get
26
31
  end
27
32
 
28
33
  #
29
- # Make a POST request
34
+ # Make a POST requesti
35
+ #
36
+ # @param [Hash, nil] params
37
+ # @param [Hash, nil] json
38
+ # @param [Hash, nil] data
30
39
  #
31
40
  # @return [Net::HTTPResponse]
32
41
  #
33
- def post
34
- post = Net::HTTP::Post.new(url)
35
-
36
- case content_type
37
- when "application/json"
38
- post.body = JSON.generate(payload)
39
- when "application/x-www-form-urlencoded"
40
- post.set_form_data(payload)
41
- end
42
+ def post(params: nil, json: nil, data: nil)
43
+ new_url = url.deep_dup
44
+ new_url.query = Addressable::URI.form_encode(params) unless (params || {}).empty?
45
+
46
+ post = Net::HTTP::Post.new(new_url)
47
+
48
+ post.body = JSON.generate(json) if json
49
+ post.set_form_data(data) if data
42
50
 
43
51
  request post
44
52
  end
45
53
 
46
54
  class << self
47
- def get(url, headers: {}, params: {})
48
- client = new(url, headers: headers, payload: params)
49
- client.get
55
+ def get(url, headers: {}, params: nil)
56
+ client = new(url, headers: headers)
57
+ client.get(params: params)
50
58
  end
51
59
 
52
- def post(url, headers: {}, payload: {})
53
- client = new(url, headers: headers, payload: payload)
54
- client.post
60
+ def post(url, headers: {}, params: nil, json: nil, data: nil)
61
+ client = new(url, headers: headers)
62
+ client.post(params: params, json: json, data: data)
55
63
  end
56
64
  end
57
65
 
@@ -9,7 +9,9 @@ module Mihari
9
9
  Errno::EPIPE,
10
10
  OpenSSL::SSL::SSLError,
11
11
  Timeout::Error,
12
- RetryableError
12
+ RetryableError,
13
+ NetworkError,
14
+ TimeoutError
13
15
  ]
14
16
 
15
17
  #
@@ -82,10 +82,11 @@ module Mihari
82
82
  required(:analyzer).value(Types::String.enum("feed"))
83
83
  required(:query).value(:string)
84
84
  required(:selector).value(:string)
85
- optional(:http_request_method).value(Types::HTTPRequestMethods).default("GET")
86
- optional(:http_request_headers).value(:hash).default({})
87
- optional(:http_request_payload).value(:hash).default({})
88
- optional(:http_request_payload_type).value(Types::HTTPRequestPayloadTypes)
85
+ optional(:method).value(Types::HTTPRequestMethods).default("GET")
86
+ optional(:headers).value(:hash).default({})
87
+ optional(:params).value(:hash)
88
+ optional(:data).value(:hash)
89
+ optional(:json).value(:hash)
89
90
  optional(:options).hash(AnalyzerOptions)
90
91
  end
91
92
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Mihari
4
- VERSION = "5.1.0"
4
+ VERSION = "5.1.1"
5
5
  end
data/lib/mihari.rb CHANGED
@@ -212,6 +212,27 @@ require "mihari/emitters/slack"
212
212
  require "mihari/emitters/the_hive"
213
213
  require "mihari/emitters/webhook"
214
214
 
215
+ # Clients
216
+ require "mihari/clients/base"
217
+
218
+ require "mihari/clients/binaryedge"
219
+ require "mihari/clients/censys"
220
+ require "mihari/clients/circl"
221
+ require "mihari/clients/crtsh"
222
+ require "mihari/clients/dnpedia"
223
+ require "mihari/clients/dnstwister"
224
+ require "mihari/clients/greynoise"
225
+ require "mihari/clients/misp"
226
+ require "mihari/clients/onyphe"
227
+ require "mihari/clients/otx"
228
+ require "mihari/clients/passivetotal"
229
+ require "mihari/clients/publsedive"
230
+ require "mihari/clients/shodan"
231
+ require "mihari/clients/the_hive"
232
+ require "mihari/clients/urlscan"
233
+ require "mihari/clients/virustotal"
234
+ require "mihari/clients/zoomeye"
235
+
215
236
  # Analyzers
216
237
  require "mihari/analyzers/base"
217
238
 
data/mihari.gemspec CHANGED
@@ -4,6 +4,11 @@ lib = File.expand_path("lib", __dir__)
4
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
5
  require "mihari/version"
6
6
 
7
+ def ci_env?
8
+ # CI=true in GitHub Actions
9
+ ENV["CI"]
10
+ end
11
+
7
12
  Gem::Specification.new do |spec|
8
13
  spec.name = "mihari"
9
14
  spec.version = Mihari::VERSION
@@ -32,7 +37,6 @@ Gem::Specification.new do |spec|
32
37
  spec.add_development_dependency "fakefs", "~> 2.4"
33
38
  spec.add_development_dependency "fuubar", "~> 2.5"
34
39
  spec.add_development_dependency "mysql2", "~> 0.5"
35
- spec.add_development_dependency "overcommit", "~> 0.60"
36
40
  spec.add_development_dependency "pg", "~> 1.4"
37
41
  spec.add_development_dependency "rack-test", "~> 2.0"
38
42
  spec.add_development_dependency "rake", "~> 13.0"
@@ -41,19 +45,19 @@ Gem::Specification.new do |spec|
41
45
  spec.add_development_dependency "rspec", "~> 3.12"
42
46
  spec.add_development_dependency "simplecov-lcov", "~> 0.8.0"
43
47
  spec.add_development_dependency "standard", "~> 1.24"
44
- spec.add_development_dependency "steep", "~> 1.3"
45
48
  spec.add_development_dependency "timecop", "~> 0.9"
46
49
  spec.add_development_dependency "vcr", "~> 6.1"
47
50
  spec.add_development_dependency "webmock", "~> 3.18"
48
51
 
52
+ unless ci_env?
53
+ spec.add_development_dependency "overcommit", "~> 0.60"
54
+ spec.add_development_dependency "ruby-lsp", "~> 0.4"
55
+ spec.add_development_dependency "steep", "~> 1.3"
56
+ end
57
+
49
58
  spec.add_dependency "activerecord", "7.0.4.2"
50
59
  spec.add_dependency "addressable", "2.8.1"
51
60
  spec.add_dependency "awrence", "2.0.1"
52
- spec.add_dependency "binaryedge", "0.1.0"
53
- spec.add_dependency "censysx", "0.1.1"
54
- spec.add_dependency "crtsh-rb", "0.3.1"
55
- spec.add_dependency "dnpedia", "0.1.0"
56
- spec.add_dependency "dnstwister", "0.1.0"
57
61
  spec.add_dependency "dotenv", "2.8.1"
58
62
  spec.add_dependency "dry-configurable", "1.0.1"
59
63
  spec.add_dependency "dry-container", "0.11.0"
@@ -67,37 +71,26 @@ Gem::Specification.new do |spec|
67
71
  spec.add_dependency "grape-entity", "1.0.0"
68
72
  spec.add_dependency "grape-swagger", "1.5.0"
69
73
  spec.add_dependency "grape-swagger-entity", "0.5.1"
70
- spec.add_dependency "greynoise", "0.1.1"
71
- spec.add_dependency "hachi", "2.0.0"
72
74
  spec.add_dependency "insensitive_hash", "0.3.3"
73
75
  spec.add_dependency "jr-cli", "0.6.0"
74
76
  spec.add_dependency "launchy", "2.5.2"
75
77
  spec.add_dependency "memist", "2.0.2"
76
- spec.add_dependency "misp", "0.1.4"
77
78
  spec.add_dependency "net-ping", "2.0.8"
78
79
  spec.add_dependency "normalize_country", "0.3.2"
79
- spec.add_dependency "onyphe", "2.0.0"
80
80
  spec.add_dependency "parallel", "1.22.1"
81
- spec.add_dependency "passive_circl", "0.1.0"
82
- spec.add_dependency "passivetotalx", "0.1.1"
83
81
  spec.add_dependency "plissken", "2.0.1"
84
82
  spec.add_dependency "public_suffix", "5.0.1"
85
- spec.add_dependency "pulsedive", "0.1.5"
86
83
  spec.add_dependency "puma", "6.0.2"
87
84
  spec.add_dependency "rack", "2.2.4"
88
85
  spec.add_dependency "rack-contrib", "2.3.0"
89
86
  spec.add_dependency "rack-cors", "1.1.1"
90
87
  spec.add_dependency "securitytrails", "1.0.0"
91
88
  spec.add_dependency "semantic_logger", "4.12.0"
92
- spec.add_dependency "sentry-ruby", "5.7.0"
93
- spec.add_dependency "shodanx", "0.2.1"
89
+ spec.add_dependency "sentry-ruby", "5.8.0"
94
90
  spec.add_dependency "slack-notifier", "2.4.0"
95
- spec.add_dependency "sqlite3", "1.6.0"
91
+ spec.add_dependency "sqlite3", "1.6.1"
96
92
  spec.add_dependency "thor", "1.2.1"
97
- spec.add_dependency "urlscan", "0.8.0"
98
93
  spec.add_dependency "uuidtools", "2.2.0"
99
- spec.add_dependency "virustotalx", "1.2.0"
100
94
  spec.add_dependency "whois", "5.1.0"
101
95
  spec.add_dependency "whois-parser", "2.0.0"
102
- spec.add_dependency "zoomeye-rb", "0.2.0"
103
96
  end