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
      }