Ethereal-dev: Re: [Ethereal-dev] user plugins loaded even if root

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

From: Guy Harris <gharris@xxxxxxxxx>
Date: Sat, 21 Jan 2006 13:54:27 -0800
LEGO wrote:
Plugins in $HOME/.ethereal/plugins get loaded anyway whether they are
owned or not by the user running them.

That means that if ethereal is sudoed ( man sudo(8) ), as I imagine
some linux administrators want ethereal to be runt by users,  the code
in user plugins will be executed. That means that if I write, compile
and install a malicious plugin in my home dir (or any dir pointed by
$HOME) it would execute
with root privileges.

Should we load user plugins  only if owned by the user ethereal is
currently running?

Possibly.  I'd just realized that recently as well.

One might argue that we should, instead, relinquish set-UID or set-GID privileges at the beginning of main(), reclaim them before opening a capture device, and relinquish them as soon as we've opened the capture device (if we're on a UN*X that supports the saved set-user and set-group IDs; are there any on which we'd be likely to be running that don't?).

However, although we should arguably be doing that *anyway*, so a set-UID or set-GID Ethereal or Tethereal will do most of its operations, *including* opening and creating files, as the user and group running the program, that doesn't prevent a malicious plugin from reclaiming those privileges itself.

A number of UN*Xes have an "issetugid()" call; if it's present, we could use that.

If it's not present, if the OS has geteuid() and getegid(), we should call both of those before relinquishing set-UID and set-GID privileges (which we'd have to do anyway, in order to reclaim those privileges), and compare the results against the results of getuid() and getgid() and, if they don't match, set a global flag, and have "issetugid()" return the value of that flag.

Note also that if we're running set-UID or set-GID, we shouldn't honor any environment variables that would, for example, change where we read or write files, or otherwise make us do something unsafe. Relinquishing set-UID and set-GID privileges *should* make that safe, but we'd need to ignore anything from environment variables in the small window in which we're set-UID or set-GID.

Long term, splitting the capture functionality off into a small program, so *it* can run set-UID or set-GID if necessary, would probably be the best answer, at least for Ethereal.

I'm not sure that's the right answer for Tethereal, though, as I'd prefer not to introduce a temporary capture file if you're just running Tethereal without "-w". An alternative might be to:

	relinquish set-UID and set-GID privileges immediately in main();

parse the command-line arguments *before* loading plugins and initializing the dissectors and taps, and just save away "-o" and "-z" arguments for later processing;

	if we're doing a live capture, open the capture device;

*permanently* relinquish set-UID and set-GID privileges (setgid() and setuid()), as we won't need them to open a capture device, and we don't *want* them any more;

	load plugins and initialize the dissectors and taps;

	process the saved "-o" and "-z" options.