# C system() function vulnerability

Suppose we have the following program:

#include <stdlib.h>
#include <stdio.h>

int main()
{
char *user = getenv("USER");
char buffer[4096];

if (user) {
snprintf(buffer, sizeof buffer, "/bin/echo %s", user);
system(buffer);
}

return 0;
}


Is it possible for a user to cause this program to execute arbitrary commands?

• Do you have actual code that compiles and demonstrates the vulnerability?
Nov 30 '11 at 16:44
• Vulnerability? Where? If that's your real buffer string, then it's going to cause a syntax error in the shell.
– Marc B
Nov 30 '11 at 16:45
• I do have a method in mind, which I'm pretty sure would work, but I'm not sure I want to tell you without knowing more. Why do you want to exploit this/a vulnerability? Nov 30 '11 at 16:47

If this is actually in live code somewhere, then whomever wrote it should be forced to write I will never call system on tainted user input again 1 googol times with a dull pencil. Yes. As written, this code contains an exploit. Here's a simple example.
tmp$cat foo.c #include <stdlib.h> #include <stdio.h> int main() { char *user = getenv("USER"); char buffer[4096]; if (user) { snprintf(buffer, sizeof buffer, "/bin/echo %s", user); printf("running %s\n", buffer); system(buffer); } return 0; } tmp$ gcc foo.c
tmp$mkdir /tmp/xxx tmp$ ls -ld /tmp/xxx
tmp$USER='foo; rm -fr /tmp/xxx' ./a.out running /bin/echo foo; rm -fr /tmp/xxx foo tmp$ ls -ld /tmp/xxx
tmp$ If you want to print out the value of the USER environment variable, you can do: fprintf(stderr, "%s", getenv("USER"));  There's no need to call system();. • I can't modify the code... It's a wargame... – Mito Nov 30 '11 at 16:54 • What kind of wargame? There aren't many games for Linux. – satuon Nov 30 '11 at 17:06 Others have told you how to exploit this. In the spirit of advocating the right way to do things, here is a good way to execute echo with user input and not have vulnerabilities (barring of course some bug in echo :-)): execlp("echo", string_from_user, NULL);  If you deal directly with the exec family of syscalls, you can pass unadulterated strings directly to the program without any chance that the shell will misinterpret them, because there is no shell in that case. Hence there is no need to escape. There are more potential security problems with code like this. Here are some that I can think of: • If an untrusted user can modify /bin/echo, obviously that untrusted user can make this run arbitrary code. • If an untrusted user can modify the PATH environment variable, my execlp example above is vulnerable. One workaround is to not use the -p variants of the exec family of syscalls, because those will not check PATH. It is not possible. You'd have to write something that changes the USER environment parameter that effectively backspaces over the previous characters, and system("string") does not actually use a shell through a pseudo-terminal to execute, which is where backspace processing happens. edit: Despite comments below, and a down-vote, they are incorrect. /bin/sh processing (or whatever shell is specified) only processes backspace & other edit characters when attached to a terminal device for input. In addition, the original author is intent on subverting a program not of his own making. • This is incorrect. The string passed to system() is interpreted by the shell, and the shell responds to many different special characters - backspace is not necessary. – caf Nov 30 '11 at 23:40 • According to Open Group system() definitely calls the shell. Dec 1 '11 at 3:17 • I disagree. Shell backspace processing occurs only with pseudo-terminals, which is not what system("") does. Dec 1 '11 at 15:12 • The vulnerability is not in some program using backspace characters, the vulnerability is in other shell characters. For example semicolons, backticks, ampersands, $(rm -rf /), etc. Dec 4 '11 at 7:13
• @AndyFinkenstadt - shell backspace processing may be limited to pseudo-terminals. The Open Group standard specifies that system(x) is equivalent to execl(<shell path>, "sh", "-c", x, (char *)0). If the USER environment variable contains something like "foo; rm -fr /" then it would cause problems when the program is run as a privileged user. Also note that there is nothing special about the USER environment variable that forbids you from changing it. Dec 5 '11 at 17:06