aikido-zen 1.0.1.beta.4-x86_64-linux-musl → 1.0.2.beta.1-x86_64-linux-musl
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/docs/rails.md +49 -5
- data/lib/aikido/zen/config.rb +3 -4
- data/lib/aikido/zen/detached_agent/agent.rb +1 -1
- data/lib/aikido/zen/detached_agent/server.rb +63 -26
- 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 +39 -15
- data/lib/aikido/zen/version.rb +1 -1
- data/lib/aikido/zen.rb +7 -2
- metadata +2 -2
@@ -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
|
@@ -3,18 +3,6 @@
|
|
3
3
|
module Aikido::Zen
|
4
4
|
module Sinks
|
5
5
|
module File
|
6
|
-
def self.load_sinks!
|
7
|
-
# Create a copy of the original method for internal use only to prevent
|
8
|
-
# recursion in PathTraversalScanner.
|
9
|
-
#
|
10
|
-
# IMPORTANT: The alias must be created before the method is overridden,
|
11
|
-
# when the extensions are prepended.
|
12
|
-
::File.singleton_class.alias_method(:expand_path__internal_for_aikido_zen, :expand_path)
|
13
|
-
|
14
|
-
::File.singleton_class.prepend(FileClassExtensions)
|
15
|
-
::File.prepend(FileExtensions)
|
16
|
-
end
|
17
|
-
|
18
6
|
SINK = Sinks.add("File", scanners: [Scanners::PathTraversalScanner])
|
19
7
|
|
20
8
|
module Helpers
|
@@ -26,87 +14,95 @@ module Aikido::Zen
|
|
26
14
|
end
|
27
15
|
end
|
28
16
|
|
29
|
-
|
30
|
-
|
17
|
+
def self.load_sinks!
|
18
|
+
::File.singleton_class.class_eval do
|
19
|
+
extend Sinks::DSL
|
31
20
|
|
32
|
-
|
33
|
-
|
34
|
-
|
21
|
+
# Create a copy of the original method for internal use only to prevent
|
22
|
+
# recursion in PathTraversalScanner.
|
23
|
+
#
|
24
|
+
# IMPORTANT: The alias must be created before the method is overridden.
|
25
|
+
alias_method :expand_path__internal_for_aikido_zen, :expand_path
|
35
26
|
|
36
|
-
|
37
|
-
|
38
|
-
|
27
|
+
sink_before :open do |path|
|
28
|
+
Helpers.scan(path, "open")
|
29
|
+
end
|
39
30
|
|
40
|
-
|
41
|
-
|
42
|
-
|
31
|
+
sink_before :read do |path|
|
32
|
+
Helpers.scan(path, "read")
|
33
|
+
end
|
43
34
|
|
44
|
-
|
45
|
-
|
46
|
-
|
35
|
+
sink_before :write do |path|
|
36
|
+
Helpers.scan(path, "write")
|
37
|
+
end
|
47
38
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
end
|
39
|
+
sink_before :truncate do |file_name|
|
40
|
+
Helpers.scan(file_name, "truncate")
|
41
|
+
end
|
52
42
|
|
53
|
-
|
54
|
-
|
55
|
-
Helpers.scan(
|
43
|
+
sink_before :rename do |old_name, new_name|
|
44
|
+
Helpers.scan(old_name, "rename")
|
45
|
+
Helpers.scan(new_name, "rename")
|
56
46
|
end
|
57
|
-
end
|
58
47
|
|
59
|
-
|
60
|
-
|
61
|
-
|
48
|
+
sink_before :unlink do |*file_names|
|
49
|
+
file_names.each do |file_name|
|
50
|
+
Helpers.scan(file_name, "unlink")
|
51
|
+
end
|
62
52
|
end
|
63
|
-
end
|
64
53
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
54
|
+
sink_before :delete do |*file_names|
|
55
|
+
file_names.each do |file_name|
|
56
|
+
Helpers.scan(file_name, "delete")
|
57
|
+
end
|
58
|
+
end
|
69
59
|
|
70
|
-
|
71
|
-
|
72
|
-
Helpers.scan(
|
60
|
+
sink_before :symlink do |old_name, new_name|
|
61
|
+
Helpers.scan(old_name, "symlink")
|
62
|
+
Helpers.scan(new_name, "symlink")
|
73
63
|
end
|
74
|
-
end
|
75
64
|
|
76
|
-
|
77
|
-
|
78
|
-
|
65
|
+
sink_before :chmod do |_mode_int, *file_names|
|
66
|
+
file_names.each do |file_name|
|
67
|
+
Helpers.scan(file_name, "chmod")
|
68
|
+
end
|
79
69
|
end
|
80
|
-
end
|
81
70
|
|
82
|
-
|
83
|
-
|
84
|
-
|
71
|
+
sink_before :chown do |_owner_int, group_int, *file_names|
|
72
|
+
file_names.each do |file_name|
|
73
|
+
Helpers.scan(file_name, "chown")
|
74
|
+
end
|
85
75
|
end
|
86
|
-
end
|
87
76
|
|
88
|
-
|
89
|
-
|
90
|
-
|
77
|
+
sink_before :utime do |_atime, _mtime, *file_names|
|
78
|
+
file_names.each do |file_name|
|
79
|
+
Helpers.scan(file_name, "utime")
|
80
|
+
end
|
81
|
+
end
|
91
82
|
|
92
|
-
|
93
|
-
|
94
|
-
|
83
|
+
sink_after :join do |result|
|
84
|
+
Helpers.scan(result, "join")
|
85
|
+
end
|
95
86
|
|
96
|
-
|
97
|
-
|
98
|
-
|
87
|
+
sink_before :expand_path do |file_name|
|
88
|
+
Helpers.scan(file_name, "expand_path")
|
89
|
+
end
|
90
|
+
|
91
|
+
sink_before :realpath do |file_name|
|
92
|
+
Helpers.scan(file_name, "realpath")
|
93
|
+
end
|
99
94
|
|
100
|
-
|
101
|
-
|
95
|
+
sink_before :realdirpath do |file_name|
|
96
|
+
Helpers.scan(file_name, "realdirpath")
|
97
|
+
end
|
102
98
|
end
|
103
|
-
end
|
104
99
|
|
105
|
-
|
106
|
-
|
100
|
+
::File.class_eval do
|
101
|
+
extend Sinks::DSL
|
107
102
|
|
108
|
-
|
109
|
-
|
103
|
+
sink_before :initialize do |path|
|
104
|
+
Helpers.scan(path, "new")
|
105
|
+
end
|
110
106
|
end
|
111
107
|
end
|
112
108
|
end
|
@@ -6,14 +6,6 @@ require_relative "../outbound_connection_monitor"
|
|
6
6
|
module Aikido::Zen
|
7
7
|
module Sinks
|
8
8
|
module HTTP
|
9
|
-
def self.load_sinks!
|
10
|
-
if Aikido::Zen.satisfy "http", ">= 1.0"
|
11
|
-
require "http"
|
12
|
-
|
13
|
-
::HTTP::Client.prepend(ClientExtensions)
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
9
|
SINK = Sinks.add("http", scanners: [
|
18
10
|
Scanners::SSRFScanner,
|
19
11
|
OutboundConnectionMonitor
|
@@ -59,33 +51,39 @@ module Aikido::Zen
|
|
59
51
|
end
|
60
52
|
end
|
61
53
|
|
62
|
-
|
63
|
-
|
54
|
+
def self.load_sinks!
|
55
|
+
if Aikido::Zen.satisfy "http", ">= 1.0"
|
56
|
+
require "http"
|
64
57
|
|
65
|
-
|
66
|
-
|
58
|
+
::HTTP::Client.class_eval do
|
59
|
+
extend Sinks::DSL
|
67
60
|
|
68
|
-
|
69
|
-
|
70
|
-
if context
|
71
|
-
prev_request = context["ssrf.request"]
|
72
|
-
context["ssrf.request"] = wrapped_request
|
73
|
-
end
|
61
|
+
sink_around :perform do |original_call, req|
|
62
|
+
wrapped_request = Helpers.wrap_request(req)
|
74
63
|
|
75
|
-
|
64
|
+
# Store the request information so the DNS sinks can pick it up.
|
65
|
+
context = Aikido::Zen.current_context
|
66
|
+
if context
|
67
|
+
prev_request = context["ssrf.request"]
|
68
|
+
context["ssrf.request"] = wrapped_request
|
69
|
+
end
|
76
70
|
|
77
|
-
|
71
|
+
connection = Helpers.build_outbound(req)
|
78
72
|
|
79
|
-
|
73
|
+
Helpers.scan(wrapped_request, connection, "request")
|
80
74
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
75
|
+
response = original_call.call
|
76
|
+
|
77
|
+
Scanners::SSRFScanner.track_redirects(
|
78
|
+
request: wrapped_request,
|
79
|
+
response: Helpers.wrap_response(response)
|
80
|
+
)
|
85
81
|
|
86
|
-
|
87
|
-
|
88
|
-
|
82
|
+
response
|
83
|
+
ensure
|
84
|
+
context["ssrf.request"] = prev_request if context
|
85
|
+
end
|
86
|
+
end
|
89
87
|
end
|
90
88
|
end
|
91
89
|
end
|
@@ -6,14 +6,6 @@ require_relative "../outbound_connection_monitor"
|
|
6
6
|
module Aikido::Zen
|
7
7
|
module Sinks
|
8
8
|
module HTTPClient
|
9
|
-
def self.load_sinks!
|
10
|
-
if Aikido::Zen.satisfy "httpclient", ">= 2.0"
|
11
|
-
require "httpclient"
|
12
|
-
|
13
|
-
::HTTPClient.prepend(HTTPClient::HTTPClientExtensions)
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
9
|
SINK = Sinks.add("httpclient", scanners: [
|
18
10
|
Scanners::SSRFScanner,
|
19
11
|
OutboundConnectionMonitor
|
@@ -66,28 +58,34 @@ module Aikido::Zen
|
|
66
58
|
end
|
67
59
|
end
|
68
60
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
private
|
73
|
-
|
74
|
-
sink_around :do_get_block do |super_call, req|
|
75
|
-
Helpers.sink(req, &super_call)
|
76
|
-
end
|
77
|
-
|
78
|
-
sink_around :do_get_stream do |super_call, req|
|
79
|
-
Helpers.sink(req, &super_call)
|
80
|
-
end
|
61
|
+
def self.load_sinks!
|
62
|
+
if Aikido::Zen.satisfy "httpclient", ">= 2.0"
|
63
|
+
require "httpclient"
|
81
64
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
65
|
+
::HTTPClient.class_eval do
|
66
|
+
extend Sinks::DSL
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
sink_around :do_get_block do |original_call, req|
|
71
|
+
Helpers.sink(req, &original_call)
|
72
|
+
end
|
73
|
+
|
74
|
+
sink_around :do_get_stream do |original_call, req|
|
75
|
+
Helpers.sink(req, &original_call)
|
76
|
+
end
|
77
|
+
|
78
|
+
sink_after :do_get_header do |_result, req, res, _sess|
|
79
|
+
# Code coverage is disabled here because `do_get_header` is not called,
|
80
|
+
# because WebMock does not mock it.
|
81
|
+
# :nocov:
|
82
|
+
Scanners::SSRFScanner.track_redirects(
|
83
|
+
request: Helpers.wrap_request(req),
|
84
|
+
response: Helpers.wrap_response(res)
|
85
|
+
)
|
86
|
+
# :nocov:
|
87
|
+
end
|
88
|
+
end
|
91
89
|
end
|
92
90
|
end
|
93
91
|
end
|
@@ -6,14 +6,6 @@ require_relative "../outbound_connection_monitor"
|
|
6
6
|
module Aikido::Zen
|
7
7
|
module Sinks
|
8
8
|
module HTTPX
|
9
|
-
def self.load_sinks!
|
10
|
-
if Aikido::Zen.satisfy "httpx", ">= 1.1.3"
|
11
|
-
require "httpx"
|
12
|
-
|
13
|
-
::HTTPX::Session.prepend(HTTPX::SessionExtensions)
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
9
|
SINK = Sinks.add("httpx", scanners: [
|
18
10
|
Scanners::SSRFScanner,
|
19
11
|
OutboundConnectionMonitor
|
@@ -44,33 +36,39 @@ module Aikido::Zen
|
|
44
36
|
end
|
45
37
|
end
|
46
38
|
|
47
|
-
|
48
|
-
|
39
|
+
def self.load_sinks!
|
40
|
+
if Aikido::Zen.satisfy "httpx", ">= 1.1.3"
|
41
|
+
require "httpx"
|
49
42
|
|
50
|
-
|
51
|
-
|
43
|
+
::HTTPX::Session.class_eval do
|
44
|
+
extend Sinks::DSL
|
52
45
|
|
53
|
-
|
54
|
-
|
55
|
-
if context
|
56
|
-
prev_request = context["ssrf.request"]
|
57
|
-
context["ssrf.request"] = wrapped_request
|
58
|
-
end
|
46
|
+
sink_around :send_request do |original_call, request|
|
47
|
+
wrapped_request = Helpers.wrap_request(request)
|
59
48
|
|
60
|
-
|
49
|
+
# Store the request information so the DNS sinks can pick it up.
|
50
|
+
context = Aikido::Zen.current_context
|
51
|
+
if context
|
52
|
+
prev_request = context["ssrf.request"]
|
53
|
+
context["ssrf.request"] = wrapped_request
|
54
|
+
end
|
61
55
|
|
62
|
-
|
56
|
+
connection = OutboundConnection.from_uri(request.uri)
|
63
57
|
|
64
|
-
|
65
|
-
|
66
|
-
request:
|
67
|
-
|
68
|
-
|
69
|
-
|
58
|
+
Helpers.scan(wrapped_request, connection, "request")
|
59
|
+
|
60
|
+
request.on(:response) do |response|
|
61
|
+
Scanners::SSRFScanner.track_redirects(
|
62
|
+
request: wrapped_request,
|
63
|
+
response: Helpers.wrap_response(response)
|
64
|
+
)
|
65
|
+
end
|
70
66
|
|
71
|
-
|
72
|
-
|
73
|
-
|
67
|
+
original_call.call
|
68
|
+
ensure
|
69
|
+
context["ssrf.request"] = prev_request if context
|
70
|
+
end
|
71
|
+
end
|
74
72
|
end
|
75
73
|
end
|
76
74
|
end
|
@@ -3,11 +3,6 @@
|
|
3
3
|
module Aikido::Zen
|
4
4
|
module Sinks
|
5
5
|
module Kernel
|
6
|
-
def self.load_sinks!
|
7
|
-
::Kernel.singleton_class.prepend(KernelExtensions)
|
8
|
-
::Kernel.prepend(KernelExtensions)
|
9
|
-
end
|
10
|
-
|
11
6
|
SINK = Sinks.add("Kernel", scanners: [Scanners::ShellInjectionScanner])
|
12
7
|
|
13
8
|
module Helpers
|
@@ -16,14 +11,18 @@ module Aikido::Zen
|
|
16
11
|
end
|
17
12
|
end
|
18
13
|
|
19
|
-
|
20
|
-
|
14
|
+
def self.load_sinks!
|
15
|
+
[::Kernel.singleton_class, ::Kernel].each do |klass|
|
16
|
+
klass.class_eval do
|
17
|
+
extend Sinks::DSL
|
21
18
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
19
|
+
%i[system spawn].each do |method_name|
|
20
|
+
sink_before method_name do |*args|
|
21
|
+
# Remove the optional environment argument before the command-line.
|
22
|
+
args.shift if args.first.is_a?(Hash)
|
23
|
+
Helpers.scan(args.first, method_name)
|
24
|
+
end
|
25
|
+
end
|
27
26
|
end
|
28
27
|
end
|
29
28
|
end
|
@@ -3,14 +3,6 @@
|
|
3
3
|
module Aikido::Zen
|
4
4
|
module Sinks
|
5
5
|
module Mysql2
|
6
|
-
def self.load_sinks!
|
7
|
-
if Aikido::Zen.satisfy "mysql2"
|
8
|
-
require "mysql2"
|
9
|
-
|
10
|
-
::Mysql2::Client.prepend(ClientExtensions)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
6
|
SINK = Sinks.add("mysql2", scanners: [Scanners::SQLInjectionScanner])
|
15
7
|
|
16
8
|
module Helpers
|
@@ -19,11 +11,17 @@ module Aikido::Zen
|
|
19
11
|
end
|
20
12
|
end
|
21
13
|
|
22
|
-
|
23
|
-
|
14
|
+
def self.load_sinks!
|
15
|
+
if Aikido::Zen.satisfy "mysql2"
|
16
|
+
require "mysql2"
|
17
|
+
|
18
|
+
::Mysql2::Client.class_eval do
|
19
|
+
extend Sinks::DSL
|
24
20
|
|
25
|
-
|
26
|
-
|
21
|
+
sink_before :query do |sql|
|
22
|
+
Helpers.scan(sql, "query")
|
23
|
+
end
|
24
|
+
end
|
27
25
|
end
|
28
26
|
end
|
29
27
|
end
|