The 'Security Digest' Archives (TM)

Archive: About | Browse | Search | Contributions | Feedback
Site: Help | Index | Search | Contact | Notices | Changes

ARCHIVE: Zardoz 'Security Digest' - Archives (1989 - 1991)
DOCUMENT: Zardoz 'Security Digest' V1 #17 1989-04-06 (1 file, 1685 bytes)
NOTICE: recognises the rights of all third-party works.


Date: Thu, 6 Apr 89 21:12:16 PDT
Subject: Security Digest V1 #17

Security Digest Volume 1 Issue 17


            another su bug in Sunos 4.0
            security problem with large uids and gids in Sunos


Date: Tue, 4 Apr 89 14:38:16 PDT
From: neil (Neil Gorsuch)
Subject: another su bug in Sunos 4.0

[ There is rumored to be another bug in Sunos 4.0 su that allows root
access to anyone.  It is currently being investigated, and seems to
be similar to the ftp bug in that it uses stack overwriting and leaves
a core dump around.  (Although any smart cracker will delete the
core file after gaining root access). - neil ]


Date: Thu, 6 Apr 89 17:58:46 PDT
From: neil (Neil Gorsuch)
Subject: security problem with large uids and gids in Sunos

[ This was posted in comp.sys.sun by [email protected],
you might want to make sure no user or group id's are >= 32768 - neil ]

The problem is that setuid(getuid()) and setgid(getgid()) do not work for
large uids and gids, i.e. 32K and larger.  In 4.3, the uid and gid in
<user.h> are declared unsigned short.  Thus no sign-extension problems
occur.  In SunOS, they are declared signed short.  getuid and getgid
sign-extend the returned value.  Unfortunately, setuid and setgid
(actually setreuid and setregid) contain explicit checks that reject
arguments with non-zero left half.  Thus setuid won't accept the value
returned by getuid, etc.  Note that you can't just do setuid(getuid() &
0xffff); After verifying that the left half is zero, setuid then checks to
see whether the value matches either the real or effective uid.  It
sign-extends the current values. So if you set the left half to zero, you
pass the explicit left-half check and then fail the comparision.  No
possible value will pass both checks.

Unfortunately, setuid(getuid()) is used by many setuid programs before
doing something like sprouting a shell.  It is intended to put things back
to an unprivileged state.  Because there's no way this can fail, it's
unusual for programs to check the value returned by setuid.  To the net
effect is that a setuid program is likely to sprout a root shell for users
whose uid's are 32K and larger.  We actually ran into the problem with
mail, where we got a shell whose gid was mail instead of the user's own
gid.  (We run mail setgid to mail, and do setgid(getgid()) in appropriate
places.)  I haven't examined the system to see exactly where the resulting
holes are.  It is even possible that no standard part of SunOS 4.0 relies
on that code (though I'd be very surprised).  But it's still a potentially
serious security problem.  Unfortunately the only fixes I can think of are

  - fix the kernel
  - make sure you don't have any uid's or gid's >= 32K

So non-source sites with lots of users may be in big trouble.  (We use
large gid's because our gid's have meaning to our accounting system.  We
don't really have 32K of them.  We just need all 16 bits to encode all the
things we want to encode.  We do have uid's >= 32K because of the way we
allocate uid's.  Because of NFS, we give users the same uid on all
systems.  AT one point we did this by assigning each department a range of
uids they could assign.  We assigned the whole 64K address space.  We now
have a better way of assigning uid's, but we are stuck with uid's > 32K.)

I believe SunOS 3.2 is OK.  setre[ug]id uses code much closer to 4.3.  It
still sign-extends the uid and gid, but it does so consistently.


        End of Security Digest Volume 1 Issue 17