Linux - SecurityThis forum is for all security related questions.
Questions, tips, system compromises, firewalls, etc. are all included here.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
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.]
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.
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.
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"?
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
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.