Every once in a while there is a security alert about tcpdump being
hackable through one of the many protocol analyzers.  Couldn't these
be prevented simply by unconditionally dropping privileges as soon
as the interface is opened?

The following is a simple and briefly tested (on a Debian GNU/Linux
system) patch I wrote to do this.  I decided to try dropping back to
nobody (whether we were originally run by root or another user),
since this should give an attacker the least capacity for damage (at
least on a standard unix system).

Obviously, this could break anything that assumes we are running as
the original user later, but I can't imagine why anything would do
that.  If it is a problem, there can be a flag to disable this
patch, but I think the safest behavior should be the default.

Andrew

--- tcpdump.c.orig      2003-12-17 20:22:57.000000000 -0500
+++ tcpdump.c   2004-01-20 12:50:12.000000000 -0500
@@ -57,6 +57,7 @@
 #endif /* WIN32 */
 
 #include <pcap.h>
+#include <pwd.h>
 #include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -105,6 +106,7 @@
 int32_t thiszone;              /* seconds offset from gmt to local time */
 
 /* Forwards */
+static void drop_privileges();
 static RETSIGTYPE cleanup(int);
 static void usage(void) __attribute__((noreturn));
 static void show_dlts_and_exit(pcap_t *pd) __attribute__((noreturn));
@@ -618,7 +620,6 @@
                int dlt;
                const char *dlt_name;
 
-#ifndef WIN32
                /*
                 * We don't need network access, so relinquish any set-UID
                 * or set-GID privileges we have (if any).
@@ -628,8 +629,8 @@
                 * people's trace files (especially if we're set-UID
                 * root).
                 */
-               setuid(getuid());
-#endif /* WIN32 */
+                drop_privileges();
+
                pd = pcap_open_offline(RFileName, ebuf);
                if (pd == NULL)
                        error("%s", ebuf);
@@ -712,12 +713,8 @@
                        netmask = 0;
                        warning("%s", ebuf);
                }
-               /*
-                * Let user own process after socket has been opened.
-                */
-#ifndef WIN32
-               setuid(getuid());
-#endif /* WIN32 */
+
+                drop_privileges();
        }
        if (infile)
                cmdbuf = read_infile(infile);
@@ -834,6 +831,26 @@
        exit(status == -1 ? 1 : 0);
 }
 
+/*
+ * Since we are processing untrusted data, drop privileges to mitigate the
+ * risk due to bugs in analysis code.
+ */
+static void
+drop_privileges()
+{
+#ifndef WIN32
+       struct passwd *nobody;
+
+       /* Attempt to drop back to nobody.  This is safest. */
+       nobody = getpwnam("nobody");
+       if (nobody && nobody->pw_uid)
+               setuid(nobody->pw_uid);
+       /* If there is no nobody (?!), at least drop back to original uid */
+       else
+               setuid(getuid());
+#endif /* WIN32 */
+}
+
 /* make a clean exit on interrupts */
 static RETSIGTYPE
 cleanup(int signo _U_)
-
This is the TCPDUMP workers list. It is archived at
http://www.tcpdump.org/lists/workers/index.html
To unsubscribe use mailto:[EMAIL PROTECTED]

Reply via email to