aikido-zen 1.0.1.beta.3-x86_64-darwin → 1.0.1.beta.5-x86_64-darwin

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.
@@ -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
- module FileClassExtensions
30
- extend Sinks::DSL
17
+ def self.load_sinks!
18
+ ::File.singleton_class.class_eval do
19
+ extend Sinks::DSL
31
20
 
32
- sink_before :open do |path|
33
- Helpers.scan(path, "open")
34
- end
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
- sink_before :read do |path|
37
- Helpers.scan(path, "read")
38
- end
27
+ sink_before :open do |path|
28
+ Helpers.scan(path, "open")
29
+ end
39
30
 
40
- sink_before :write do |path|
41
- Helpers.scan(path, "write")
42
- end
31
+ sink_before :read do |path|
32
+ Helpers.scan(path, "read")
33
+ end
43
34
 
44
- sink_before :truncate do |file_name|
45
- Helpers.scan(file_name, "truncate")
46
- end
35
+ sink_before :write do |path|
36
+ Helpers.scan(path, "write")
37
+ end
47
38
 
48
- sink_before :rename do |old_name, new_name|
49
- Helpers.scan(old_name, "rename")
50
- Helpers.scan(new_name, "rename")
51
- end
39
+ sink_before :truncate do |file_name|
40
+ Helpers.scan(file_name, "truncate")
41
+ end
52
42
 
53
- sink_before :unlink do |*file_names|
54
- file_names.each do |file_name|
55
- Helpers.scan(file_name, "unlink")
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
- sink_before :delete do |*file_names|
60
- file_names.each do |file_name|
61
- Helpers.scan(file_name, "delete")
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
- sink_before :symlink do |old_name, new_name|
66
- Helpers.scan(old_name, "symlink")
67
- Helpers.scan(new_name, "symlink")
68
- end
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
- sink_before :chmod do |_mode_int, *file_names|
71
- file_names.each do |file_name|
72
- Helpers.scan(file_name, "chmod")
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
- sink_before :chown do |_owner_int, group_int, *file_names|
77
- file_names.each do |file_name|
78
- Helpers.scan(file_name, "chown")
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
- sink_before :utime do |_atime, _mtime, *file_names|
83
- file_names.each do |file_name|
84
- Helpers.scan(file_name, "utime")
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
- sink_after :join do |result|
89
- Helpers.scan(result, "join")
90
- end
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
- sink_before :expand_path do |file_name|
93
- Helpers.scan(file_name, "expand_path")
94
- end
83
+ sink_after :join do |result|
84
+ Helpers.scan(result, "join")
85
+ end
95
86
 
96
- sink_before :realpath do |file_name|
97
- Helpers.scan(file_name, "realpath")
98
- end
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
- sink_before :realdirpath do |file_name|
101
- Helpers.scan(file_name, "realdirpath")
95
+ sink_before :realdirpath do |file_name|
96
+ Helpers.scan(file_name, "realdirpath")
97
+ end
102
98
  end
103
- end
104
99
 
105
- module FileExtensions
106
- extend Sinks::DSL
100
+ ::File.class_eval do
101
+ extend Sinks::DSL
107
102
 
108
- sink_before :initialize do |path|
109
- Helpers.scan(path, "new")
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
- module ClientExtensions
63
- extend Sinks::DSL
54
+ def self.load_sinks!
55
+ if Aikido::Zen.satisfy "http", ">= 1.0"
56
+ require "http"
64
57
 
65
- sink_around :perform do |super_call, req|
66
- wrapped_request = Helpers.wrap_request(req)
58
+ ::HTTP::Client.class_eval do
59
+ extend Sinks::DSL
67
60
 
68
- # Store the request information so the DNS sinks can pick it up.
69
- context = Aikido::Zen.current_context
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
- connection = Helpers.build_outbound(req)
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
- Helpers.scan(wrapped_request, connection, "request")
71
+ connection = Helpers.build_outbound(req)
78
72
 
79
- response = super_call.call
73
+ Helpers.scan(wrapped_request, connection, "request")
80
74
 
