SetGID and SetUID Shell Scripts October 22, 2007
Under most UNIX implementations, shell scripts cannot be made to setuid. This is both a security precaution and hindrance. For example, let’s say that you have the need to allow your users to RSYNC content from one server (a development server), that they have an account on, to a production server that they don’t have direct access to. So here is a script called rolldata.sh that accomplishes just that:
#!/usr/bin/sh /opt/local/bin/rsync -avP -e "/bin/ssh -i /sshdir/rolluser-id_rsa" \ "/localdir/" "rolluser@securehost.domain.com:/remotedir/"
Now, this works, but it leaves a few glaring security problems:
1) The user needs to be able to READ the /sshdir/rolluser-id_rsa file in order for the ssh command to work without a password. If they can read this file, then they could just SSH right to the box and do lots of other stuff if they know how, which is not very hard.
2) Since ssh will only allow identity files to be -r——– in permission, every user who needs to be able to execute the above script must have their own rolluser-id_rsa file somewhere (and their own personal script) that can read by them and nobody else.
So, the obvious solution I thought would be to setgid the shell script, make it owned by root and make it only executable like:
---s--s--- 1 root cit 229 Oct 22 19:32 rolldata.sh -r-------- 1 root cit 883 Oct 22 18:59 rolluser-id_rsa
Therefore, only root would be able read the contents of the rolldata.sh script and the rolluser-id_rsa file, but any user in group cit could run it. The only problem is that most UNIX kernels (including Solaris) don’t allow you to setuid/gid a shell script!
However, this restriction obviously does not apply to compiled code, so this is what I came up with to get around this restriction. Create a C file called rolldata.c that looks like:
#include <unistd.h>; main () { setuid(0); int ret; ret = execl ("/mydir/rolldata.sh", "/mydir/rolldata.sh", "-1", (char *)0); }
This program simply runs a pre-defined script as the user root, by way of the setuid(0); call. After compiling this (gcc ./rolldata.c), call this file rolldata and set the permissions with setgid like:
---s--s--- 1 root cit 6656 Oct 22 20:05 rolldata ---x------ 1 root cit 229 Oct 22 19:32 rolldata.sh -r-------- 1 root cit 883 Oct 22 18:59 rolluser-id_rsa
Now, any user in group cit can now execute the rolldata.sh script by way of running rolldata, but cannot read the script or the ssh identity key!
[user@computer mydir]$ ./rolldata building file list ... 109 files to consider wrote 2998 bytes read 20 bytes 6036.00 bytes/sec total size is 2532169264 speedup is 839022.29 [user@computer mydir]$ cat ./rolluser-id_rsa cat: cannot open ./rolluser-id_rsa
Leave a Reply