Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Apply escaping args to other command shells #19745

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions lib/metasploit/framework/ssh/platform.rb
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@ def self.get_platform_info(ssh_socket, timeout: 10)
info
end

def self.is_posix(platform)
return ['unifi','linux','osx','solaris','bsd','hpux','aix'].include?(platform)
end

def self.get_platform_from_info(info)
case info
when /unifi\.version|UniFiSecurityGateway/i # Ubiquiti Unifi. uname -a is left in, so we got to pull before Linux
Expand Down
2 changes: 1 addition & 1 deletion lib/msf/base/sessions/ssh_command_shell_bind.rb
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ def bootstrap(datastore = {}, handler = nil)
@platform = Metasploit::Framework::Ssh::Platform.get_platform(ssh_connection)
if @platform == 'windows'
extend(Msf::Sessions::WindowsEscaping)
else
elsif Metasploit::Framework::Ssh::Platform.is_posix(@platform)
extend(Msf::Sessions::UnixEscaping)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks much better! Maybe one small additional detail would be adding else branch with some message/exception to cover those cases where the platform is not posix - but otherwise, it's all great.

end

Expand Down
36 changes: 16 additions & 20 deletions lib/msf/base/sessions/windows_escaping.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,38 +28,34 @@ def escape_cmd(executable)
# to cmd.exe, whereas this is expected to be passed directly to the Win32 API, anticipating that it
# will in turn be interpreted by CommandLineToArgvW.
def argv_to_commandline(args)
escaped_args = args.map do |arg|
escape_arg(arg)
end
escaped_args = args.map { |arg| escape_arg(arg) }

escaped_args.join(' ')
end

# Escape an individual argument per Windows shell rules
# @param arg [String] Shell argument
def escape_arg(arg)
needs_quoting = space_chars.any? do |char|
arg.include?(char)
end
needs_quoting = space_chars.any? { |char| arg.include?(char) }

# Fix the weird behaviour when backslashes are treated differently when immediately prior to a double-quote
# We need to send double the number of backslashes to make it work as expected
# See: https://learn.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-commandlinetoargvw#remarks
arg = arg.gsub(/(\\*)"/, '\\1\\1"')
# Fix the weird behaviour when backslashes are treated differently when immediately prior to a double-quote
# We need to send double the number of backslashes to make it work as expected
# See: https://learn.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-commandlinetoargvw#remarks
arg = arg.gsub(/(\\*)"/, '\\1\\1"')

# Quotes need to be escaped
arg = arg.gsub('"', '\\"')
# Quotes need to be escaped
arg = arg.gsub('"', '\\"')

if needs_quoting
# At the end of the argument, we're about to add another quote - so any backslashes need to be doubled here too
arg = arg.gsub(/(\\*)$/, '\\1\\1')
arg = "\"#{arg}\""
end
if needs_quoting
# At the end of the argument, we're about to add another quote - so any backslashes need to be doubled here too
arg = arg.gsub(/(\\*)$/, '\\1\\1')
arg = "\"#{arg}\""
end

# Empty string needs to be coerced to have a value
arg = '""' if arg == ''
# Empty string needs to be coerced to have a value
arg = '""' if arg == ''

arg
arg
end

# Convert the executable and argument array to a command that can be run in this command shell
Expand Down
Loading