SECURITY HOLE in tftpd
lee at unmvax.UUCP
lee at unmvax.UUCP
Fri Sep 21 08:23:44 AEST 1984
Here is Bill Shannon's original article..
>From shannon at sun.uucp (Bill Shannon) Sat Feb 5 23:28:16 206
>Relay-Version: version B 2.10.1 6/24/83; site unmvax.UUCP
>Posting-Version: version B 2.10.1 6/24/83 SMI; site sun.uucp
>Path: unmvax!unm-cvax!lanl-a!cmcl2!floyd!harpo!decvax!decwrl!sun!shannon
>From: shannon at sun.uucp (Bill Shannon)
>Newsgroups: net.bugs.4bsd
>Subject: SECURITY HOLE in tftpd
>Message-ID: <566 at sun.uucp>
>Date: Wed, 7-Mar-84 16:36:55 MST
>Date-Received: Thu, 8-Mar-84 13:13:09 MST
>Organization: Sun Microsystems, Inc.
>Lines: 21
>
>Subject: tftpd doesn't check file permissions properly
>Index: etc/tftpd.c 4.2BSD
>
>Description:
> The tftp daemon runs as root and is only supposed to let you
> access files with public read. However, it only checks the
> file itself, not the path to the file.
>Repeat-By:
> chmod 700 /sys
> tftp localhost
> get /sys/sys/tty.c
>Fix:
> I fixed it by doing a setgid(-2), setuid(-2) before checking access
> permissions. It's hard to check the entire path by hand because
> of symbolic links; you really have to run as someone who will only
> have public permission to the file. -2/-2 is not guaranteed to be
> restrictive enough, but it was a quick fix. Perhaps a uid/gid should
> be reserved for this purpose.
>
> Sorry, no diff of the fix. Our tftpd has changed far too much for
> other reasons for it to be useful.
>
I came up with a different fix that does not require a reset of the UID/GID.
Nor does it need a special user id. Just runs as root.
RCS file: RCS/tftpd.c,v
retrieving revision 1.1
diff -c -r1.1 tftpd.c
*** /tmp/,RCSt1021188 Thu Sep 20 16:22:24 1984
--- tftpd.c Thu Sep 20 16:08:43 1984
***************
*** 188,193
int mode;
{
struct stat stbuf;
if (*file != '/')
return (EACCESS);
--- 188,195 -----
int mode;
{
struct stat stbuf;
+ char *ptr;
+ int sret;
if (*file != '/')
return (EACCESS);
***************
*** 191,196
if (*file != '/')
return (EACCESS);
if (stat(file, &stbuf) < 0)
return (errno == ENOENT ? ENOTFOUND : EACCESS);
if (mode == RRQ) {
--- 193,215 -----
if (*file != '/')
return (EACCESS);
+ /* Check path first */
+ ptr = file;
+ ptr++;
+ while (*ptr) {
+ if (*ptr++ != '/')
+ continue;
+ ptr--;
+ *ptr = NULL;
+ sret = stat(file, &stbuf);
+ *ptr++ = '/';
+ if (sret < 0)
+ return (errno == ENOENT ? ENOTFOUND : EACCESS);
+ if (!((stbuf.st_mode&S_IFMT)&S_IFDIR))
+ break;
+ if ((stbuf.st_mode&(S_IEXEC >> 6)) == 0)
+ return (EACCESS);
+ }
if (stat(file, &stbuf) < 0)
return (errno == ENOENT ? ENOTFOUND : EACCESS);
if (mode == RRQ) {
--
--Lee (Ward)
{ucbvax,convex,gatech,pur-ee}!unmvax!lee
More information about the Comp.bugs.4bsd.ucb-fixes
mailing list