Skip to content

Commit

Permalink
Merge pull request #34 from basecamp/debug-errors
Browse files Browse the repository at this point in the history
Fix flagging `String#constantize` invocations as suspicious
  • Loading branch information
jorgemanrubia authored Sep 24, 2021
2 parents fc99bd6 + f405535 commit b8f050d
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 13 deletions.
22 changes: 10 additions & 12 deletions lib/console1984/command_executor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class Console1984::CommandExecutor
include Console1984::Freezeable

delegate :username_resolver, :session_logger, :shield, to: Console1984
attr_reader :last_suspicious_command_error

# Logs and validates +commands+, and executes the passed block in a protected environment.
#
Expand All @@ -19,14 +20,14 @@ def execute(commands, &block)
run_as_system { session_logger.before_executing commands }
validate_command commands
execute_in_protected_mode(&block)
rescue Console1984::Errors::ForbiddenCommandAttempted, FrozenError
flag_suspicious(commands)
rescue Console1984::Errors::SuspiciousCommandAttempted
flag_suspicious(commands)
rescue Console1984::Errors::ForbiddenCommandAttempted, FrozenError => error
flag_suspicious(commands, error: error)
rescue Console1984::Errors::SuspiciousCommandAttempted => error
flag_suspicious(commands, error: error)
execute_in_protected_mode(&block)
rescue Console1984::Errors::ForbiddenCommandExecuted
rescue Console1984::Errors::ForbiddenCommandExecuted => error
# We detected that a forbidden command was executed. We exit IRB right away.
flag_suspicious(commands)
flag_suspicious(commands, error: error)
Console1984.supervisor.exit_irb
ensure
run_as_system { session_logger.after_executing commands }
Expand Down Expand Up @@ -70,11 +71,7 @@ def validate_command(command)
end

def from_irb?(backtrace)
executing_user_command? && backtrace.find do |line|
line_from_irb = line =~ /^[^\/]/
break if !(line =~ /console1984\/lib/ || line_from_irb)
line_from_irb
end
executing_user_command? && backtrace.first.to_s =~ /^[^\/]/
end

private
Expand All @@ -86,9 +83,10 @@ def build_command_validator
Console1984::CommandValidator.from_config(Console1984.protections_config.validations)
end

def flag_suspicious(commands)
def flag_suspicious(commands, error: nil)
puts "Forbidden command attempted: #{commands.join("\n")}"
run_as_system { session_logger.suspicious_commands_attempted commands }
@last_suspicious_command_error = error
nil
end

Expand Down
2 changes: 1 addition & 1 deletion lib/console1984/ext/core/object.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ module Console1984::Ext::Core::Object

class_methods do
def const_get(*arguments)
if Console1984.command_executor.executing_user_command?
if Console1984.command_executor.from_irb?(caller)
begin
# To validate if it's an invalid constant, we try to declare a class with it.
# We essentially leverage Console1984::CommandValidator::ForbiddenReopeningValidation here:
Expand Down
24 changes: 24 additions & 0 deletions lib/console1984/ext/core/string.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Prevents loading forbidden classes dynamically.
#
# See extension to +Console1984::Ext::Core::Object#const_get+.
module Console1984::Ext::Core::String
extend ActiveSupport::Concern

include Console1984::Freezeable
self.prevent_instance_data_manipulation_after_freezing = false

def constantize
if Console1984.command_executor.from_irb?(caller)
begin
Console1984.command_executor.validate_command("class #{self}; end")
super
rescue Console1984::Errors::ForbiddenCommandAttempted
raise
rescue StandardError
super
end
else
super
end
end
end
9 changes: 9 additions & 0 deletions lib/console1984/ext/irb/commands.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,13 @@ def decrypt!
def encrypt!
shield.enable_protected_mode
end

# This returns the last error that prevented a command execution in the console
# or nil if there isn't any.
#
# This is meant for internal usage when debugging legit commands that are wrongly
# prevented.
def _console_last_suspicious_command_error
Console1984.command_executor.last_suspicious_command_error
end
end
1 change: 1 addition & 0 deletions lib/console1984/shield.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ def extend_irb
def extend_core_ruby
Object.prepend Console1984::Ext::Core::Object
Module.prepend Console1984::Ext::Core::Module
String.prepend Console1984::Ext::Core::String
end

def extend_sockets
Expand Down

0 comments on commit b8f050d

Please sign in to comment.