Security – Postfix sender acces restriction – Security breach

postfixSecuritysmtp

We encounter security problems with our mail server and would like some advice.

The story behind it

On our mail server (Postfix 2.9.6 + Dovecot 2.1.7) we would like to be able to create restricted email accounts. Those accounts (used by the trainees) would be able to send/receive emails to/from the local domains only (for security reasons we don't want them to be able to send or receive emails to other mail servers). To make it simple, we created a specific sub-domain for the restricted email accounts.

On our infrastructure, all email accounts are LDAP based, the config files are included hereunder.

What we did

In postfix, it is possible to create restriction rules in file /etc/postfix/main.cf and so we added rules:

check_sender_access ldap:/etc/postfix/ldap_restricted_senders.cf
check_recipient_access ldap:/etc/postfix/ldap_restricted_recipients.cf

to section:

smtpd_recipient_restrictions

For sure, following lines were also added :

smtpd_restriction_classes =
  local_only,
  insiders_only

local_only = check_recipient_access ldap:/etc/postfix/ldap_virtual_domains_restrict.cf, reject
insiders_only = check_sender_access ldap:/etc/postfix/ldap_virtual_domains_restrict.cf, reject

Content of /etc/postfix/ldap_restricted_senders.cf is:

bind = yes
bind_dn = uid=postfix,ou=service,dc=example,dc=com
bind_pw = *******
server_host = ldap://127.0.0.1:389
search_base = ou=domain,dc=example,dc=com
query_filter = (&(ObjectClass=DNSDomain)(dc=%s))
result_attribute = description

This returns "ok" when the domain is allowed to send emails outside.


Content of /etc/postfix/ldap_restricted_recipients.cf is:

bind = yes
bind_dn = uid=postfix,ou=service,dc=example,dc=com
bind_pw = ******
server_host = ldap://127.0.0.1:389
search_base = ou=domain,dc=example,dc=com
query_filter = (&(description=local_only)(dc=%s))
result_attribute = description
result_filter = insiders_only

This returns "insiders_only" when the domain can be reached by only local domains.


Content of /etc/postfix/ldap_virtual_domains_restrict.cf is:

bind = yes
bind_dn = uid=postfix,ou=service,dc=example,dc=com
bind_pw = ******
server_host = ldap://127.0.0.1:389
search_base = ou=domain,dc=example,dc=com
query_filter = (&(ObjectClass=dNSDomain)(dc=%s))
result_attribute = dc
result_filter = OK

This returns "ok" when the domain is local (can send emails to the restricted sub-domain).


For more precision, the postfix smtpd_recipient_restrictions section contains:

smtpd_recipient_restrictions =
  permit_mynetworks,
  reject_sender_login_mismatch
  check_sender_access ldap:/etc/postfix/ldap_restricted_senders.cf
  check_recipient_access ldap:/etc/postfix/ldap_restricted_recipients.cf
  permit_sasl_authenticated,
  reject_non_fqdn_hostname,
  reject_non_fqdn_sender,
  reject_non_fqdn_recipient,
  reject_unauth_destination,
  reject_unauth_pipelining,
  reject_invalid_hostname,
  check_policy_service unix:private/policy-spf

This works fine in the sens that all emails from the subdomain can send emails only to other local domains and can only receive emails from local domains.

BUT…

Since we enable this we noticed that people could use the mail server to send SPAM (so we temporary removed it).

We noticed the problem because the log file /var/log/mail.log contained lines like:

Jul 22 11:59:24 mail postfix/qmgr[366]: F342F42AE4: from=<mnd0gb8@example.com>, size=2171, nrcpt=11 (queue active)
Jul 22 11:59:24 mail postfix/smtp[382]: 1344D42ACC: to=<iraci@*******>, relay=127.0.0.1[127.0.0.1]:10024, delay=1197348, delays=1197334/12/0.17/2.2, dsn=2.0.0, status=sent (250 2.0.0 from MTA(smtp:[127.0.0.1]:10025): 250 2.0.0 Ok: queued as F342F42AE4)
Jul 22 11:59:24 mail postfix/smtp[382]: 1344D42ACC: to=<hugocesar_007@*******>, relay=127.0.0.1[127.0.0.1]:10024, delay=1197348, delays=1197334/12/0.17/2.2, dsn=2.0.0, status=sent (250 2.0.0 from MTA(smtp:[127.0.0.1]:10025): 250 2.0.0 Ok: queued as F342F42AE4)
Jul 22 11:59:24 mail postfix/smtp[382]: 1344D42ACC: to=<reginadanielian@*******>, relay=127.0.0.1[127.0.0.1]:10024, delay=1197348, delays=1197334/12/0.17/2.2, dsn=2.0.0, status=sent (250 2.0.0 from MTA(smtp:[127.0.0.1]:10025): 250 2.0.0 Ok: queued as F342F42AE4)
Jul 22 11:59:24 mail postfix/smtp[382]: 1344D42ACC: to=<thais_jp@*******>, relay=127.0.0.1[127.0.0.1]:10024, delay=1197348, delays=1197334/12/0.17/2.2, dsn=2.0.0, status=sent (250 2.0.0 from MTA(smtp:[127.0.0.1]:10025): 250 2.0.0 Ok: queued as F342F42AE4)
Jul 22 11:59:24 mail postfix/smtp[382]: 1344D42ACC: to=<tropicalfmcomerciais@*******>, relay=127.0.0.1[127.0.0.1]:10024, delay=1197348, delays=1197334/12/0.17/2.2, dsn=2.0.0, status=sent (250 2.0.0 from MTA(smtp:[127.0.0.1]:10025): 250 2.0.0 Ok: queued as F342F42AE4)
Jul 22 11:59:24 mail postfix/smtp[382]: 1344D42ACC: to=<valeria.x@*******>, relay=127.0.0.1[127.0.0.1]:10024, delay=1197348, delays=1197334/12/0.17/2.2, dsn=2.0.0, status=sent (250 2.0.0 from MTA(smtp:[127.0.0.1]:10025): 250 2.0.0 Ok: queued as F342F42AE4)
Jul 22 11:59:24 mail postfix/smtp[382]: 1344D42ACC: to=<veloso1071@*******>, relay=127.0.0.1[127.0.0.1]:10024, delay=1197348, delays=1197334/12/0.17/2.2, dsn=2.0.0, status=sent (250 2.0.0 from MTA(smtp:[127.0.0.1]:10025): 250 2.0.0 Ok: queued as F342F42AE4)
Jul 22 11:59:24 mail postfix/smtp[382]: 1344D42ACC: to=<termopiso@*******>, relay=127.0.0.1[127.0.0.1]:10024, delay=1197348, delays=1197334/12/0.17/2.2, dsn=2.0.0, status=sent (250 2.0.0 from MTA(smtp:[127.0.0.1]:10025): 250 2.0.0 Ok: queued as F342F42AE4)
Jul 22 11:59:24 mail postfix/smtp[382]: 1344D42ACC: to=<rafaelpm84@*******>, relay=127.0.0.1[127.0.0.1]:10024, delay=1197348, delays=1197334/12/0.17/2.2, dsn=2.0.0, status=sent (250 2.0.0 from MTA(smtp:[127.0.0.1]:10025): 250 2.0.0 Ok: queued as F342F42AE4)
Jul 22 11:59:24 mail postfix/smtp[382]: 1344D42ACC: to=<vanessyca@*******>, relay=127.0.0.1[127.0.0.1]:10024, delay=1197348, delays=1197334/12/0.17/2.2, dsn=2.0.0, status=sent (250 2.0.0 from MTA(smtp:[127.0.0.1]:10025): 250 2.0.0 Ok: queued as F342F42AE4)
Jul 22 11:59:24 mail postfix/qmgr[366]: 1344D42ACC: removed

What we suppose

As the restriction we setup matches only the domain (for the sender) someone was using our server as relay with with emails where sender was forged to match anything@example.com and would so be accepted.

We are going to change the settings to make the rule match the whole email instead but we are not sure that it will prevent the spoofing.

What do you think about it? Have we done something wrong ? Is there another way (or functionality) to have such a restriction ?

PS: We can post more information if needed

Best Answer

As the restriction we setup matches only the domain (for the sender) someone was using our server as relay with with emails where sender was forged to match anything@example.com and would so be accepted.

Yes, this is caused by this restriction in smtpd_recipient_restrictions

check_sender_access ldap:/etc/postfix/ldap_restricted_senders.cf

You said above, this query will return "OK", when sender allowed to send outgoing email. This means postfix will allow the email and bypass the restriction below it

  check_recipient_access ldap:/etc/postfix/ldap_restricted_recipients.cf
  permit_sasl_authenticated,
  reject_non_fqdn_hostname,
  reject_non_fqdn_sender,
  reject_non_fqdn_recipient,
  reject_unauth_destination,
  reject_unauth_pipelining,
  reject_invalid_hostname,
  check_policy_service unix:private/policy-spf

Perhaps the solution is replace "OK" query result with "DUNNO". The differences between those two parameters is,

  • When OK, postfix terminates the restriction checking list
  • When DUNNO, postfix will move to next restriction checking list

See also man 5 access.

OK Accept the address etc. that matches the pattern.

DUNNO Pretend that the lookup key was not found. This prevents Postfix from trying substrings of the lookup key (such as a subdomain name, or a network address subnetwork).

This feature is available in Postfix 2.0 and later.