aikido-zen 1.0.1.beta.3-x86_64-mingw-64 → 1.0.1.beta.5-x86_64-mingw-64
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/aikido/zen/rails_engine.rb +1 -15
- data/lib/aikido/zen/sinks/async_http.rb +40 -42
- data/lib/aikido/zen/sinks/curb.rb +56 -58
- data/lib/aikido/zen/sinks/em_http.rb +27 -29
- data/lib/aikido/zen/sinks/excon.rb +62 -65
- data/lib/aikido/zen/sinks/file.rb +66 -70
- data/lib/aikido/zen/sinks/http.rb +26 -28
- data/lib/aikido/zen/sinks/httpclient.rb +27 -29
- data/lib/aikido/zen/sinks/httpx.rb +27 -29
- data/lib/aikido/zen/sinks/kernel.rb +11 -12
- data/lib/aikido/zen/sinks/mysql2.rb +10 -12
- data/lib/aikido/zen/sinks/net_http.rb +25 -27
- data/lib/aikido/zen/sinks/patron.rb +56 -58
- data/lib/aikido/zen/sinks/pg.rb +23 -25
- data/lib/aikido/zen/sinks/resolv.rb +21 -21
- data/lib/aikido/zen/sinks/socket.rb +10 -12
- data/lib/aikido/zen/sinks/sqlite3.rb +18 -21
- data/lib/aikido/zen/sinks/trilogy.rb +10 -12
- data/lib/aikido/zen/sinks.rb +1 -4
- data/lib/aikido/zen/sinks_dsl.rb +27 -15
- data/lib/aikido/zen/version.rb +1 -1
- data/lib/aikido/zen.rb +26 -15
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c35cec4c784296981a3deb9fe1fd2d34fd6a653fbd6d2d3037c24632bfe0322e
|
4
|
+
data.tar.gz: a6f19f666167e9c39b5c273bea3481b2acf2e2dd817bee5aee9bb9b3da3a0252
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9becfc0eb3e60ac46f8af101d3d6b30bcf3aa8505a8a296378ee1d0dfe278c34b578ec5e5682c59d196b2e72415adfc1d8de218511400aa971d1386bece19817
|
7
|
+
data.tar.gz: 605f53dbf38a95839ccd3effd9a9bc75900bb2b12b0b45553db16182aae66739a4d9bf7114baa34b6ec9c8ff16a05edc318529db9f8ed23aa712e51c0b09879b
|
@@ -10,8 +10,6 @@ module Aikido::Zen
|
|
10
10
|
end
|
11
11
|
|
12
12
|
initializer "aikido.add_middleware" do |app|
|
13
|
-
next unless config.zen.protect?
|
14
|
-
|
15
13
|
app.middleware.use Aikido::Zen::Middleware::SetContext
|
16
14
|
app.middleware.use Aikido::Zen::Middleware::CheckAllowedAddresses
|
17
15
|
# Request Tracker stats do not consider failed request or 40x, so the middleware
|
@@ -51,20 +49,8 @@ module Aikido::Zen
|
|
51
49
|
end
|
52
50
|
|
53
51
|
config.after_initialize do
|
54
|
-
|
55
|
-
|
56
|
-
# Make sure this is run at the end of the initialization process, so
|
57
|
-
# that any gems required after aikido-zen are detected and patched
|
58
|
-
# accordingly.
|
59
|
-
Aikido::Zen.load_sinks!
|
60
|
-
|
61
|
-
# It's important we start after loading sinks, so we can report the installed packages
|
52
|
+
# Start the Aikido Agent only once the application starts.
|
62
53
|
Aikido::Zen.start!
|
63
|
-
|
64
|
-
# Agent's bootstrap process has finished —Controllers are patched to block
|
65
|
-
# unwanted requests, sinks are loaded, scanners are running—, so we mark
|
66
|
-
# the agent as installed.
|
67
|
-
Aikido::Zen.middleware_installed!
|
68
54
|
end
|
69
55
|
end
|
70
56
|
end
|
@@ -7,14 +7,6 @@ module Aikido::Zen
|
|
7
7
|
module Sinks
|
8
8
|
module Async
|
9
9
|
module HTTP
|
10
|
-
def self.load_sinks!
|
11
|
-
if Aikido::Zen.satisfy "async-http", ">= 0.70.0"
|
12
|
-
require "async/http"
|
13
|
-
|
14
|
-
::Async::HTTP::Client.prepend(Async::HTTP::ClientExtensions)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
10
|
SINK = Sinks.add("async-http", scanners: [
|
19
11
|
Scanners::SSRFScanner,
|
20
12
|
OutboundConnectionMonitor
|
@@ -30,48 +22,54 @@ module Aikido::Zen
|
|
30
22
|
end
|
31
23
|
end
|
32
24
|
|
33
|
-
|
34
|
-
|
25
|
+
def self.load_sinks!
|
26
|
+
if Aikido::Zen.satisfy "async-http", ">= 0.70.0"
|
27
|
+
require "async/http"
|
35
28
|
|
36
|
-
|
37
|
-
|
38
|
-
scheme: request.scheme || scheme,
|
39
|
-
authority: request.authority || authority,
|
40
|
-
path: request.path
|
41
|
-
}))
|
29
|
+
::Async::HTTP::Client.class_eval do
|
30
|
+
extend Sinks::DSL
|
42
31
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
32
|
+
sink_around :call do |original_call, request|
|
33
|
+
uri = URI(format("%<scheme>s://%<authority>s%<path>s", {
|
34
|
+
scheme: request.scheme || scheme,
|
35
|
+
authority: request.authority || authority,
|
36
|
+
path: request.path
|
37
|
+
}))
|
49
38
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
39
|
+
wrapped_request = Scanners::SSRFScanner::Request.new(
|
40
|
+
verb: request.method,
|
41
|
+
uri: uri,
|
42
|
+
headers: request.headers.to_h,
|
43
|
+
header_normalizer: ->(value) { Array(value).join(", ") }
|
44
|
+
)
|
56
45
|
|
57
|
-
|
46
|
+
# Store the request information so the DNS sinks can pick it up.
|
47
|
+
context = Aikido::Zen.current_context
|
48
|
+
if context
|
49
|
+
prev_request = context["ssrf.request"]
|
50
|
+
context["ssrf.request"] = wrapped_request
|
51
|
+
end
|
58
52
|
|
59
|
-
|
53
|
+
connection = OutboundConnection.from_uri(uri)
|
60
54
|
|
61
|
-
|
55
|
+
Helpers.scan(wrapped_request, connection, "request")
|
62
56
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
57
|
+
response = original_call.call
|
58
|
+
|
59
|
+
Scanners::SSRFScanner.track_redirects(
|
60
|
+
request: wrapped_request,
|
61
|
+
response: Scanners::SSRFScanner::Response.new(
|
62
|
+
status: response.status,
|
63
|
+
headers: response.headers.to_h,
|
64
|
+
header_normalizer: ->(value) { Array(value).join(", ") }
|
65
|
+
)
|
66
|
+
)
|
71
67
|
|
72
|
-
|
73
|
-
|
74
|
-
|
68
|
+
response
|
69
|
+
ensure
|
70
|
+
context["ssrf.request"] = prev_request if context
|
71
|
+
end
|
72
|
+
end
|
75
73
|
end
|
76
74
|
end
|
77
75
|
end
|
@@ -6,14 +6,6 @@ require_relative "../outbound_connection_monitor"
|
|
6
6
|
module Aikido::Zen
|
7
7
|
module Sinks
|
8
8
|
module Curl
|
9
|
-
def self.load_sinks!
|
10
|
-
if Aikido::Zen.satisfy "curb", ">= 0.2.3"
|
11
|
-
require "curb"
|
12
|
-
|
13
|
-
::Curl::Easy.prepend(Curl::EasyExtensions)
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
9
|
SINK = Sinks.add("curb", scanners: [
|
18
10
|
Scanners::SSRFScanner,
|
19
11
|
OutboundConnectionMonitor
|
@@ -53,59 +45,65 @@ module Aikido::Zen
|
|
53
45
|
end
|
54
46
|
end
|
55
47
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
sink_around :perform do |super_call|
|
60
|
-
wrapped_request = Helpers.wrap_request(self)
|
61
|
-
|
62
|
-
# Store the request information so the DNS sinks can pick it up.
|
63
|
-
context = Aikido::Zen.current_context
|
64
|
-
if context
|
65
|
-
prev_request = context["ssrf.request"]
|
66
|
-
context["ssrf.request"] = wrapped_request
|
67
|
-
end
|
68
|
-
|
69
|
-
connection = OutboundConnection.from_uri(URI(url))
|
70
|
-
|
71
|
-
Helpers.scan(wrapped_request, connection, "request")
|
72
|
-
|
73
|
-
response = super_call.call
|
74
|
-
|
75
|
-
Scanners::SSRFScanner.track_redirects(
|
76
|
-
request: wrapped_request,
|
77
|
-
response: Helpers.wrap_response(self)
|
78
|
-
)
|
48
|
+
def self.load_sinks!
|
49
|
+
if Aikido::Zen.satisfy "curb", ">= 0.2.3"
|
50
|
+
require "curb"
|
79
51
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
52
|
+
::Curl::Easy.class_eval do
|
53
|
+
extend Sinks::DSL
|
54
|
+
|
55
|
+
sink_around :perform do |original_call|
|
56
|
+
wrapped_request = Helpers.wrap_request(self)
|
57
|
+
|
58
|
+
# Store the request information so the DNS sinks can pick it up.
|
59
|
+
context = Aikido::Zen.current_context
|
60
|
+
if context
|
61
|
+
prev_request = context["ssrf.request"]
|
62
|
+
context["ssrf.request"] = wrapped_request
|
63
|
+
end
|
64
|
+
|
65
|
+
connection = OutboundConnection.from_uri(URI(url))
|
66
|
+
|
67
|
+
Helpers.scan(wrapped_request, connection, "request")
|
68
|
+
|
69
|
+
response = original_call.call
|
70
|
+
|
71
|
+
Scanners::SSRFScanner.track_redirects(
|
72
|
+
request: wrapped_request,
|
73
|
+
response: Helpers.wrap_response(self)
|
74
|
+
)
|
75
|
+
|
76
|
+
# When libcurl has follow_location set, it will handle redirections
|
77
|
+
# internally, and expose the "last_effective_url" as the URI that was
|
78
|
+
# last requested in the redirect chain.
|
79
|
+
#
|
80
|
+
# In this case, we can't actually stop the request from happening, but
|
81
|
+
# we can scan again (now that we know another request happened), to
|
82
|
+
# stop the response from being exposed to the user. This downgrades
|
83
|
+
# the SSRF into a blind SSRF, which is better than doing nothing.
|
84
|
+
if url != last_effective_url
|
85
|
+
last_effective_request = Helpers.wrap_request(self, url: last_effective_url)
|
86
|
+
|
87
|
+
# Code coverage is disabled here because the else clause is a no-op,
|
88
|
+
# so there is nothing to cover.
|
89
|
+
# :nocov:
|
90
|
+
if context
|
91
|
+
context["ssrf.request"] = last_effective_request
|
92
|
+
else
|
93
|
+
# empty
|
94
|
+
end
|
95
|
+
# :nocov:
|
96
|
+
|
97
|
+
connection = OutboundConnection.from_uri(URI(last_effective_url))
|
98
|
+
|
99
|
+
Helpers.scan(last_effective_request, connection, "request")
|
100
|
+
end
|
101
|
+
|
102
|
+
response
|
103
|
+
ensure
|
104
|
+
context["ssrf.request"] = prev_request if context
|
98
105
|
end
|
99
|
-
# :nocov:
|
100
|
-
|
101
|
-
connection = OutboundConnection.from_uri(URI(last_effective_url))
|
102
|
-
|
103
|
-
Helpers.scan(last_effective_request, connection, "request")
|
104
106
|
end
|
105
|
-
|
106
|
-
response
|
107
|
-
ensure
|
108
|
-
context["ssrf.request"] = prev_request if context
|
109
107
|
end
|
110
108
|
end
|
111
109
|
end
|
@@ -7,19 +7,6 @@ module Aikido::Zen
|
|
7
7
|
module Sinks
|
8
8
|
module EventMachine
|
9
9
|
module HttpRequest
|
10
|
-
def self.load_sinks!
|
11
|
-
if Aikido::Zen.satisfy "em-http-request", ">= 1.0"
|
12
|
-
require "em-http-request"
|
13
|
-
|
14
|
-
::EventMachine::HttpRequest.use(EventMachine::HttpRequest::Middleware)
|
15
|
-
|
16
|
-
# NOTE: We can't use middleware to intercept requests as we want to ensure any
|
17
|
-
# modifications to the request from user-supplied middleware are already applied
|
18
|
-
# before we scan the request.
|
19
|
-
::EventMachine::HttpClient.prepend(EventMachine::HttpRequest::HttpClientExtensions)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
10
|
SINK = Sinks.add("em-http-request", scanners: [
|
24
11
|
Scanners::SSRFScanner,
|
25
12
|
OutboundConnectionMonitor
|
@@ -35,26 +22,37 @@ module Aikido::Zen
|
|
35
22
|
end
|
36
23
|
end
|
37
24
|
|
38
|
-
|
39
|
-
|
25
|
+
def self.load_sinks!
|
26
|
+
if Aikido::Zen.satisfy "em-http-request", ">= 1.0"
|
27
|
+
require "em-http-request"
|
40
28
|
|
41
|
-
|
42
|
-
wrapped_request = Scanners::SSRFScanner::Request.new(
|
43
|
-
verb: req.method.to_s,
|
44
|
-
uri: URI(req.uri),
|
45
|
-
headers: req.headers
|
46
|
-
)
|
29
|
+
::EventMachine::HttpRequest.use(EventMachine::HttpRequest::Middleware)
|
47
30
|
|
48
|
-
#
|
49
|
-
|
50
|
-
|
31
|
+
# NOTE: We can't use middleware to intercept requests as we want to ensure any
|
32
|
+
# modifications to the request from user-supplied middleware are already applied
|
33
|
+
# before we scan the request.
|
34
|
+
::EventMachine::HttpClient.class_eval do
|
35
|
+
extend Sinks::DSL
|
51
36
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
37
|
+
sink_before :send_request do
|
38
|
+
wrapped_request = Scanners::SSRFScanner::Request.new(
|
39
|
+
verb: req.method.to_s,
|
40
|
+
uri: URI(req.uri),
|
41
|
+
headers: req.headers
|
42
|
+
)
|
43
|
+
|
44
|
+
# Store the request information so the DNS sinks can pick it up.
|
45
|
+
context = Aikido::Zen.current_context
|
46
|
+
context["ssrf.request"] = wrapped_request if context
|
47
|
+
|
48
|
+
connection = OutboundConnection.new(
|
49
|
+
host: req.host,
|
50
|
+
port: req.port
|
51
|
+
)
|
56
52
|
|
57
|
-
|
53
|
+
Helpers.scan(wrapped_request, connection, "request")
|
54
|
+
end
|
55
|
+
end
|
58
56
|
end
|
59
57
|
end
|
60
58
|
|
@@ -6,15 +6,6 @@ require_relative "../outbound_connection_monitor"
|
|
6
6
|
module Aikido::Zen
|
7
7
|
module Sinks
|
8
8
|
module Excon
|
9
|
-
def self.load_sinks!
|
10
|
-
if Aikido::Zen.satisfy "excon", ">= 0.50.0"
|
11
|
-
require "excon"
|
12
|
-
|
13
|
-
::Excon::Connection.prepend(ConnectionExtensions)
|
14
|
-
::Excon::Middleware::RedirectFollower.prepend(RedirectFollowerExtensions)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
9
|
SINK = Sinks.add("excon", scanners: [
|
19
10
|
Scanners::SSRFScanner,
|
20
11
|
OutboundConnectionMonitor
|
@@ -46,72 +37,78 @@ module Aikido::Zen
|
|
46
37
|
end
|
47
38
|
end
|
48
39
|
|
49
|
-
|
50
|
-
|
40
|
+
def self.load_sinks!
|
41
|
+
if Aikido::Zen.satisfy "excon", ">= 0.50.0"
|
42
|
+
require "excon"
|
43
|
+
|
44
|
+
::Excon::Connection.class_eval do
|
45
|
+
extend Sinks::DSL
|
51
46
|
|
52
|
-
|
53
|
-
|
47
|
+
sink_around :request do |original_call, params = {}|
|
48
|
+
request = Helpers.build_request(@data, params)
|
54
49
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
50
|
+
# Store the request information so the DNS sinks can pick it up.
|
51
|
+
context = Aikido::Zen.current_context
|
52
|
+
if context
|
53
|
+
prev_request = context["ssrf.request"]
|
54
|
+
context["ssrf.request"] = request
|
55
|
+
end
|
61
56
|
|
62
|
-
|
57
|
+
connection = OutboundConnection.from_uri(request.uri)
|
63
58
|
|
64
|
-
|
59
|
+
Helpers.scan(request, connection, "request")
|
65
60
|
|
66
|
-
|
61
|
+
response = original_call.call
|
67
62
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
63
|
+
Scanners::SSRFScanner.track_redirects(
|
64
|
+
request: request,
|
65
|
+
response: Scanners::SSRFScanner::Response.new(
|
66
|
+
status: response.status,
|
67
|
+
headers: response.headers.to_h
|
68
|
+
)
|
69
|
+
)
|
75
70
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
71
|
+
response
|
72
|
+
rescue Sinks::DSL::PresafeError => err
|
73
|
+
outer_cause = err.cause
|
74
|
+
case outer_cause
|
75
|
+
when ::Excon::Error::Socket
|
76
|
+
inner_cause = outer_cause.cause
|
77
|
+
# Excon wraps errors inside the lower level layer. This only happens
|
78
|
+
# to our scanning exceptions when a request is using RedirectFollower,
|
79
|
+
# so we unwrap them when it happens so host apps can handle errors
|
80
|
+
# consistently.
|
81
|
+
raise inner_cause if inner_cause.is_a?(Aikido::Zen::UnderAttackError)
|
82
|
+
end
|
83
|
+
raise
|
84
|
+
ensure
|
85
|
+
context["ssrf.request"] = prev_request if context
|
86
|
+
end
|
87
87
|
end
|
88
|
-
raise
|
89
|
-
ensure
|
90
|
-
context["ssrf.request"] = prev_request if context
|
91
|
-
end
|
92
|
-
end
|
93
88
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
89
|
+
::Excon::Middleware::RedirectFollower.class_eval do
|
90
|
+
extend Sinks::DSL
|
91
|
+
|
92
|
+
sink_before :response_call do |datum|
|
93
|
+
response = datum[:response]
|
94
|
+
|
95
|
+
# Code coverage is disabled here because the else clause is a no-op,
|
96
|
+
# so there is nothing to cover.
|
97
|
+
# :nocov:
|
98
|
+
if !response.nil?
|
99
|
+
Scanners::SSRFScanner.track_redirects(
|
100
|
+
request: Helpers.build_request(datum, {}),
|
101
|
+
response: Scanners::SSRFScanner::Response.new(
|
102
|
+
status: response[:status],
|
103
|
+
headers: response[:headers]
|
104
|
+
)
|
105
|
+
)
|
106
|
+
else
|
107
|
+
# empty
|
108
|
+
end
|
109
|
+
# :nocov:
|
110
|
+
end
|
113
111
|
end
|
114
|
-
# :nocov:
|
115
112
|
end
|
116
113
|
end
|
117
114
|
end
|