COMMAND
lpd
SYSTEMS AFFECTED
FreeBSD 2.1.5, 2.1.6, 2.1.7, 2.2 Gamma, FreeBSD -current is
vulnerable for dates prior to February 25, 1997
PROBLEM
The following information is Secure Networks Inc. (SNI) copyright
and it is a part of their security advisory (March 5, 1997).
There is a serious security vulnerability in all FreeBSD lpd
implementations This vulnerability allows remote users to gain
unauthorized root access to any system allowing connections to
the line printer daemon (lpd).
A user is not required to be in lpd's access list (/etc/hosts.lpd)
to exploit this vulnerability, as the problem occurs while lpd is
attempting to determine whether the host is permitted to connect.
The vulnerability is present in the source file
lib/libc/net/rcmd.c, which contains the function __ivaliduser().
This function is used by the line printer daemon (lpd) to
determine whether the user connecting to the daemon is in it's
access list (contained in /etc/hosts.lpd). When performing a
domain name lookup on the connecting IP address, the resulting
response is copied into a fixed size buffer of size MAXHOSTNAMELEN
(256 bytes). Since DNS responses containing a hostname and domain
name are currently allowed to exceed 256 bytes, overflow can
occur. The faulty code follows:
if ((hp = gethostbyaddr((char *)&raddr, sizeof(u_long), AF_INET)) == NULL)
return (-1);
strcpy(hname, hp->h_name);
The string copy is done without any bounds checking. Corrected
code looks as follows:
if ((hp = gethostbyaddr((char *)&raddr, sizeof(u_long), AF_INET)) == NULL)
return (-1);
strncpy(hname, hp->h_name, sizeof(hname));
hname[sizeof(hname)-1] = '\0';
SOLUTION
FreeBSD 2.2 is not vulnerable and it was corrected in -current,
and -stable as of February 25, 1997.
If the system in question does not require the use of printing
services, lpd should be removed or commented out from the system
startup file /etc/rc.
If you require the use of printing services, this vulnerability
can be fixed by applying the following patch to
lib/libc/net/rcmd.c. This patch has been known to apply to all
FreeBSD 2.x systems.
--- CUT HERE ---
*** libc/lib/net/rcmd.c.old Tue Feb 25 15:33:42 1997
--- libc/lib/net/rcmd.c Tue Feb 25 15:33:56 1997
***************
*** 377,383 ****
if ((hp = gethostbyaddr((char *)&raddr, sizeof(u_long),
AF_INET)) == NULL)
return (-1);
! strcpy(hname, hp->h_name);
while (fgets(buf, sizeof(buf), hostf)) {
p = buf;
--- 377,384 ----
if ((hp = gethostbyaddr((char *)&raddr, sizeof(u_long),
AF_INET)) == NULL)
return (-1);
! strncpy(hname, hp->h_name, sizeof(hname));
! hname[sizeof(hname)-1] = '\0';
while (fgets(buf, sizeof(buf), hostf)) {
p = buf;
--- CUT HERE ---
At this point, libc will have to be recompiled. lpd is shipped
dynamically linked under FreeBSD, therefore the fix will take
effect without recompiling lpd itself.