- Lỗ hổng SQL injection bậc hai trong Mailcow API cho phép attenkiếm API key trích xuất credential admin qua email notification.
- Payload lưu sạch trong DB, chỉ fire khi job quarantine_notify.py chạy — né WAF và scanner black-box.
TL;DR
CVE-2026-40871 là lỗ hổng second-order SQL injection trong Mailcow (self-hosted mail server chạy Docker). Điểm inject là field quarantine_category của endpoint POST /api/v1/add/mailbox. Payload lưu nguyên văn vào database, chỉ thực thi khi job quarantine_notify.py chạy và ghép chuỗi vào SQL bằng Python %-format. Kết quả: attacker có API key có thể chạy SQL tuỳ ý, đánh cắp credential admin và exfiltrate qua email notification. Cần API key hợp lệ — không phải pre-auth RCE — nhưng dễ chain với XSS trong SOGo webmail để lấy key.
Có gì mới
Disclosure được researcher lukehebe công bố trên GitHub và lan truyền qua tweet của @NullSecurityX. Ba lỗi gốc chồng lên nhau:
- Unvalidated input: API nhận
quarantine_categorybất kỳ chuỗi nào, không whitelist enum. - Unsafe query construction:
quarantine_notify.py(~line 79) xây SQL bằngquery %% (value,)thay vì prepared statement. - Delayed execution: payload sống trong DB đến khi một mail rơi vào quarantine, lúc đó consumer script mới đọc ra và inject.
Vì sao nó quan trọng
Second-order SQLi khó bắt hơn first-order rất nhiều. WAF xem request tạo mailbox là data hợp lệ; scanner black-box như sqlmap không thấy payload reflect ra response. Blue-team chỉ phát hiện khi phân tích log của worker script — thứ ít ai monitor bằng API gateway.
Trên thực tế, Mailcow phổ biến với indie hacker, SMB và self-hoster muốn thoát Google Workspace. Một instance bị dính nghĩa là toàn bộ mailbox, password hash, alias, và domain config có thể rò rỉ qua chính kênh email notification mà quản trị viên coi là "nội bộ".
Fact kỹ thuật
| Thuộc tính | Chi tiết |
|---|---|
| CVE ID | CVE-2026-40871 |
| Type | Second-Order SQL Injection + Sensitive Data Exposure |
| Severity | High (disclosure chưa kèm CVSS numeric) |
| Entry point | POST /api/v1/add/mailbox |
| Tham số bị inject | quarantine_category |
| Sink | quarantine_notify.py ~ line 79 |
| Kỹ thuật sink | Python % string formatting thay vì parameterized query |
| Trigger | Quarantine event trên mailbox bị poison |
| Auth yêu cầu | API key hợp lệ (authenticated) |
| Exfil channel | Email notification gửi ra ngoài |
So với CVE-2025-53909
Năm ngoái Mailcow đã dính CVE-2025-53909 — Server-Side Template Injection trong template của quarantine/quota alert. Cả hai đều liên quan hệ thống notification, nhưng:
- CVE-2025-53909 ở tầng render template (Jinja-like), payload chạy trong Python context.
- CVE-2026-40871 ở tầng SQL, payload chạy trong DB engine (MariaDB/MySQL) với quyền của DB user Mailcow.
Pattern lặp lại: mailcow trust data đã "qua API" nên bỏ escape ở consumer. Đây là bài học cho mọi kiến trúc event-driven có producer/consumer tách biệt.
Chuỗi tấn công thực tế
- Attacker lấy API key — ví dụ chain với XSS trong SOGo webmail để đánh cắp cookie/API key của admin.
- Gọi
POST /api/v1/add/mailboxvớiquarantine_categorychứa payload SQL (UNION SELECT hoặc subquery bơm kết quả vào cột text). - Đợi hoặc chủ động gửi mail bẩn để trigger quarantine.
quarantine_notify.pyđọcquarantine_category, ghép thẳng vào query, SQL injected thực thi.- Kết quả query (credential hash, secret, domain key) nhét vào nội dung email notification, gửi ra address attacker kiểm soát.
Limitations & pricing
Lỗ hổng không phải pre-auth — cần API key. Disclosure chưa công bố PoC payload cụ thể, chưa có CVSS chính thức, chưa có version range, và chưa có patch release tại thời điểm viết. Mailcow repo chưa ra security advisory riêng cho CVE này.
Mitigation tạm thời
- Rotate toàn bộ API key và restrict IP source cho
/api/v1/qua reverse proxy. - Disable API nếu không dùng tự động hoá (Mailcow UI vẫn chạy bình thường).
- Audit bảng
mailboxcho giá trịquarantine_categorykhác 4 enum hợp lệ (reject,add_header,cc,none) — bất cứ chuỗi bất thường nào đều là cờ đỏ. - Bật MySQL general log tạm thời, grep
quarantine_notifycho query có keywordUNION/SELECT/INTO OUTFILE. - Ai đang chạy SOGo: update SOGo + chặn inline script để cắt đường lấy API key.
Tiếp theo
Maintainer Mailcow nhiều khả năng sẽ:
- Chuyển
quarantine_notify.pysang prepared statement của MySQLdb connector. - Thêm whitelist enum cho
quarantine_categoryở API validator. - Audit các worker khác (
clean.py,quota_notify.py) cho cùng pattern%-format SQL.
Nếu bạn tự host Mailcow, theo dõi mailcow-dockerized cho patch release và sub thêm mailcow.email/categories/cve.
Nguồn: lukehebe disclosure, @NullSecurityX.

