Home > Running with set-user-id (setuid)

For security reasons it is sometimes desirable to run a CGI script under a specific account context, rather than the unprivileged guest context.

This article describes how to control which account context is used when a CGI script executes, on both Unix and Windows. Techniques can be used by normal users as well as administrators.


Security Concerns - to setuid or not

Configuring setuid will decrease the risk of being hacked, but it will significantly increase the potential damage that a successful hack can inflict.

setuid provides benefits mainly on shared systems where many users with equal rights are sharing the unprivileged user context. By making your files and folders accessible to the unprivileged user, you inadvertently make them accessible to all peer users, since they can operate within the unprivileged context as well. Running your scripts as setuid deprives your peers from the automatic rights to your data. However, you still are responsible for restricting file permissions to your data and scripts after going setuid. If you leave file permissions open and just enhance your script with setuid privileges, then you will be more threatened than before.

While setuid protects from peer users, it generally offers no increased protection from external users. Instead, external users who do find a security hole in a script will now be able to exploit it with your account privileges, rather than the unprivileged user's rights. Thus, if the threat to your system from external users is greater than from peer users, avoid setuid. In particular, if you have no peer users, do not go setuid.


Unix/Linux - root users

Whenever possible, use Apache's "User" and "Group" settings within your <VirtualHost> blocks to control the process security. This is a tested, proven, secure way to manage CGI process security.

You might also try CGI Wrap. It can be acquired at http://cgiwrap.unixtools.org/.


Unix/Linux - normal users

Use Apache suexec or CGI Wrap if possible. Pester your admins to support this if they don't already.

Otherwise... it is possible to roll your own setuid wrapper. This is a very simple C program that absorbs the setuid bit and then shells out to the original Perl script. Here is the source code to wrap.c. The full path to the Perl script (in red) must be customized to match your environment:

#include <stdlib.h>
int main() {
	execl("/usr/www/users/xav/scripts/genesis/genesis/index.cgi");
	return 1;
	}

The following commands - listed in blue - prepare the setuid wrapping:

[vepar]/> ls -al
total 252
drwxr-xr-x   4 xav  users     512 Jan  4 01:16 .
drwxr-xr-x   7 xav  users    1024 Jan  3 20:46 ..
-rwxr-xr-x   1 xav  users  108011 Jan  3 20:45 index.cgi
drwxrwxrwx   6 xav  users     512 Jan  3 20:45 script_data
drwxrwxrwx  27 xav  users    1536 Jan  4 01:08 web_pages
-rw-------   1 xav  users     104 Jan  4 01:07 wrap.c
[vepar]/> gcc wrap.c
[vepar]/> mv a.out wrap.cgi
[vepar]/> chmod 4711 wrap.cgi
[vepar]/> chmod 700 index.cgi
[vepar]/> chmod -R 700 script_data
[vepar]/> ls -al
total 270
drwxr-xr-x   4 xav  users     512 Jan  4 01:17 .
drwxr-xr-x   7 xav  users    1024 Jan  3 20:46 ..
-rwx------   1 xav  users  108011 Jan  3 20:45 index.cgi
-rwx------   6 xav  users     512 Jan  3 20:45 script_data
drwxrwxrwx  27 xav  users    1536 Jan  4 01:08 web_pages
-rw-------   1 xav  users     104 Jan  4 01:07 wrap.c
-rws--x--x   1 xav  users    8808 Jan  4 01:17 wrap.cgi
[vepar]/>

In the above example, we first compile the C program with "gcc". This creates "a.out", a compiled C program. We rename a.out to wrap.cgi.

Next, we set the special setuid permissions "rws--x--x" on our C program by chmod'ing to 4711. Then we restrict all access to our original Perl script by chmod'ing to 700.

At this point, we also chmod 700 all data files, modules, and libraries used by the original Perl script (such as the "script_data" subfolder).

Now, from our web browser, we visit wrap.cgi instead of index.cgi. The original Perl script is still executed, but it does so using the account context, not the unprivileged user context. Files and folders are accessed with the user rights, not the shared unprivileged rights.

Note that this entire process depends on an interactive shell running in the account user context (i.e., a telnet connection). This process cannot be completed if FTP is the only means of communicating with the server, because generally the "SITE CHMOD" FTP command will only accept 3-digit chmods, not 4-digit ones.

Note: in many cases, only certain Perl scripts can be run under setuid. You should make sure your script runs with the "-wT" switches. You may need to delete $ENV{'PATH'}. A full discussion of the modifications necessary to Perl scripts to allow setuid can be found at the perlsec manpage.


Windows NT/2000/XP with IIS - for administrators with MMC access

On this platform, all CGI execution is handled by unprivileged guest user "IUSR_Machine".

To change this, open the MMC by going to "Start" -> "Programs" -> "Administrative Tools" -> "Internet Services Manager". Expand the nodes until you can select your CGI file and get properties on it:

selecting a document in the MMC

Select "File Security", then choose the first "Edit":

the document Properties window

On the screen that comes up, leave "Anonymous access" checked at the top - that means people don't have to enter a username/password each time they run the script - and choose the first "Edit" button:

the Authentication Methods window

Probably you will see something like this - the IUSR_Machine account is there, with its password being controlled by IIS:

the default Anonymous account configuration

Simply replace the unprivileged account with your own user account, and enter the appropriate password. Don't let IIS control your password, or it may change it at random:

a customized Anonymous account configuration

Your script will now execute under your user account.


Windows NT/2000/XP with IIS - users without MMC access

Configuring Windows at this level is beyond the scope of this document. If you have web administration enabled, try that. Otherwise, call somebody who does have MMC access. I will hack it for a fee (contact me).


Windows 9x and Windows Millennium

These operating systems do not have the concept of separate user accounts or processes. All processes have equal rights. There is no concept of setuid here.