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