[exim] Compromised webhosting accounts

Top Page
Delete this message
Reply to this message
Author: Lena
Date:  
To: exim-users
Subject: [exim] Compromised webhosting accounts
After reading https://github.com/Exim/exim/wiki/BlockCracking ,
a web-hosting admin asked me how to use that approach to block
outgoing spam from webhosting accounts - malicious or
compromised because a webhosting user installed vulnerable version
of soft such as WordPress or Joomla.
Web scripts can submit mail via SMTP to localhost or not via SMTP
(via pipe to "sendmail" binary which calls exim).
I was told that PHP's mail() function submits not via SMTP, at least usually.
When not via SMTP, instead of the rcpt ACL for each recipient,
the not_smtp ACL is executed once per message with possibly several
email addresses in $recipients, but each recipient needs to be
verified separately - I contrived how:

If not via SMTP, and each webhosting user/client's scripts run under
unique userid, and Exim version 4.82 or higher, then (untested):

acl_not_smtp = acl_check_not_smtp
UNLIMITED_USERIDS = root : toor : cron : mailnull : mail : exim : somethingelse
# "mailnull" is Exim user id under FreeBSD, "mail" under some other OSes.
LIM = 100
PERIOD = 1h
WARNTO = abuse@???
SHELL = /bin/sh

begin acl
acl_check_not_smtp:
  accept set acl_m_user = $authenticated_id
        condition = ${if inlist{$acl_m_user}{UNLIMITED_USERIDS}}


  accept condition = ${if exists{$spool_directory/blocked_notsmtp_users}}
        condition = ${lookup{$acl_m_user}lsearch\
                    {$spool_directory/blocked_notsmtp_users}{1}{0}}
        control = freeze/no_tell
        add_header = X-Username: $acl_m_user


  accept condition = ${if forany{<, $recipients}\
                                {eq{${acl{recipient}{$item}}}{caught}}}
        continue = ${run{SHELL -c "echo $acl_m_user \
           >>$spool_directory/blocked_notsmtp_users; \
           \N{\N echo Subject: local user $acl_m_user blocked; echo; echo \
           because has sent mail to LIM invalid recipients during PERIOD.; \
           \N}\N | $exim_path -f root WARNTO"}}
        control = freeze/no_tell
        add_header = X-Username: $acl_m_user


accept

recipient:
accept condition = ${if match{$acl_arg1}{\N[$/"'`\\]\N}}

  accept !verify = sender=$acl_arg1/defer_ok/callout=10s,defer_ok
        ratelimit = LIM / PERIOD / per_cmd / notsmtpuser-$acl_m_user
        message = caught


accept

You can either disable mail from webserver via SMTP to localhost
or use identd daemon, then username should be in $sender_ident .
In case of FreeBSD the "ident" service is provided by inetd, see `man inetd`:
in /etc/inetd.conf uncomment after 'Provide internally a real "ident" service',
in /etc/rc.conf inetd_enable="YES" and
/etc/rc.d/inetd start
or restart), in Exim config

rfc1413_hosts = *
rfc1413_query_timeout = 2s

Please comment.

--
Lena