COMMAND
IPFilter
SYSTEMS AFFECTED
Most unices with IPFILTER-v3.2.10
PROBLEM
garath found following. The IPFilter package is a freely
distributable TCP/IP packet filter, designed primarily for use in
a firewalled environment. The package includes a series of kernel
additions and modifications, and various applications. A problem
exists in its method of creating files for saving output. fopen,
in ip_fil.c, is used to open the saved output file in an insecure
manner:
sprintf(fname, "/tmp/%s", ifp->if_xname);
if ((fp = fopen(fname, "w")))
fclose(fp);
This problem has existed in IPFilter since v3.2.3. The package
comes with the following operating systems:
o OpenBSD
o FreeBSD (post 2.2)
o NetBSD (post 1.2)
and has been tested and run on:
o Solaris/Solaris-x86 2.3 - 2.6
o SunOS 4.1.1 - 4.1.4
o BSD/OS 1.1 - 3.1
o IRIX 6.2
o Linux 2.0.31 - 2.0.35
Any user, anticpating priviledged usage of these routines, can
create a symbolic link which could effectively clobber arbitrary
system files. Because none of the commands which use this
vulnerable routine are setuid, normal users cannot create files in
system directories. Testing was performed using IPFilter v3.2.10
in OpenBSD 2.5-beta.
SOLUTION
For those who actually make use of the feature and/or feel they
need a patch to correctly address this situation (they do testing
as root on systems where unfriendly users are likely to be present
and hanging out waiting for root to possibly do something like
this), see below:
Index: ip_fil.c
===================================================================
RCS file: /devel/CVS/IP-Filter/ip_fil.c,v
retrieving revision 2.0.2.44.2.17
retrieving revision 2.0.2.44.2.18
diff -c -r2.0.2.44.2.17 -r2.0.2.44.2.18
*** ip_fil.c 1999/03/15 11:51:57 2.0.2.44.2.17
--- ip_fil.c 1999/04/11 10:42:36 2.0.2.44.2.18
***************
*** 1126,1147 ****
ip_t *ip;
{
# endif
- FILE *fp;
char fname[32];
# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
(defined(OpenBSD) && (OpenBSD >= 199603))
sprintf(fname, "/tmp/%s", ifp->if_xname);
- if ((fp = fopen(fname, "a"))) {
- fclose(fp);
- }
# else
sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit);
- if ((fp = fopen(fname, "a"))) {
- fwrite((char *)ip, ntohs(ip->ip_len), 1, fp);
- fclose(fp);
- }
# endif
return 0;
}
--- 1126,1147 ----
ip_t *ip;
{
# endif
char fname[32];
+ int fd;
# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
(defined(OpenBSD) && (OpenBSD >= 199603))
sprintf(fname, "/tmp/%s", ifp->if_xname);
# else
sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit);
# endif
+ fd = open(fname, O_WRONLY|O_APPEND);
+ if (fd == -1) {
+ perror("open");
+ return -1;
+ }
+ write(fd, (char *)ip, ntohs(ip->ip_len));
+ close(fd);
return 0;
}
***************
*** 1204,1227 ****
void init_ifp()
{
- FILE *fp;
struct ifnet *ifp, **ifa;
char fname[32];
# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
(defined(OpenBSD) && (OpenBSD >= 199603))
for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) {
ifp->if_output = write_output;
sprintf(fname, "/tmp/%s", ifp->if_xname);
! if ((fp = fopen(fname, "w")))
! fclose(fp);
}
# else
for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) {
ifp->if_output = write_output;
sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit);
! if ((fp = fopen(fname, "w")))
! fclose(fp);
}
# endif
}
--- 1204,1234 ----
void init_ifp()
{
struct ifnet *ifp, **ifa;
char fname[32];
+ int fd;
+
# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
(defined(OpenBSD) && (OpenBSD >= 199603))
for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) {
ifp->if_output = write_output;
sprintf(fname, "/tmp/%s", ifp->if_xname);
! fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0600);
! if (fd == -1)
! perror("open");
! else
! close(fd);
}
# else
for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) {
ifp->if_output = write_output;
sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit);
! fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0600);
! if (fd == -1)
! perror("open");
! else
! close(fd);
}
# endif
}