Wednesday, 6 June 2012

What happens if we call System from a Set-User-Id Program?

For more info visitWhat is System function and why do we use it? System is a function provided by C library STDLIB, it is used to execute a command string from within a C program. We can understand it to be the substitute for fork() and exec(). Instead of forking a new child process and calling exec function to execute a new command, we can directly use System function to execute a new command. Also, System function has a lot of advantages other than just fork() and exec(). Features: i) It forks(), exec() and waits for the child process. ii) Performs error handling if fork() or exec() or waitpid() fails. iii) Doesn't handle signals. We can use system in our C program as follows system("ls -lrt"); Just a simple statement and we can execute all the commands, scripts and binary executables from our program, without using fork() and execute(). But, what happens when we try to use system function with Set-User-Id programs. Let's say there is a user, user1, who is the owner of two programs, prog1 and prog2. Now, suppose that user1 has set SUID bit for prog1, but no SUID bit has been set for prog2, i.e user1 wants that, whenever prog1 runs, it should run with the owner's permission, but prog2 should always run with the user's permission. Let's  write prog1.c #include<stdio.h> #include<stdlib.h> int main() { printf("\nreal user id %d\n",getuid()); printf("\neffective user id %d\n",geteuid()); system("prog2"); exit(0); } Now write prog2.c #include<stdio.h> #include<stdlib.h> int main() { printf("\nin prog2\n"); printf("real user id %d\n",getuid()); printf("effective user id %d\n",geteuid()); printf("exit prog2\n"); exit(0); } Compile prog2.c and prog1.c. Suppose we get two binary executables, prog1 and prog2. Set SUID bit for prog1. Now, log in as different user, let's say user2, set the directory of prog2 in PATH environment variable. Run prog1 as user2. The output shall be real user id 1197 effective user id 1196 in prog2 real user id 1197 effective user id 1196 exit prog2 Did you notice the hole in security. Even though prog2 was not SUID bit set, it was run with the file owner's permission. Always be careful while using System function. The above problem can be solved by adding an extra line of code in prog1. Modified prog1 which is secure, #include<stdio.h> #include<stdlib.h> int main() { printf("real user id %d\n",getuid()); printf("effective user id %d\n",geteuid()); setuid(getuid()); system("prog2"); exit(0); } Now compile and run the prog1 as user2. Don't forget to set the SUID bit for prog1. The output shall be real user id 1197 effective user id 1196 in prog2 real user id 1197 effective user id 1197 exit prog2 getuid() gives the real user id  and setuid(getuid()) sets the effective useri id, before calling the system function, as real user id. So, when system() is called, real user id is passed to the exec() function used in the system function, and is set as the effective user id. Whenever a new child process is executed, the exec() copies the effective user id from the parent process. Infact, setuid() doesn't only set the effective user id of the process. It performs different actions in different situations. However, in this scenario, it only sets the effective user id of the process.

No comments:

Post a Comment