81
- Scanners::SSRFScanner.track_redirects(
82
- request: wrapped_request,
83
- response: Helpers.wrap_response(response)
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
- response
87
- ensure
88
- context["ssrf.request"] = prev_request if context
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
- module HTTPClientExtensions
70
- extend Sinks::DSL
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
- sink_after :do_get_header do |_result, req, res, _sess|
83
- # Code coverage is disabled here because `do_get_header` is not called,
84
- # because WebMock does not mock it.
85
- # :nocov:
86
- Scanners::SSRFScanner.track_redirects(
87
- request: Helpers.wrap_request(req),
88
- response: Helpers.wrap_response(res)
89
- )
90
- # :nocov:
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
- module SessionExtensions
48
- extend Sinks::DSL
39
+ def self.load_sinks!
40
+ if Aikido::Zen.satisfy "httpx", ">= 1.1.3"
41
+ require "httpx"
49
42
 
50
- sink_around :send_request do |super_call, request|
51
- wrapped_request = Helpers.wrap_request(request)
43
+ ::HTTPX::Session.class_eval do
44
+ extend Sinks::DSL
52
45
 
53
- # Store the request information so the DNS sinks can pick it up.
54
- context = Aikido::Zen.current_context
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
- connection = OutboundConnection.from_uri(request.uri)
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
- Helpers.scan(wrapped_request, connection, "request")
56
+ connection = OutboundConnection.from_uri(request.uri)
63
57
 
64
- request.on(:response) do |response|
65
- Scanners::SSRFScanner.track_redirects(
66
- request: wrapped_request,
67
- response: Helpers.wrap_response(response)
68
- )
69
- end
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
- super_call.call
72
- ensure
73
- context["ssrf.request"] = prev_request if context
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
- module KernelExtensions
20
- extend Sinks::DSL
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
- %i[system spawn].each do |method_name|
23
- sink_before method_name do |*args|
24
- # Remove the optional environment argument before the command-line.
25
- args.shift if args.first.is_a?(Hash)
26
- Helpers.scan(args.first, method_name)
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
- module ClientExtensions
23
- extend Sinks::DSL
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
- sink_before :query do |sql|
26
- Helpers.scan(sql, "query")
21
+ sink_before :query do |sql|
22
+ Helpers.scan(sql, "query")
23
+ end
24
+ end
27
25
  end
28
26
  end
29
27
  end
@@ -7,13 +7,6 @@ module Aikido::Zen
7
7
  module Sinks
8
8
  module Net
9
9
  module HTTP
10
- def self.load_sinks!
11
- # In stdlib but not always required
12
- require "net/http"
13
-
14
- ::Net::HTTP.prepend(Net::HTTP::HTTPExtensions)
15
- end
16
-
17
10
  SINK = Sinks.add("net-http", scanners: [
18
11
  Scanners::SSRFScanner,
19
12
  OutboundConnectionMonitor
@@ -66,33 +59,38 @@ module Aikido::Zen
66
59
  end
67
60
  end
68
61
 
69
- module HTTPExtensions
70
- extend Sinks::DSL
62
+ def self.load_sinks!
63
+ # In stdlib but not always required
64
+ require "net/http"
71
65
 
72
- sink_around :request do |super_call, req|
73
- wrapped_request = Helpers.wrap_request(req, self)
66
+ ::Net::HTTP.class_eval do
67
+ extend Sinks::DSL
74
68
 
75
- # Store the request information so the DNS sinks can pick it up.
76
- context = Aikido::Zen.current_context
77
- if context
78
- prev_request = context["ssrf.request"]
79
- context["ssrf.request"] = wrapped_request
80
- end
69
+ sink_around :request do |original_call, req|
70
+ wrapped_request = Helpers.wrap_request(req, self)
81
71
 
82
- connection = Helpers.build_outbound(self)
72
+ # Store the request information so the DNS sinks can pick it up.
73
+ context = Aikido::Zen.current_context
74
+ if context
75
+ prev_request = context["ssrf.request"]
76
+ context["ssrf.request"] = wrapped_request
77
+ end
83
78
 
84
- Helpers.scan(wrapped_request, connection, "request")
79
+ connection = Helpers.build_outbound(self)
85
80
 
86
- response = super_call.call
81
+ Helpers.scan(wrapped_request, connection, "request")
87
82
 
88
- Scanners::SSRFScanner.track_redirects(
89
- request: wrapped_request,
90
- response: Helpers.wrap_response(response)
91
- )
83
+ response = original_call.call
84
+
85
+ Scanners::SSRFScanner.track_redirects(
86
+ request: wrapped_request,
87
+ response: Helpers.wrap_response(response)
88
+ )
92
89
 
93
- response
94
- ensure
95
- context["ssrf.request"] = prev_request if context
90
+ response
91
+ ensure
92
+ context["ssrf.request"] = prev_request if context
93
+ end
96
94
  end
97
95
  end
98
96
  end
@@ -6,14 +6,6 @@ require_relative "../outbound_connection_monitor"
6
6
  module Aikido::Zen
7
7
  module Sinks
8
8
  module Patron
9
- def self.load_sinks!
10
- if Aikido::Zen.satisfy "patron", ">= 0.6.4"
11
- require "patron"
12
-
13
- ::Patron::Session.prepend(SessionExtensions)
14
- end
15
- end
16
-
17
9
  SINK = Sinks.add("patron", scanners: [
18
10
  Scanners::SSRFScanner,
19
11
  OutboundConnectionMonitor
@@ -44,58 +36,64 @@ module Aikido::Zen
44
36
  end
45
37
  end
46
38
 
47
- module SessionExtensions
48
- extend Sinks::DSL
49
-
50
- sink_around :handle_request do |super_call, request|
51
- wrapped_request = Scanners::SSRFScanner::Request.new(
52
- verb: request.action,
53
- uri: URI(request.url),
54
- headers: request.headers
55
- )
56
-
57
- # Store the request information so the DNS sinks can pick it up.
58
- context = Aikido::Zen.current_context
59
- if context
60
- prev_request = context["ssrf.request"]
61
- context["ssrf.request"] = wrapped_request
62
- end
63
-
64
- connection = OutboundConnection.from_uri(URI(request.url))
65
-
66
- Helpers.scan(wrapped_request, connection, "request")
67
-
68
- response = super_call.call
69
-
70
- Scanners::SSRFScanner.track_redirects(
71
- request: wrapped_request,
72
- response: Helpers.wrap_response(request, response)
73
- )
74
-
75
- # When libcurl has follow_location set, it will handle redirections
76
- # internally, and expose the response.url as the URI that was last
77
- # requested in the redirect chain.
78
- #
79
- # In this case, we can't actually stop the request from happening, but
80
- # we can scan again (now that we know another request happened), to
81
- # stop the response from being exposed to the user. This downgrades
82
- # the SSRF into a blind SSRF, which is better than doing nothing.
83
- if request.url != response.url && !response.url.to_s.empty?
84
- last_effective_request = Scanners::SSRFScanner::Request.new(
85
- verb: request.action,
86
- uri: URI(response.url),
87
- headers: request.headers
88
- )
89
- context["ssrf.request"] = last_effective_request if context
90
-
91
- connection = OutboundConnection.from_uri(URI(response.url))
39
+ def self.load_sinks!
40
+ if Aikido::Zen.satisfy "patron", ">= 0.6.4"
41
+ require "patron"
92
42
 
93
- Helpers.scan(last_effective_request, connection, "request")
43
+ ::Patron::Session.class_eval do
44
+ extend Sinks::DSL
45
+
46
+ sink_around :handle_request do |original_call, request|
47
+ wrapped_request = Scanners::SSRFScanner::Request.new(
48
+ verb: request.action,
49
+ uri: URI(request.url),
50
+ headers: request.headers
51
+ )
52
+
53
+ # Store the request information so the DNS sinks can pick it up.
54
+ context = Aikido::Zen.current_context
55
+ if context
56
+ prev_request = context["ssrf.request"]
57
+ context["ssrf.request"] = wrapped_request
58
+ end
59
+
60
+ connection = OutboundConnection.from_uri(URI(request.url))
61
+
62
+ Helpers.scan(wrapped_request, connection, "request")
63
+
64
+ response = original_call.call
65
+
66
+ Scanners::SSRFScanner.track_redirects(
67
+ request: wrapped_request,
68
+ response: Helpers.wrap_response(request, response)
69
+ )
70
+
71
+ # When libcurl has follow_location set, it will handle redirections
72
+ # internally, and expose the response.url as the URI that was last
73
+ # requested in the redirect chain.
74
+ #
75
+ # In this case, we can't actually stop the request from happening, but
76
+ # we can scan again (now that we know another request happened), to
77
+ # stop the response from being exposed to the user. This downgrades
78
+ # the SSRF into a blind SSRF, which is better than doing nothing.
79
+ if request.url != response.url && !response.url.to_s.empty?
80
+ last_effective_request = Scanners::SSRFScanner::Request.new(
81
+ verb: request.action,
82
+ uri: URI(response.url),
83
+ headers: request.headers
84
+ )
85
+ context["ssrf.request"] = last_effective_request if context
86
+
87
+ connection = OutboundConnection.from_uri(URI(response.url))
88
+
89
+ Helpers.scan(last_effective_request, connection, "request")
90
+ end
91
+
92
+ response
93
+ ensure
94
+ context["ssrf.request"] = prev_request if context
95
+ end
94
96
  end
95
-
96
- response
97
- ensure
98
- context["ssrf.request"] = prev_request if context
99
97
  end
100
98
  end
101
99
  end