LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Security (https://www.linuxquestions.org/questions/linux-security-4/)
-   -   Why is system() insecure? (https://www.linuxquestions.org/questions/linux-security-4/why-is-system-insecure-603187/)

reverse 11-29-2007 02:43 AM

Why is system() insecure?
 
From the Debian system() man page:

Quote:

Do not use system() from a program with set-user-ID or set-group-ID privileges, because strange values for some environment variables might be used to subvert system integrity. Use the exec(3) family of functions instead, but not execlp(3) or execvp(3). system() will not, in fact, work properly from programs with set-user-ID or set-group-ID privileges on systems on which /bin/sh is bash version 2, since bash 2 drops privileges on startup. (Debian uses a modified bash which does not do this when invoked as sh.)
Well actually I have two questions.

#1. What do they mean by "strangle values for some environment variables". Suppose I have this: system("/bin/ls"). Why would this be insecure? I thought it might be because of a malformed IFS + PATH variable, i.e.:

Code:

/* We have the SUID-root `insecure` binary which makes a call to system() at some point, exact call being: system("/bin/ls") */

/* I thought this would be insecure because of a construction like this: */

$ export IFS=/
/* The above line would mean "/" separates commands from their arguments and thus the command /bin/ls would actually mean: command `bin` with argv[1] == `ls` */

$ export PATH="./evil-dir"

/* And then in the directory evil-dir one could put a script named "bin" which would contain: #!/bin/bash -c echo just a test */

/* And now by running "insecure", this would call system("/bin/ls") which would actuall mean: "run program `bin` with argument `ls`", and since our PATH is modified, the program `bin` would be one of our choice. */
$ ./insecure
just a test

/* However, this does not work, so my assumptions were wrong, and I do NOT actually understand why system() is insecure. */

My 2nd question is as follows: why does Debian have a bash modified in such a way that it does *not* drop priviledges when invoked as /bin/sh? And is this not a weakening of the system's security?

--

I think I might as well extend this a bit: where can I read about generally insecure functions (the above mentioned man page seems to also disconsider execlp and execvp, but yet again I do not know why) -- why they are insecure, and the recommended alternatives?

[Note to any eventual moderators reading: I'm not sure this doesn't belong to Programming, if you consider it does, please *do* move it as my interest is for the thread to get the appropriate exposure, thank you, and sorry for any eventual trouble.]

jschiwal 11-29-2007 07:44 PM

Linux ignores suid and guid in scripts to avoid a race condition vulnerability.
Quote:

Originally Posted by http://www.linuxjunkies.org/html/Secure-Programs-HOWTO.html
When a program is executed, and its file has its setuid or setgid bit set, the process' EUID or EGID (respectively) is usually set to the file's value. This functionality was the source of an old Unix security weakness when used to support setuid or setgid scripts, due to a race condition. Between the time the kernel opens the file to see which interpreter to run, and when the (now-set-id) interpreter turns around and reopens the file to interpret it, an attacker might change the file (directly or via symbolic links).

You were testing a suid script.

The most basic reason for using exec() instead of system() is that the exec() has an argument requiring the path. system() simply calls /bin/sh with the argument you supplied.

Exec() also allows controlling the environment variables.

reverse 11-30-2007 04:00 AM

Quote:

You were testing a suid script.
I'm not sure I understand. Suppose we have the BINARY (a.out, ELF, whatever) "insecure" that calls "system("/bin/ls");" <- are you saying Linux will drop priviledges if INSECURE is SUID-ROOT? Or rather, /bin/ls won't get executed as SUID-ROOT because it is called as "/bin/sh -c /bin/ls" ?

Even if this were the case, my modifying IFS and PATH I'd still have to be able to "trick" `insecure` into executing "bin" with the argument "ls", even if the SUID bit is honoured or not.

Ok, let me just make a really practical example:
Code:

$ cat insecure.c
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv)
{
        printf("Executing: %s\n", argv[0]);
        system("/bin/ls");
        return EXIT_SUCCESS;
}
$ ./insecure
Executing: ./insecure
ALL.txt  insecure  insecure.c
$ ls -al insecure
-rwxrwxrwx 1 reverse reverse 6.5K 2007-11-30 11:54 insecure
$ echo As you can see its not SUID nor SGID
As you can see its not SUID nor SGID
$ cat bin
echo this should get executed
$ ls -al bin
-rwxrwxrwx 1 reverse reverse 30 2007-11-30 11:58 bin
$ export PATH="."
$ bin
this should get executed
$ export IFS="/"
$ echo "${IFS}"
/
$ insecure
Executing: insecure
ALL.txt  bin  insecure  insecure.c

So why is it that when I execute insecure the 2nd time, "bin" doesn't get executed? Since "/" is now delimiting command line arguments.

chrism01 12-02-2007 09:19 PM

There's a diff between
1. IFS (cmd PARAM separation)
2. path delimiters eg '/'
3. cmd delimiters ie ';'

given this is Linux, why don't you just <quote>use the source Luke<unquote> (ie read the src code of the 'cmds/progs' you want to understand).

reverse 12-03-2007 03:26 AM

Since my quest is to understand why the C system() call is insecure, I'm not sure what source I should read. Please be so kind as to tell me.

Also, I'm not sure what you mean with the "There's a diff between PARAM sep. and PATH delimiters". If I set "/" to delimit parameters, why would "/bin/ls" still be considered "program ls in directory bin" instead of "program bin with argument ls"?

/bin/ls : <PARAM SEPARATOR>bin<PARAM SEPARATOR>ls

chrism01 12-03-2007 06:47 PM

Re your 2nd qn: if you read the src code for the shell, you'll find out what you want to know, but in short I believe you'll find that the three concepts/delimiters I defined are treated SEPARATELY and differently. IOW, you cannot use IFS to affect the other 2.
HTH

Re qn 1. I expect the system() insecure thing is to do with passing params (possibly user supplied) to a shell which will then interpret them ie http://www.owasp.org/index.php/Command_Injection


All times are GMT -5. The time now is 03:24 AM.