OffSec Proving Grounds Twiggy — SaltStack CVE-2020-11651 RCE
In this Art of Vector walkthrough, we take a lab machine called Twiggy from a blank terminal to full root access — starting with reconnaissance, then pivoting to an exposed SaltStack service and chaining CVE-2020-11651 and CVE-2020-11652 into remote code execution.
Watch the companion video here:
https://youtu.be/QBcr0krhKhE?si=dKIfQTYaX1E-rjUN
This write-up follows the actual flow of the recorded video: recon first, then web enumeration, then the shift toward SaltStack once the exposed management plane becomes the strongest lead.
Lab only. All testing was performed in an authorized training environment. Never run these techniques against systems you do not own or do not have explicit written permission to assess.
Summary
Twiggy looks ordinary at first glance. There is SSH, HTTP, and a web app that is worth checking. But the winning path is not in the CMS. The real signal is the pair of SaltStack ZeroMQ ports, 4505 and 4506, plus the Salt API on 8000.
Once the Salt version is identified as 3000-1, the attack chain becomes clear. Public research on the 2020 SaltStack bugs points to an authentication bypass and path traversal combination that can be turned into remote code execution on the master. In the lab, that ends with full root.
Enumeration
Nmap
The machine opens with a straightforward scan. The first important observation is not just that HTTP is present, but that the host also exposes 4505, 4506, and 8000.
sudo nmap -p- -A 192.168.233.62
The important ports are:
22/tcp open ssh
80/tcp open http
4505/tcp open zmtp
4506/tcp open zmtp
8000/tcp open http
That combination is where the machine shifts from "probably a web app target" to "possibly a SaltStack target."
Service analysis
Once the ports are visible, the next step is to stop treating them equally.
Port 80 points to Mezzanine on nginx. That is worth checking first.
searchsploit mezzanine
In this case, the public findings around Mezzanine do not give us the path we need for initial access.
Ports 4505 and 4506 are more unusual. Service detection identifies them as ZeroMQ, which is the clue that points back to SaltStack.
Port 8000 closes the loop by exposing the Salt API. In the video, this is the moment where the attack path becomes clear.
curl http://192.168.233.62:8000 -v
The key line is the upstream header:
X-Upstream: salt-api/3000-1
Web enumeration
The web path is still tested properly before committing to Salt. Mezzanine is reviewed, searchsploit is checked, and directory brute-forcing is used to make sure there is not an easier route hiding behind the site.
gobuster dir -u http://192.168.233.62/ \
-w /usr/share/seclists/Discovery/Web-Content/raft-large-directories.txt
Nothing on the web side matches the leverage of the exposed management service. The web app is the distraction, not the root cause.
Why SaltStack became the real path
Port 8000 gives the clearest confirmation. The API response exposes a SaltStack header that identifies the target as salt-api/3000-1.
That version sits in the vulnerable window for the 2020 SaltStack issues. In practice, the pair matters because one weakness removes the trust boundary and the other expands access on the master. Together, they turn exposed management ports into a path to high-impact execution.
The important idea is not the exploit script itself. The important idea is the chain:
- ZeroMQ ports visible on the host
- Salt API reachable
- Vulnerable version exposed
- Management plane reachable from the attacker network
Once those conditions line up, the host is already in trouble.
Exploitation path
Once salt-api/3000-1 is exposed, the path forward is SaltStack research around CVE-2020-11651 and CVE-2020-11652.
The video follows a practical sequence:
- confirm the Salt version
- pull a public PoC
- fix the local environment
- validate that the master is vulnerable
- move from file access to
root
Python environment
On Kali, the first hurdle is usually the local Python environment, not the target.
python3 -m venv myvenv
source myvenv/bin/activate
pip install salt
That setup step matters because modern Kali blocks the old habit of dropping dependencies straight into the system interpreter.
Proving impact
The first useful move is proving that the target is vulnerable and that file access works.
python3 exploit.py --master 192.168.233.62 --read /etc/passwd
In the video, this is the point where the attack becomes real. The exploit confirms that the master is online, vulnerable, and accessible enough to read sensitive files directly from the target.
Moving to root
Reading files proves impact, but the goal is shell access. The route used in the walkthrough is to create a password hash, craft a new privileged entry, write it into /etc/passwd, and then log in over SSH.
Generate a password hash:
openssl passwd -1 password123
Prepare a new passwd file with the added privileged user entry, then upload it:
python3 exploit.py --master 192.168.233.62 \
--upload-src passwd \
--upload-dest ../../../../../../etc/passwd
Once the file write succeeds, log in:
ssh aov@192.168.233.62
id
whoami
In the walkthrough, that final step lands directly in a root session.
Root outcome
What matters at the end is not the exploit script itself, but the result: exposed Salt services gave the attacker a path to administrative control of the machine.
That is why Twiggy works as a teaching machine. The chain is clean:
- recon finds the unusual ports
- service analysis identifies Salt
- web enumeration rules out the obvious path
- version confirmation ties the host to known Salt flaws
- exploitation turns exposed infrastructure into
root
Why this machine is a good lesson
Twiggy is not memorable because it has a flashy exploit. It is memorable because it rewards good enumeration.
If you stop at the CMS, you waste time. If you scan shallowly, you may miss the ports that matter. If you see 4505 and 4506 and do not recognize them, you miss the entire attack path.
This is why recon matters so much in practice. A fast win usually starts with noticing the one service that should not be there.
Defensive takeaways
If you run Salt anywhere in your environment, the lessons are straightforward:
- Patch beyond the vulnerable versions immediately.
- Never leave
4505and4506exposed to untrusted networks. - Treat an exposed Salt master as a serious incident, not a routine misconfiguration.
- Remember that the control plane can be more dangerous than the application sitting in front of it.
References
- CVE-2020-11651 (NVD)
- CVE-2020-11652 (NVD)
- Exploit-DB 48421
- SaltStack vulnerabilities actively exploited
Unauthorized access is illegal. This write-up is for education and authorized lab work only.
