You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 71 Next »

Many programs and libraries, including the shared library loader on both UNIX and Windows systems, depend on environment variable settings. Because environment variables are inherited from the parent process when a program is executed, an attacker can easily sabotage variables, causing a program to behave in an unexpected and insecure manner [[Viega 03]].

All programs, in particular those running with higher privileges than the caller (such as those with setuid/setgid flags), should treat their environment as untrusted user input. Because the environment is inherited by processes spawned by calls to the fork(), system(), or exec() functions, it is important to verify that the environment does not contain any values that can lead to unexpected behavior.

The best practice for such programs is to:

This rule is a more specific instance of STR02-A. Sanitize data passed to complex subsystems.

C99 states that, "the set of environment names and the method for altering the environment list are implementation-defined." It is therefore important to understand what local functions are available for clearing, modifying, and looking up default values for environment variables. Because some programs may behave in unexpected ways when certain environment variables are not set, it is important to understand which variables are necessary on your system and what are safe values for them.

The non-standard function clearenv() may be used to clear out the environment where available, otherwise it can be cleared by obtaining a list of environment variable names from environ and removing each one using unsetenv().

POSIX also specifies the confstr() function which can then be used to look up default values for environment variables [[Open Group 04]]. POSIX.1-2008 defines a new _CS_V7_ENV argument to confstr() to retrieve a list of environment variable settings required for a default conforming environment [[Austin Group 08]]. A space-separated list of variable=value pairs is returned, with variable names guaranteed not to contain equal signs, and variable=value pairs guaranteed not to contain spaces. Used together with the _CS_PATH request illustrated above, this completely describes the minimum environment variable settings required to obtain a clean conforming environment. On systems conforming to the POSIX.1-2008 standard, this should be used to create a sanitized environment.

If it is explicitly known which environment variables need to be kept, [[Viega 03]] defines a function, spc_sanitize_environment(), which will remove everything else.

Non-Compliant Code Example (POSIX) (ls)

This non-compliant code invokes the C99 system() function to execute the /bin/ls program. The C99 system() function passes a string to the command processor in the host environment to be executed.

if (system("/bin/ls dir.`date +%Y%m%d`") == -1) {
  /* handle error */
}

Although IFS does not affect the command portion of this string, /bin/ls, it does determine how the argument is built after calling date. If the default shell does not ignore the incoming value of the IFS environment value, and an attacker sets IFS to ".", the intended directory will not be found.

Compliant Solution (POSIX) (ls)

In this compliant solution, the environment is cleared by clearenv() and then the PATH and IFS variables are set to safe values before invoking system().

char *pathbuf;
size_t n;

if (clearenv() != 0) {
  /* Handle Error */
}

n = confstr(_CS_PATH, NULL, 0);
if (n == 0) {
  /* Handle Error */
}

if ((pathbuf = malloc(n)) == NULL) {
  /* Handle Error */
}

if (confstr(_CS_PATH, pathbuf, n) == 0) {
  /* Handle Error */
}

if (setenv("PATH", pathbuf, 1) == -1) {
  /* Handle Error */
}
if (setenv("IFS", " \t\n", 1) == -1) {
  /* Handle Error */
}

if (system("/bin/ls dir.`date +%Y%m%d`") == -1) {
  /* Handle Error */
}

Sanitizing a shell command can be difficult and doing so can adversely affect the power and flexibility associated with them.

Compliant Solution (Windows)

There is no portable or guaranteed way to clear out the environment under Windows. Following the recommendations of ENV04-A. Do not call system() if you do not need a command processor, care should be taken to use _execle(), _execlpe(), _execve(), or _execvpe() instead of system() because they allow the the environment to be explicitly specified.

Automated Detection

Compass/ROSE could detect violations of this recommendation. It should ensure that any call to system() or the exec() family (excluding those functions that provide their own environment) is preceded by a call to clearenv().

Risk Assessment

Invoking an external program in an attacker-controlled environment is dangerous.

Recommendation

Severity

Likelihood

Remediation Cost

Priority

Level

ENV03-A

high

likely

high

P9

L2

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this rule on the CERT website.

References

[[Austin Group 08]] vol. 2, System Interfaces, confstr()
[CA-1995-14] "Telnetd Environment Vulnerability"
[[Dowd 06]] Chapter 10, "UNIX II: Processes"
[[ISO/IEC 9899:1999]] Section 7.20.4, "Communication with the environment"
[[ISO/IEC PDTR 24772]] "XYS Executing or Loading Untrusted Code"
[[Open Group 04]] Chapter 8, "Environment Variables", confstr()
[[Viega 03]] Section 1.1, "Sanitizing the Environment"
[[Wheeler 03]] Section 5.2, "Environment Variables"


ENV02-A. Beware of multiple environment variables with the same effective name      10. Environment (ENV)       ENV04-A. Do not call system() if you do not need a command processor

  • No labels