blahblah has asked for the wisdom of the Perl Monks concerning the following question:

Hello,

The general concensus in the community is that running CGIs setuid root is incredibly dangerous since no program is bug free. A bug in a program with elevated privileges can be very damaging should that program get exploited.

So, I would like to create a program that allows users to login, and then do things on the server as themselves - such as access their mail spools, add and remove files from their home directories, etc. However, I don't want to run the program setuid root to accomplish this.

How can I create a CGI that allows users to login, setuid to the logged in user, without being unsafe? Pointers to existing code would also be very much appreciated if possible.


blahblah

Replies are listed 'Best First'.
Re: safe scripts that can setuid
by Tanktalus (Canon) on Oct 27, 2005 at 23:15 UTC

    As suEXEC only works to become a single user (whosever home directory your script is in), I don't think that's what you want. suEXEC is a solution if each user who wants to use the scripts will locally-install the script (i.e., in their ~/public_html, by default). Then you still want some sort of authentication to ensure that not just anyone who happens to go to ~susan can manipulate susan's files.

    Instead, you would need to use a setuid-root executable of some sort. Using sudo is one way to do this.

    • Your CGI script gets called by apache. It runs as nobody, or apache, or whatever the system is set up to run under.
    • Your "CGI" script calls sudo with the appropriate options. Here you have two choices - call sudo with appropriate options to directly become the other user, or call sudo with appropriate options to become root and call an intermediate script.
    • The intermediate script checks the user/password and figures out if they are ok. It then drops privileges to the appropriate user and, optionally, runs the final script (the final phase could be in the same script that drops privileges, but it's sometimes easier to think of as separate scripts).
    • The final script actually performs the CGI work.
    You need to ensure environment variables are passed through (so don't use the -i option of sudo). And you need to set up the sudoers file to allow this to all work as well, preferably without a password.

      suEXEC is a solution if each user who wants to use the scripts will locally-install the script

      Two words: hard links.

      Then you still want some sort of authentication to ensure that not just anyone who happens to go to ~susan can manipulate susan's files.

      Basic auth + SSL might suffice.

      Playing games with sudo, elevated privileges, multiple scripts, etc. shouldn't be recommended. Chances are that someone trying to implement things like that without a solid understanding of the issues is going to create all sorts of holes.

      Really, we should probably respond with the question, "why are you doing this?" Because, there's almost certain to be a better solution already built.

      -sauoq
      "My two cents aren't worth a dime.";
      
Re: safe scripts that can setuid
by sauoq (Abbot) on Oct 27, 2005 at 23:02 UTC

    If you are using Apache, the right way to do this is with suEXEC.

    -sauoq
    "My two cents aren't worth a dime.";
    
Re: safe scripts that can setuid
by sgifford (Prior) on Oct 28, 2005 at 02:25 UTC
    One way to do this is to write a small server which runs as root, and takes a username, password, and information about what the user would like to do. It can then authenticate the user and decide what action to take, and finally communicate back the result. If you use a program like checkpassword to do the authentication, then only that program will run as root, and it's very well-audited and likely to be secure.

    This is often safer than a SetUID CGI script because it's better isolated from the Web server.