Tuesday, November 12, 2013

How to use SUID for shell scripts in Linux?



Question : How to write a shell script which will read the required passwords/connect strings from a config file? Other users should be able to execute the scripts, however they should not be able to read the config file.

Say, I have a config file, myconfig.txt, which contains credentials for an oracle connection:
$ cat myconfig.txt
SQLUSR="scott"
SQLPWD="pwd123"
Shell script,script1.sh, to connect to Oracle and get employee name:
$ cat script1.sh
#!/usr/bin/bash

source myconfig.txt

NM=`sqlplus -s ${SQLUSR}/${SQLPWD}@XE <<EOF
set heading off
select ename from emp where empno=7369;
EOF`

echo Name is $NM
The issue here is: Any user, who has permissions to run this script can get to know the password present in the myconfig.txt either by reading the file directly or by running the shell script in debug mode.

How to prevent the user from reading the password?
   By removing the read permission from the group and others on the myconfig.txt file will not help. Because, in that case, the other users will not be able to run the script as well.

Setting the SUID on the Shell script:
    After removing the read permission and then applying the suid bit on the shell script will work on say Solaris, will not work in Linux flavors. Because SUID can be applied only on binary executables in Linux.

Solution:
   In order to create a binary executable, we need to write our code in either say C, C++, etc..which gives binary executables.
   Let us write a C program which reads the myconfig.txt file and sets environment variables for all the entries present in the file. And then invoking the shell script from the C program should suffice:
$ cat getName.c
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

int main()
{
    FILE *fp = fopen("/home/guru/C/myconfig.txt","r");
    char data[128];
    char *d1;
    while(fgets(data,128,fp)!=NULL){
        d1=(char *)malloc(128);
        strcpy(d1,data);
        d1[strlen(d1)-1]='\0';
        putenv(d1);
    }
    fclose(fp);
    system("/home/guru/C/script.sh");
}
 Creating an executable for this C program :
$ gcc -o getName getName.c
$ ./getName
NM is SMITH
Remove the read permission on the myconfig.txt file for group and others and applying the SUID on the executable:
$ chmod go-r myconfig.txt
$ chmod u+s getName
Logging as a different user to check :
$ su - guest
$ echo $USER
guest
$ cd /home/guru/C
$ ./getName
NM is SMITH
$ cat myconfig.txt
cat: myconfig.txt: Permission denied
  On applying the SUID permission, the other user when trying to execute the script, gets the same permission as the owner on the myconfig.txt file and hence the script is able to read the file.
Related Posts Plugin for WordPress, Blogger...

1 comment: