CS360 Lecture notes -- The Setuid bit, passwd, time

  • Jim Plank
  • Directory: /blugreen/homes/plank/cs360/notes/Setuid
  • Lecture notes: http://www.cs.utk.edu/~plank/plank/classes/cs360/360/notes/Setuid/lecture.html

    The setuid bit

    The setuid bit is a way to allow other users to access and write to your files in a restricted way. For example, suppose I want to write a logging program, such as in log1.c. Now, in the Logfile lecture, I said that to let others use this program, I'd have to set up the log file (in this case /blugreen/homes/plank/cs360/notes/Setuid/log_file to be writable by everyone:
    UNIX> chmod 0666 /blugreen/homes/plank/cs360/notes/Setuid/log_file
    
    However, that is unsafe, since any of you could now edit that file, truncate it, or whatever. Thus, this isn't a good solution in an environment in which you don't trust everyone.

    To combat this, one of the things that Unix provides is the ``setuid'' bit. This says to set the user id of the program being exectuted to that of the owner of the executable file. You can see whether the bit is set in the "ls -l" command (it is part of the mode in "stat"):

    UNIX> cd /blugreen/homes/plank/cs360/notes/Setuid
    UNIX> ls -l log1 log2
    -rwxr-xr-x  1 plank       24576 Sep 30 09:46 log1
    -rwsr-xr-x  1 plank       24576 Sep 30 09:46 log2
    UNIX>
    
    Log1 is log1.c compiled normally. Log2 is created by:
    UNIX> cp log1 log2
    UNIX> chmod 04755 log2
    
    This sets the setuid bit. You'll notice that since log_file is chmod()'d to 0644, log1 will fail when you call it from your account, but log2 will succeed:

    (YOU MUST BE LOGGED INTO THE MACHINE "vertex" FOR THIS TO WORK -- so do "ssh vertex" first.)

    UNIX> echo "$USER"
    booth
    UNIX> cd /blugreen/homes/plank/cs360/notes/Setuid
    UNIX> cat log_file
    plank      Mon Feb 28 11:28:58 1994
    booth      Mon Feb 28 11:37:24 1994
    elmore     Tue Mar  8 09:45:19 1994
    hamner     Tue Mar  8 21:14:06 1994
    UNIX> log1
    Can't write log file /blugreen/homes/plank/cs360/notes/Setuid/log_file
    UNIX> date
    Fri Sep 30 10:13:04 EDT 1994
    UNIX> log2
    UNIX> cat log_file
    plank      Mon Feb 28 11:28:58 1994
    booth      Mon Feb 28 11:37:24 1994
    elmore     Tue Mar  8 09:45:19 1994
    hamner     Tue Mar  8 21:14:06 1994
    booth      Fri Sep 30 10:13:10 1994
    UNIX>
    
    So, this gives you a way to let other users mess with your files in a restricted way. You must be very careful when using the setuid bit, that you not give users too much access. For example, look at log3.c:
    #include < stdio.h >
    
    main(int argc, char **argv)
    {
      char s[1000];
      FILE *f;
      int i;
    
      if (argc == 2) {
        sprintf(s, "/blugreen/homes/plank/cs360/notes/Setuid/%s", argv[1]);
        
        f = fopen(s, "w");
        if (f == NULL) {
          perror(s);
          exit(1);
        }
        i = 1;
        while(i > 0) {
          i = fread(s, sizeof(char), 1000, stdin);
          if (i > 0) {
            fwrite(s, sizeof(char), i, f);
          }
        }
        fclose(f);
      }
    }
    
    This file lets a user create a file in the directory /blugreen/homes/plank/cs360/notes/Setuid and set the contents to standard input. The user specifies the file name. Were I to set the setuid bit of this file, then a malignant user could for example, trash my .cshrc file by calling "log3 ../../../.cshrc". Then he/she could set that file to whatever he/she wanted. Thus, what looks like a benign program is really a huge security leak. Thus, you must be careful writing programs that make use of the setuid bit.

    On our systems, the setuid bit only works if you are logged onto the machine which contains the filesystem that the executable file is on. Thus, to use the "log2" program, you must be logged into the machine "vertex", as that is the machine that contains "/blugreen/homes/plank/..." The reason for this is security. Other machines mount my filesystem "remotely", and are not trusted where setuid bits are concerned.


    /etc/passwd

    Read the book -- sections 6.2 and 6.3.