Zammad is a widely deployed open-source helpdesk and customer support ticketing platform, particularly popular in Europe and among German-speaking organizations. As a customer support hub, Zammad contains high-value data: all customer and internal support tickets with full conversation history, customer contact information including email and phone, LDAP/Active Directory bind credentials, and the passwords for all configured email channels (IMAP/SMTP). Key assessment areas: the Zammad REST API token provides full ticket and user enumeration; LDAP bind credentials are stored in the settings database table; email channel IMAP and SMTP passwords are stored in the channels table; the Rails secret_key_base in Zammad configuration enables session cookie forgery; and the Elasticsearch backend may be exposed without authentication in default configurations. This guide covers systematic Zammad security assessment.
# Zammad — API token authentication and user enumeration
ZAMMAD_URL="https://zammad.example.com"
API_TOKEN="your-zammad-api-token"
# Test API access — verify token and current user
curl -s "${ZAMMAD_URL}/api/v1/users/me" \
-H "Authorization: Token token=${API_TOKEN}" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
print(f'Current user: {d.get(\"login\")} name={d.get(\"firstname\")} {d.get(\"lastname\")}')
print(f'Role IDs: {d.get(\"role_ids\")} (1=admin, 2=agent)')
print(f'Email: {d.get(\"email\")}')
" 2>/dev/null
# Enumerate all users — customers and agents
curl -s "${ZAMMAD_URL}/api/v1/users?expand=true&per_page=200" \
-H "Authorization: Token token=${API_TOKEN}" 2>/dev/null | python3 -c "
import json,sys
users=json.load(sys.stdin)
print(f'Users: {len(users)}')
for u in users:
roles = u.get('role_ids',[])
print(f' [{u.get(\"id\")}] {u.get(\"login\")} email={u.get(\"email\")} roles={roles} org={u.get(\"organization_id\")}')
" 2>/dev/null
# Enumerate all organizations — customer company list
curl -s "${ZAMMAD_URL}/api/v1/organizations?per_page=200" \
-H "Authorization: Token token=${API_TOKEN}" 2>/dev/null | python3 -c "
import json,sys
orgs=json.load(sys.stdin)
print(f'Organizations: {len(orgs)}')
for o in orgs[:20]:
print(f' [{o.get(\"id\")}] {o.get(\"name\")} domain={o.get(\"domain\")} shared={o.get(\"shared\")}')
" 2>/dev/null
# Zammad ticket enumeration — complete support history
ZAMMAD_URL="https://zammad.example.com"
API_TOKEN="your-zammad-api-token"
# List all tickets with full details
curl -s "${ZAMMAD_URL}/api/v1/tickets?expand=true&per_page=100" \
-H "Authorization: Token token=${API_TOKEN}" 2>/dev/null | python3 -c "
import json,sys
tickets=json.load(sys.stdin)
print(f'Tickets: {len(tickets)}')
for t in tickets[:20]:
print(f' [{t.get(\"id\")}] {t.get(\"title\")} state={t.get(\"state\")} priority={t.get(\"priority\")}')
print(f' Customer: {t.get(\"customer_id\")} org={t.get(\"organization_id\")} group={t.get(\"group\")}')
print(f' Created: {t.get(\"created_at\")} updated={t.get(\"updated_at\")}')
" 2>/dev/null
# Get ticket articles (actual message content)
TICKET_ID="1"
curl -s "${ZAMMAD_URL}/api/v1/ticket_articles/by_ticket/${TICKET_ID}?expand=true" \
-H "Authorization: Token token=${API_TOKEN}" 2>/dev/null | python3 -c "
import json,sys
articles=json.load(sys.stdin)
print(f'Ticket articles: {len(articles)}')
for a in articles:
print(f' from={a.get(\"from\")} to={a.get(\"to\")} type={a.get(\"type\")}')
print(f' Body: {a.get(\"body\",\"\")[:150]}')
" 2>/dev/null
# Zammad credential extraction — LDAP, email channels, Rails secret
# Zammad stores sensitive config in PostgreSQL settings and channels tables
# Rails application configuration — secret_key_base
grep -r "secret_key_base\|database_password" \
/etc/zammad/ /opt/zammad/config/ 2>/dev/null | head -20
# secret_key_base — signs Rails session cookies; leakage enables session forgery
# Direct database access — LDAP and email channel credentials
PGPASSWORD="zammad_db_password" psql -U zammad -d zammad 2>/dev/null << 'EOF'
-- LDAP bind credentials
SELECT name, preferences
FROM settings
WHERE name IN ('ldap_config', 'user_show_password_login', 'auth_ldap');
-- Email channel credentials (IMAP/SMTP passwords)
SELECT area, options
FROM channels
WHERE area IN ('Email::Account', 'Email::Outbound');
EOF
# Reveals LDAP bind_dn, bind_pw for Active Directory integration
# Reveals IMAP passwords for all configured mailboxes
# Reveals SMTP credentials for outbound email delivery
# Zammad API — list configured channels (admin token required)
curl -s "${ZAMMAD_URL}/api/v1/channels?expand=true" \
-H "Authorization: Token token=${API_TOKEN}" 2>/dev/null | python3 -c "
import json,sys
channels=json.load(sys.stdin)
for c in channels:
opts = c.get('options',{}) or {}
inbound = opts.get('inbound',{}) or {}
print(f'Channel: {c.get(\"area\")} adapter={inbound.get(\"adapter\")} host={inbound.get(\"host\")} user={inbound.get(\"user\")}')
" 2>/dev/null
| Security Test | Method | Risk |
|---|---|---|
| API token ticket and customer data enumeration | GET /api/v1/tickets and /api/v1/users with API token — returns all support tickets with customer information, conversation history, and contact details; complete CRM data exposure including organization relationships | Critical |
| LDAP bind credential extraction | PostgreSQL query on settings table — LDAP bind_pw for Active Directory integration; service account credentials with read access to all AD users, groups, and organizational units | Critical |
| Email channel password extraction | PostgreSQL query on channels table — IMAP and SMTP passwords for all configured mailboxes; enables reading all incoming support emails and sending emails as the Zammad system account | High |
| Rails secret_key_base extraction for session forgery | Read /etc/zammad/ or deployment config files — secret_key_base enables crafting valid Rails session cookies for any user, bypassing Zammad authentication entirely including admin accounts | Critical |
| Ticket article content disclosure | GET /api/v1/ticket_articles/by_ticket/{id} — returns full conversation bodies including customer-submitted information that frequently contains passwords, license keys, and sensitive system data shared with support | High |
Ironimo tests Zammad deployments for API token ticket and customer data enumeration, LDAP bind credential extraction from the settings table, email channel IMAP/SMTP password access, Rails secret_key_base extraction for session forgery, Elasticsearch unauthenticated backend access, webhook configuration credential disclosure, admin API channel enumeration, and two-factor authentication enforcement verification.
Start free scan