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_category bất kỳ chuỗi nào, không whitelist enum.
  • Unsafe query construction: quarantine_notify.py (~line 79) xây SQL bằng query %% (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ínhChi tiết
CVE IDCVE-2026-40871
TypeSecond-Order SQL Injection + Sensitive Data Exposure
SeverityHigh (disclosure chưa kèm CVSS numeric)
Entry pointPOST /api/v1/add/mailbox
Tham số bị injectquarantine_category
Sinkquarantine_notify.py ~ line 79
Kỹ thuật sinkPython % string formatting thay vì parameterized query
TriggerQuarantine event trên mailbox bị poison
Auth yêu cầuAPI key hợp lệ (authenticated)
Exfil channelEmail 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ế

  1. Attacker lấy API key — ví dụ chain với XSS trong SOGo webmail để đánh cắp cookie/API key của admin.
  2. Gọi POST /api/v1/add/mailbox với quarantine_category chứa payload SQL (UNION SELECT hoặc subquery bơm kết quả vào cột text).
  3. Đợi hoặc chủ động gửi mail bẩn để trigger quarantine.
  4. quarantine_notify.py đọc quarantine_category, ghép thẳng vào query, SQL injected thực thi.
  5. 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 mailbox cho giá trị quarantine_category khá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_notify cho query có keyword UNION/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.py sang 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.