On Tue, 2009-08-25 at 19:31 +0200, Florian Zumbiehl wrote: > actually, I even explained _how_ this could lead to temporarily wider > permissions than configured, but let's trace through an example for > Mr. POSIX: > > Assumption: > > /dev/foo is configured to be owned by user root, group users, mode 0646. > The attacker tries to open /dev/foo for writing as a user that's not > root, not a member of the group root, but a member of the group users. > > The Trace: > > action | owner | group | mode | open(O_WRONLY)? > ----------------------------+-------+-------+---------+----------------- > mknod(/dev/foo) | root | root | 0644(?) | no > chmod(/dev/foo,0646) | root | root | 0646 | yes > chown(/dev/foo,root,users) | root | users | 0646 | no > > Could we now take care of the bug? > Sure, let's invert the chmod() and chown()... BUT WAIT! Assumption: /dev/foo is configured to be owned by user mrposix, mode 0466. The attacker (mrposix) tries to open /dev/foo for writing. The Trace: action | owner | mode | open(O_WRONLY)? ------------------------------+---------+---------+----------------- mknod(/dev/foo) | root | 0644 | no chown(/dev/foo,mrposix,users) | mrposix | 0644 | yes chmod(/dev/foo,0466) | mrposix | 0466 | no In other words, exactly the same race. Since we don't have a chownmod syscall, we have to do this non-atomically, which means that either there's a race for denying access for particular users or a race for denying access for particular groups. Now, let's put aside for a moment the fact that either of these modes is insane. Which of the two attempts to deny access _should_ work? The surprising answer is that the attempt to deny access to the *user* is the one that should work (ie. don't change the code), not the attempt to deny access to a group. There's a simple reason for this. A user's uid is fixed, and is a key fact of that user's privilege. The only way for "mrposix" to change users is if he was really root in the first place, or has access to a setuid program. A user's gid *is not* fixed, in fact, a user may be a member of any one or more groups at their own choice. An entry in /etc/passwd or /etc/groups does not *force* the user into those groups, it simply grants the user *access* to be a member of those groups. There are tried, tested and (most importantly) *permitted* methods for a user to shed group membership. Since a user can shed their group membership in this way, they can work around your attempt to restrict access, and thus grant themselves write access after all. (This is, in fact, why it's "insane" to deny access using modes; a user can always find a way to become *less* privileged, and thus if you're trying to deny them access to things, actually gain privilege) Scott -- Scott James Remnant scott@xxxxxxxxxxxxx
Attachment:
signature.asc
Description: This is a digitally signed message part