aikido-zen 0.1.0 → 0.1.1

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: f254d2813587d13946fc4c61856481a71f1489f326fd8bec1ab72c8e641b693e
4
- data.tar.gz: 3a938c013d75088f131736b91b6388396e993ef54d1b1e53990a961aee6e73b6
3
+ metadata.gz: 51eaea8541cd36bd28a72265eb65c03d603ca04200e4445c1ce9ef5f1eda161e
4
+ data.tar.gz: dbb1085f145533d7c432950e0960b35eae89f9b5c389d17971273fd16ae02da6
5
5
  SHA512:
6
- metadata.gz: 42128d2fa8f5cb702bbb03bde4fdb737ece7cb2b66500d8ed5e52ab982febc5e41f19c74584ad3b63330a4a7b25080577c12a2b959615ad6d3a6c6153eb8e68f
7
- data.tar.gz: 633d0a6370b76a478a613f712316e5fbe11be8d6491714b1b511333571e2dea89025b96a9e59444e64633be06eaea226694fe4eeeab4837b6d2f023aa9b130d0
6
+ metadata.gz: 298cd2aee853100f077036d8982c04cbcaafafda4554e279f855586bf379d68227005c7eb1869a7c64941e0fe2c06b7d0fb9cdf0f22232d1c9c4ad6b98b5d383
7
+ data.tar.gz: 4f8fa891bc625d17ed21e0c78ecee44af8fb6784202243982748fa6df86dbdb333f3242cc7890e28bef7cb9ce700b6567600e6ba4a5448af002915852db0c7e8
data/.simplecov ADDED
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Due to dependency resolution, on Ruby 2.x we're stuck with a _very_ old
4
+ # SimpleCov version, and it doesn't really give us any benefit to run coverage
5
+ # in separate ruby versions since we don't branch on ruby version in the code.
6
+ return if RUBY_VERSION < "3.0"
7
+
8
+ SimpleCov.start do
9
+ # Make sure SimpleCov waits until after the tests
10
+ # are finished to generate the coverage reports.
11
+ self.external_at_exit = true
12
+
13
+ enable_coverage :branch
14
+ minimum_coverage line: 95, branch: 85
15
+
16
+ add_filter "/test/"
17
+ end
18
+
19
+ # vim: ft=ruby
data/CHANGELOG.md CHANGED
@@ -2,4 +2,20 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## 0.1.1
6
+
7
+ ### Fixed
8
+
9
+ - Avoid an error when sending the initial heartbeat if the Aikido server hasn't
10
+ received stats yet.
11
+ - Fix the SSRF scanner to ensure the port in the user-supplied payload matches
12
+ the port in the request.
13
+ - Don't break the HTTP.rb sink when a Zen context isn't set.
14
+ - Don't break the Typhoeus sink when a Zen context isn't set.
15
+ - Don't break the PG sink outside of Rails.
16
+ - Updated [libzen](https://github.com/AikidoSec/zen-internals) to v0.1.31 to
17
+ prevent flagging false positives in SQL queries with comments.
18
+
19
+ ## 0.1.0
20
+
5
21
  - Initial version
@@ -65,7 +65,9 @@ module Aikido::Zen
65
65
 
66
66
  poll_for_setting_updates
67
67
 
68
- @worker.delay(@config.initial_heartbeat_delay) { send_heartbeat if stats.any? }
68
+ @worker.delay(@config.initial_heartbeat_delay) do
69
+ send_heartbeat if @collector.stats.any?
70
+ end
69
71
  end
70
72
 
71
73
  # Clean up any ongoing threads, and reset the state. Called automatically
@@ -31,6 +31,8 @@ module Aikido::Zen
31
31
  attach_function :detect_sql_injection_native, :detect_sql_injection,
32
32
  [:string, :string, :int], :int
33
33
  rescue LoadError, FFI::NotFoundError => err
34
+ # :nocov:
35
+
34
36
  # Emit an $stderr warning at startup.
35
37
  warn "Zen could not load its binary extension #{libzen_name}: #{err}"
36
38
 
@@ -38,6 +40,8 @@ module Aikido::Zen
38
40
  attempt = format("%p for SQL injection", query)
39
41
  raise InternalsError.new(attempt, "loading", Internals.libzen_name)
40
42
  end
43
+
44
+ # :nocov:
41
45
  else
42
46
  # Analyzes the SQL query to detect if the provided user input is being
43
47
  # passed as-is without escaping.
@@ -112,7 +112,8 @@ module Aikido::Zen
112
112
  is_port_relevant = input_uri.port != input_uri.default_port
113
113
  return false if is_port_relevant && input_uri.port != conn_uri.port
114
114
 
115
- conn_uri.hostname == input_uri.hostname
115
+ conn_uri.hostname == input_uri.hostname &&
116
+ conn_uri.port == input_uri.port
116
117
  end
117
118
 
118
119
  def private_ip?(hostname)
@@ -128,8 +129,11 @@ module Aikido::Zen
128
129
  # * The input itself, if it already looks like a URI.
129
130
  # * The input prefixed with http://
130
131
  # * The input prefixed with https://
132
+ # * The input prefixed with the scheme of the request's URI, to consider
133
+ # things like an FTP request (to "ftp://localhost") with a plain host
134
+ # as a user-input ("localhost").
131
135
  #
132
- # @return [Set<URI>]
136
+ # @return [Array<URI>] a list of unique URIs based on the above criteria.
133
137
  def uris_from_input
134
138
  input = @input.to_s
135
139
 
@@ -138,10 +142,12 @@ module Aikido::Zen
138
142
  # valid hostname. We should do the same for the input.
139
143
  input = format("[%s]", input) if unescaped_ipv6?(input)
140
144
 
141
- [input, "http://#{input}", "https://#{input}"]
142
- .map { |candidate| as_uri(candidate) }
143
- .compact
144
- .uniq
145
+ [
146
+ input,
147
+ "http://#{input}",
148
+ "https://#{input}",
149
+ "#{@request_uri.scheme}://#{input}"
150
+ ].map { |candidate| as_uri(candidate) }.compact.uniq
145
151
  end
146
152
 
147
153
  def as_uri(string)
@@ -66,7 +66,7 @@ module Aikido::Zen
66
66
 
67
67
  response
68
68
  ensure
69
- context["ssrf.request"] = prev_request
69
+ context["ssrf.request"] = prev_request if context
70
70
  end
71
71
  end
72
72
  end
@@ -7,6 +7,17 @@ module Aikido::Zen
7
7
  module PG
8
8
  SINK = Sinks.add("pg", scanners: [Scanners::SQLInjectionScanner])
9
9
 
10
+ # For some reason, the ActiveRecord pg adapter does not wrap exceptions in
11
+ # StatementInvalid, which leads to inconsistent handling. This guarantees
12
+ # that all Zen errors are wrapped in a StatementInvalid, so documentation
13
+ # can be consistent.
14
+ WRAP_EXCEPTIONS = if defined?(ActiveRecord::StatementInvalid)
15
+ <<~RUBY
16
+ rescue Aikido::Zen::SQLInjectionError
17
+ raise ActiveRecord::StatementInvalid
18
+ RUBY
19
+ end
20
+
10
21
  module Extensions
11
22
  %i[
12
23
  send_query exec sync_exec async_exec
@@ -16,12 +27,7 @@ module Aikido::Zen
16
27
  def #{method}(query, *)
17
28
  SINK.scan(query: query, dialect: :postgresql, operation: :#{method})
18
29
  super
19
- rescue Aikido::Zen::SQLInjectionError
20
- # The pg adapter does not wrap exceptions in StatementInvalid, which
21
- # leads to inconsistent handling. This guarantees that all Aikido
22
- # errors are wrapped in a StatementInvalid, so documentation can be
23
- # consistent.
24
- raise ActiveRecord::StatementInvalid
30
+ #{WRAP_EXCEPTIONS}
25
31
  end
26
32
  RUBY
27
33
  end
@@ -33,12 +39,7 @@ module Aikido::Zen
33
39
  def #{method}(_, query, *)
34
40
  SINK.scan(query: query, dialect: :postgresql, operation: :#{method})
35
41
  super
36
- rescue Aikido::Zen::SQLInjectionError
37
- # The pg adapter does not wrap exceptions in StatementInvalid, which
38
- # leads to inconsistent handling. This guarantees that all Aikido
39
- # errors are wrapped in a StatementInvalid, so documentation can be
40
- # consistent.
41
- raise ActiveRecord::StatementInvalid
42
+ #{WRAP_EXCEPTIONS}
42
43
  end
43
44
  RUBY
44
45
  end
@@ -66,7 +66,7 @@ module Aikido::Zen
66
66
  operation: "request"
67
67
  )
68
68
  ensure
69
- context["ssrf.request"] = nil
69
+ context["ssrf.request"] = nil if context
70
70
  end
71
71
 
72
72
  true
@@ -2,9 +2,9 @@
2
2
 
3
3
  module Aikido
4
4
  module Zen
5
- VERSION = "0.1.0"
5
+ VERSION = "0.1.1"
6
6
 
7
7
  # The version of libzen_internals that we build against.
8
- LIBZEN_VERSION = "0.1.30"
8
+ LIBZEN_VERSION = "0.1.31"
9
9
  end
10
10
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aikido-zen
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nicolas Sanguinetti
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-11-15 00:00:00.000000000 Z
11
+ date: 2024-11-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -60,6 +60,7 @@ extensions: []
60
60
  extra_rdoc_files: []
61
61
  files:
62
62
  - ".ruby-version"
63
+ - ".simplecov"
63
64
  - ".standard.yml"
64
65
  - CHANGELOG.md
65
66
  - LICENSE