console1984 0.1.14 → 0.1.18
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +5 -2
- data/lib/console1984/command_executor.rb +10 -12
- data/lib/console1984/ext/active_record/protected_auditable_tables.rb +1 -1
- data/lib/console1984/ext/core/module.rb +1 -1
- data/lib/console1984/ext/core/object.rb +1 -1
- data/lib/console1984/ext/core/string.rb +24 -0
- data/lib/console1984/ext/irb/commands.rb +9 -0
- data/lib/console1984/refrigerator.rb +5 -5
- data/lib/console1984/shield.rb +1 -1
- data/lib/console1984/version.rb +1 -1
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 68e6cdce847f11b0872e12826a4fd65b7e31e267461de5b6e85582a692310e0a
|
4
|
+
data.tar.gz: aac2138d6008c87076de90b8944bf246584b47cd061a160c54f0138345491f6d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '0388bba4469870ce2616845c31ee6ea34e08e6af1bb3d39e239a87cd4c3c7ee4ec7602f0e928904ae256e0bbc17554e694724067e529026f9d5cae9dff83bc0f'
|
7
|
+
data.tar.gz: 2a96eaa2ecd586694a12d0bbf9dc717ef4a9585ebd277a1b538d5e589495742c63cb6d2b8c9918db9b55f07d9c1338416e4d18365628daf7286757d953cdc316
|
data/README.md
CHANGED
@@ -35,6 +35,9 @@ By default, console1984 is only enabled in `production`. You can configure the t
|
|
35
35
|
config.console1984.protected_environments = %i[ production staging ]
|
36
36
|
```
|
37
37
|
|
38
|
+
Finally, you need to [configure Active Record Encryption](https://edgeguides.rubyonrails.org/active_record_encryption.html#setup) in your
|
39
|
+
project. This is because the library stores the tracked console commands encrypted.
|
40
|
+
|
38
41
|
## How it works
|
39
42
|
|
40
43
|
### Session activity logging
|
@@ -155,9 +158,9 @@ These config options are namespaced in `config.console1984`:
|
|
155
158
|
|
156
159
|
## About built-in protection mechanisms
|
157
160
|
|
158
|
-
`console1984`
|
161
|
+
`console1984` adds many protection mechanisms to prevent tampering. This includes attempts to alter data in auditing tables or monkey patching certain classes to change how the system works. If you find a way to circumvent these tampering controls, please [report an issue](https://github.com/basecamp/console1984/issues).
|
159
162
|
|
160
|
-
|
163
|
+
We aim to make these defense mechanisms as robust as possible, but there might always be open doors because Ruby is highly dynamic. If your organization needs bullet-proof protection against malicious actors using the console, you should consider additional security measures. An example would be using a read-only database user for auditing data while in a console. The gem doesn't offer direct support for doing this, but it's on our radar for future improvement.
|
161
164
|
|
162
165
|
## Running the test suite
|
163
166
|
|
@@ -10,6 +10,7 @@ class Console1984::CommandExecutor
|
|
10
10
|
include Console1984::Freezeable
|
11
11
|
|
12
12
|
delegate :username_resolver, :session_logger, :shield, to: Console1984
|
13
|
+
attr_reader :last_suspicious_command_error
|
13
14
|
|
14
15
|
# Logs and validates +commands+, and executes the passed block in a protected environment.
|
15
16
|
#
|
@@ -19,14 +20,14 @@ class Console1984::CommandExecutor
|
|
19
20
|
run_as_system { session_logger.before_executing commands }
|
20
21
|
validate_command commands
|
21
22
|
execute_in_protected_mode(&block)
|
22
|
-
rescue Console1984::Errors::ForbiddenCommandAttempted, FrozenError
|
23
|
-
flag_suspicious(commands)
|
24
|
-
rescue Console1984::Errors::SuspiciousCommandAttempted
|
25
|
-
flag_suspicious(commands)
|
23
|
+
rescue Console1984::Errors::ForbiddenCommandAttempted, FrozenError => error
|
24
|
+
flag_suspicious(commands, error: error)
|
25
|
+
rescue Console1984::Errors::SuspiciousCommandAttempted => error
|
26
|
+
flag_suspicious(commands, error: error)
|
26
27
|
execute_in_protected_mode(&block)
|
27
|
-
rescue Console1984::Errors::ForbiddenCommandExecuted
|
28
|
+
rescue Console1984::Errors::ForbiddenCommandExecuted => error
|
28
29
|
# We detected that a forbidden command was executed. We exit IRB right away.
|
29
|
-
flag_suspicious(commands)
|
30
|
+
flag_suspicious(commands, error: error)
|
30
31
|
Console1984.supervisor.exit_irb
|
31
32
|
ensure
|
32
33
|
run_as_system { session_logger.after_executing commands }
|
@@ -70,11 +71,7 @@ class Console1984::CommandExecutor
|
|
70
71
|
end
|
71
72
|
|
72
73
|
def from_irb?(backtrace)
|
73
|
-
executing_user_command? && backtrace.
|
74
|
-
line_from_irb = line =~ /^[^\/]/
|
75
|
-
break if !(line =~ /console1984\/lib/ || line_from_irb)
|
76
|
-
line_from_irb
|
77
|
-
end
|
74
|
+
executing_user_command? && backtrace.first.to_s =~ /^[^\/]/
|
78
75
|
end
|
79
76
|
|
80
77
|
private
|
@@ -86,9 +83,10 @@ class Console1984::CommandExecutor
|
|
86
83
|
Console1984::CommandValidator.from_config(Console1984.protections_config.validations)
|
87
84
|
end
|
88
85
|
|
89
|
-
def flag_suspicious(commands)
|
86
|
+
def flag_suspicious(commands, error: nil)
|
90
87
|
puts "Forbidden command attempted: #{commands.join("\n")}"
|
91
88
|
run_as_system { session_logger.suspicious_commands_attempted commands }
|
89
|
+
@last_suspicious_command_error = error
|
92
90
|
nil
|
93
91
|
end
|
94
92
|
|
@@ -5,7 +5,7 @@ module Console1984::Ext::ActiveRecord::ProtectedAuditableTables
|
|
5
5
|
%i[ execute exec_query exec_insert exec_delete exec_update exec_insert_all ].each do |method|
|
6
6
|
define_method method do |*args, **kwargs|
|
7
7
|
sql = args.first
|
8
|
-
if Console1984.command_executor.executing_user_command? && sql =~ auditable_tables_regexp
|
8
|
+
if Console1984.command_executor.executing_user_command? && sql.b =~ auditable_tables_regexp
|
9
9
|
raise Console1984::Errors::ForbiddenCommandAttempted, "#{sql}"
|
10
10
|
else
|
11
11
|
super(*args, **kwargs)
|
@@ -6,7 +6,7 @@ module Console1984::Ext::Core::Module
|
|
6
6
|
extend ActiveSupport::Concern
|
7
7
|
|
8
8
|
def instance_eval(*)
|
9
|
-
if Console1984.command_executor.
|
9
|
+
if Console1984.command_executor.from_irb?(caller)
|
10
10
|
raise Console1984::Errors::ForbiddenCommandAttempted
|
11
11
|
else
|
12
12
|
super
|
@@ -16,7 +16,7 @@ module Console1984::Ext::Core::Object
|
|
16
16
|
|
17
17
|
class_methods do
|
18
18
|
def const_get(*arguments)
|
19
|
-
if Console1984.command_executor.
|
19
|
+
if Console1984.command_executor.from_irb?(caller)
|
20
20
|
begin
|
21
21
|
# To validate if it's an invalid constant, we try to declare a class with it.
|
22
22
|
# We essentially leverage Console1984::CommandValidator::ForbiddenReopeningValidation here:
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# Prevents loading forbidden classes dynamically.
|
2
|
+
#
|
3
|
+
# See extension to +Console1984::Ext::Core::Object#const_get+.
|
4
|
+
module Console1984::Ext::Core::String
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
include Console1984::Freezeable
|
8
|
+
self.prevent_instance_data_manipulation_after_freezing = false
|
9
|
+
|
10
|
+
def constantize
|
11
|
+
if Console1984.command_executor.from_irb?(caller)
|
12
|
+
begin
|
13
|
+
Console1984.command_executor.validate_command("class #{self}; end")
|
14
|
+
super
|
15
|
+
rescue Console1984::Errors::ForbiddenCommandAttempted
|
16
|
+
raise
|
17
|
+
rescue StandardError
|
18
|
+
super
|
19
|
+
end
|
20
|
+
else
|
21
|
+
super
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -13,4 +13,13 @@ module Console1984::Ext::Irb::Commands
|
|
13
13
|
def encrypt!
|
14
14
|
shield.enable_protected_mode
|
15
15
|
end
|
16
|
+
|
17
|
+
# This returns the last error that prevented a command execution in the console
|
18
|
+
# or nil if there isn't any.
|
19
|
+
#
|
20
|
+
# This is meant for internal usage when debugging legit commands that are wrongly
|
21
|
+
# prevented.
|
22
|
+
def _console_last_suspicious_command_error
|
23
|
+
Console1984.command_executor.last_suspicious_command_error
|
24
|
+
end
|
16
25
|
end
|
@@ -11,6 +11,11 @@ class Console1984::Refrigerator
|
|
11
11
|
end
|
12
12
|
|
13
13
|
private
|
14
|
+
def eager_load_all_classes
|
15
|
+
Rails.application.eager_load! unless Rails.application.config.eager_load
|
16
|
+
Console1984.class_loader.eager_load
|
17
|
+
end
|
18
|
+
|
14
19
|
def freeze_internal_instances
|
15
20
|
Console1984.config.freeze unless Console1984.config.test_mode
|
16
21
|
end
|
@@ -23,9 +28,4 @@ class Console1984::Refrigerator
|
|
23
28
|
# Not using a constant because we want this to run lazily (console-dependant dependencies might not be loaded).
|
24
29
|
[Parser::CurrentRuby]
|
25
30
|
end
|
26
|
-
|
27
|
-
def eager_load_all_classes
|
28
|
-
Rails.application.eager_load! unless Rails.application.config.eager_load
|
29
|
-
Console1984.class_loader.eager_load
|
30
|
-
end
|
31
31
|
end
|
data/lib/console1984/shield.rb
CHANGED
@@ -40,6 +40,7 @@ class Console1984::Shield
|
|
40
40
|
def extend_core_ruby
|
41
41
|
Object.prepend Console1984::Ext::Core::Object
|
42
42
|
Module.prepend Console1984::Ext::Core::Module
|
43
|
+
String.prepend Console1984::Ext::Core::String
|
43
44
|
end
|
44
45
|
|
45
46
|
def extend_sockets
|
@@ -63,7 +64,6 @@ class Console1984::Shield
|
|
63
64
|
if Object.const_defined?(class_string)
|
64
65
|
klass = class_string.constantize
|
65
66
|
klass.prepend(Console1984::Ext::ActiveRecord::ProtectedAuditableTables)
|
66
|
-
klass.include(Console1984::Freezeable)
|
67
67
|
end
|
68
68
|
end
|
69
69
|
end
|
data/lib/console1984/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: console1984
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.18
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jorge Manrubia
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-09-
|
11
|
+
date: 2021-09-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: colorize
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: activeresource
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: benchmark-ips
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -211,6 +225,7 @@ files:
|
|
211
225
|
- lib/console1984/ext/active_record/protected_auditable_tables.rb
|
212
226
|
- lib/console1984/ext/core/module.rb
|
213
227
|
- lib/console1984/ext/core/object.rb
|
228
|
+
- lib/console1984/ext/core/string.rb
|
214
229
|
- lib/console1984/ext/irb/commands.rb
|
215
230
|
- lib/console1984/ext/irb/context.rb
|
216
231
|
- lib/console1984/ext/socket/tcp_socket.rb
|