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 2 commits into
base: master
Choose a base branch
from

Conversation

smashery
Copy link
Contributor

This adds escape_args method to all CommandShells, and more specifically, finds the appropriate OS escaping routines for an SSH server (usually Unix presumably, but possibly Windows).

Resolves #19636

Verification

  • Start msfconsole
  • auxiliary/scanner/ssh/ssh_login
  • Create a session on a target host
  • Launch a post exploitation module (just to set up irb correctly)
  • For example: use netfilter_priv_esc_ipv4
  • set session 1 (again to set up irb)
  • irb
  • `write_file('/tmp/test','data')
  • write_file('/tmp/test "quotes"', 'hi')
  • Verify that it successfully writes the files, correctly escaping the quotes (previously it would fail with the escape_arg error)

@adfoster-r7
Copy link
Contributor

adfoster-r7 commented Dec 18, 2024

Not a blocker to this PR; Looks like it'd be worth us expanding our acceptance tests to include ssh modules+sessions in the future 👍

@msutovsky-r7 msutovsky-r7 self-assigned this Dec 18, 2024
Comment on lines +241 to +245
if @platform == 'windows'
extend(Msf::Sessions::WindowsEscaping)
else
extend(Msf::Sessions::UnixEscaping)
end
Copy link
Contributor

Choose a reason for hiding this comment

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

Are you sure there are no other possibilities besides Windows and Unix wrt. shell escaping?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

From https://github.com/rapid7/metasploit-framework/blob/master/lib/metasploit/framework/ssh/platform.rb#L97-L132, I'm really not all that familiar with what exactly to expect shell-escaping-wise when you get (for example) an "arista" shell. If it's some custom shell completely unrelated to anything POSIX, then any of the behaviour that uses escape_arg (such as uploading files or launching processes) would be useless anyway and would need its entirely new implementation.

In those cases, I'm not sure what the best default would be. The alternative I guess would be better in those unknown cases to just not extend the object, and do no escaping.

Copy link
Contributor

Choose a reason for hiding this comment

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

From my very brief analysis, the current state should easily cover all platforms except Cisco ios, Juniper, Mikrotik, Arista and vcenter - I'm not 100% sure how those shells work when it comes to character escaping. So the options are: add else for all above mentioned and just implement escaping for them later on with more thorough analysis or ignore it, hope for best and add at least else block for Unknown platform. We will probably have to create/extend tests for SSH sessions (though I'm not very familiar how they are implemented now, but I don't expect such cases are covered there).

lib/msf/base/sessions/unix_escaping.rb Outdated Show resolved Hide resolved
Co-authored-by: Julien Voisin <[email protected]>
Copy link
Contributor

@msutovsky-r7 msutovsky-r7 left a comment

Choose a reason for hiding this comment

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

Hi @smashery, I added some comments.

# will in turn be interpreted by CommandLineToArgvW.
def argv_to_commandline(args)
escaped_args = args.map do |arg|
escape_arg(arg)
Copy link
Contributor

Choose a reason for hiding this comment

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

More condensed form

Suggested change
escape_arg(arg)
escaped_args = args.map { |arg| escape_arg(arg) }

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

Choose a reason for hiding this comment

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

More condensed form

Suggested change
needs_quoting = space_chars.any? do |char|
needs_quoting = space_chars.any? { |char| arg.include?(char) }

Comment on lines +241 to +245
if @platform == 'windows'
extend(Msf::Sessions::WindowsEscaping)
else
extend(Msf::Sessions::UnixEscaping)
end
Copy link
Contributor

Choose a reason for hiding this comment

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

From my very brief analysis, the current state should easily cover all platforms except Cisco ios, Juniper, Mikrotik, Arista and vcenter - I'm not 100% sure how those shells work when it comes to character escaping. So the options are: add else for all above mentioned and just implement escaping for them later on with more thorough analysis or ignore it, hope for best and add at least else block for Unknown platform. We will probably have to create/extend tests for SSH sessions (though I'm not very familiar how they are implemented now, but I don't expect such cases are covered there).

@msutovsky-r7 msutovsky-r7 removed their assignment Dec 28, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Status: In Progress
Development

Successfully merging this pull request may close these issues.

NoMethodError undefined method `escape_arg'
4 participants