[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: setuid/setgid binaries contained in the Debian repository.



Hi,

On Mon, Aug 11, 2003 at 01:18:08PM -0400, Matt Zimmerman wrote:

> On Mon, Aug 11, 2003 at 06:13:10PM +0200, Emile van Bergen wrote:
> 
> > On Mon, Aug 11, 2003 at 10:33:47AM -0400, Matt Zimmerman wrote:
> > > I don't follow.  The wrapper is running with uid games, and it exec()s
> > > the actual game.  So the game is running with uid games, exactly as if
> > > the game itself were setuid, and if the game is exploited, uid games is
> > > compromised (and so is the wrapper).
> > 
> > If the game is exploited, its uid is exploited, but *only* that uid, not
> > the user that has invoked it or any other future user that invokes it.
> 
> Right, but its uid owns executable programs, and thus "owns" any user who
> runs those executables.

Nonsense. The only thing that can be 'owned' is the user's files and
they cannot be written to by the game uid. Also, the game uid cannot run
any process impersonating the user. 

The whole point is removing the 'thus' from your sentence, by having a
trapdoor that drops the invoking user's permissions.

> > > The only barrier I see is that it would clean the environment variables.
> > > Yes, this is a popular attack vector, but it is by no means the only
> > > one.
> > 
> > No, but it helps. Everything that the wrapper can do will help protect the
> > game. 
> > 
> > The point is that if the game is *still* compromised, nothing is lost but
> > the files that can be written by this particular game's uid, which should
> > be nothing but its own highscore files. Not a problem. A given game's
> > highscore files need to trust that game anyway.
> 
> The problem is that the game will often trust the high score files, not the
> other way around.  If a wrapper solution is to work, it needs to prevent the
> need for security within the game itself, entirely, by providing a secure
> sandbox.  This is by no means trivial, and triviality is the most desirable
> feature in a wrapper program (for purposes of auditability and obvious
> correctness).

The wrapper *is* trivial. It's what, twenty lines of code? The sandbox
available on a unix system is the separate uid. 

I can't make it simpler than that. Any java, selinux, MAC, UML-based
solution will be *much* more complex conceptually and less transparent.

It's the game code's responsibility to properly bridge between its user
interface and its highscore files. No OS can help it do that, that's its
role. That's its purpose.

> > Good point, but that's easy to fix, and the fix is necessary to get rid of
> > the user's supplementary groups as well --  it turns out a normal user
> > cannot trim its own group list using setgroups.
> > 
> > To make the wrapper unwritable both by the user and the per-game uid/gid,
> > make it setuid root, setgid to the per-game uid/gid, have the wrapper call
> > setgroups to get rid of the group list, obtain the desired new uid/gid
> > from the effective gid given by the filesystem, call setgid, call setuid
> > to set the real, saved and effective uid.
> 
> This is now adding quite a bit of complexity, and a setuid root program to
> boot (which, it seems, is now also setgid).  And what have we gained?
> Shared high scores?

We have gained sandboxed games that are shielded from each other, and a
wrapper that cannot be written to by the user or the game's uid.

> I would rather see a tiny setuid program which sanitizes and records high
> scores, which is invoked by the game, which runs with the privileges of the
> user 

So your highscore manager has the privileges of the user *and* the high
score file owner. Less secure than my solution.

> (or, for extra high-score paranoia, setgid, where only gid games can
> invoke the high score manager).  

Yes, but all games share the same trust from the high score manager. One
compromised came can impersonate another game to the high score manager.
The only way to prevent that is different uids for each game. Hence my
solution.

> I believe joeyh described a system somewhat like this.  This also has
> complexity to be counted against it (and would be difficult to
> integrate into many games), but at least it does not involve root in
> the process.
>
> > Example:
> > [...]
> > /usr/lib/games:
> > -rwxr-x---    1 root quake 1234567 Aug 11 16:30 quake (real binary)
> 
> What is the point of restricting execute permission on this unprivileged
> program?

It's not a necessity, but if the user wants to be shielded from its bugs
and want the game to be able to write the high score files, he should not run
it directly.

> > /usr/bin:
> > -rwsr-s---    1 root quake    6231 Aug 11 16:30 quake (from wrapper.c)
> 
> I don't see why this should be setgid.  It seems the setgid bit is only used
> to store configuration information (which uid the wrapper should change to).
> This may as well be hard-coded in the wrapper, since a separate copy of the
> wrapper will be necessary for every game anyway with this scheme.

A separate copy on the file system, yes, but in my scheme, the same binary.
It needs to set the gid to that of the game anyway, you don't want it to
run as the user's gid after all. 

Giving the process the 'quake' egid after invocation doesn't create any
extra risk. It's already got root, you know. We're already dependent on
the fact that the code path between _start and the call to setuid is
taken exactly as intended.

> > int main(int argc, char **argv)
> > {
> >         static char realgame[PATH_MAX];
> >         static char *gameenv[] = { 0 };
> 
> Having a completely empty environment will surely cause problems; a trusted
> PATH at least should be set, and things like TERM are required for proper
> operation of many games (though presumably not Quake, which isn't
> terminal-based).  You also need some way to tell the game who the user is,
> for record keeping purposes.

Sure. That's something you could put in $USER.

> > Any user that's a member of the group 'quake' can run /usr/lib/games/quake
> > as user 'quake', group 'quake', nothing else. Neither the user nor 'quake'
> > can write to the wrapper.
> 
> > Now, if this is insecure for any reason, I'd like to hear why, because then
> > it seems unix has a fundamental problem. 
> 
> Unix has fundamental security problems; this is not news.  The security
> history of the entire setuid paradigm is awful.

Not the paradigm; the history of entire services running as root is
awful. We should change /that/, not restrict root to prevent it from
creating trapdoors and controlled privilege escalators through the
setuid concept. Those are useful things and in some form or another
present in any security system.

> I don't see any obvious security vulnerabilities in the privileged part of
> your system, but there are functional problems, which would severely cripple
> or break most of the games in Debian, which would need security-conscious
> solutions (such as passing environment variables and command-line
> arguments).

I don't think the migration is more difficult than when putting
client/server code in the games. A game can just write to its files like
it's used to; the only thing that must be changed is to take the
player's identity within the game from the command line or the
environment instead of from getuid().

Before you shout that this is insecure, remember that the high score
files are owned by their respective game uids, so it cannot write to its
high score file unless it's running as its assigned uid.

The only way the user can get from his own uid to the game uid is
through the trapdoor that only runs the particular game belonging to it.

Cheers,


Emile.

-- 
E-Advies - Emile van Bergen           emile@e-advies.nl      
tel. +31 (0)70 3906153           http://www.e-advies.nl    

Attachment: pgp7kMWAm6q9f.pgp
Description: PGP signature


Reply to: