I discovered a command injection vulnerability in SaltStack's Salt that allows privilege escalation using malicious filenames on a minion when the master calls
snapper.diff. But... I was too slow! SaltStack had already fixed it almost a month earlier, and the source code I was looking at was out of date.
As this is already fixed and pretty trivial to exploit, this post is going to be pretty brief compared to the previous posts I've done on SaltStack vulnerabilities (CVE-2020-28243 and CVE-2020-28243 (2)).
- Snapper is installed and configured on the minion (this requires a filesystem such as btrfs)
- Master uses the snapper module to request a diff on a minion
When the snapper module performs a diff between a snapshot and the current state, it first checks each file to see if it is a text file using the file command. But because the filename is passed directly into
os.popen it can be easily be abused by anyone able to create a file.
The exploit is trivial to set up; we create a text file with a filename that contains a command injection. Here we will use
$() to create a subshell:
Now the exploit is ready. Now we wait for the master to request a diff from the minion. This can be done using the following Salt command:
salt '*' snapper.diff
Lets see it in action:
Now that we've got a proof of concept working, we can get full remote command execution using some base64'ing like so:
The fix SaltStack went for replaces the
subprocess.run and now passes a list of arguments to prevent command injection. The filename passed into this can only ever be a single argument, and subshells are not supported by default in
Note: It appears that this security fix actually broke the functionality as
subprocess.STDOUT seems to cause an error:
OSError: [Errno 9] Bad file descriptor. It should probably be replaced with
subprocess.PIPE. I raised this as an issue here.
SaltStack detected this code as a potential vulnerability using a Bandit scan and fixed this almost a month before I found it. This was all done as part of a larger pull request where several potential vulnerabilities were fixed.
It's great to see SaltStack taking a proactive move to reduce their attack surface. However, in all my attempts to contact SaltStack about this vulnerability I was ignored, presumably they don't care as it was already fixed. Given the exploit was in the code base for almost 5 years I think it was important enough to warrant a CVE-ID.