Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Updated links to include FIO17

...

A security flaw exists in this noncompliant code example resulting from the absence of proper canonicalization measures on the file path. This allows an attacker to traverse the file system and possibly write to a file of his choice, with the privileges of the vulnerable program. For example, it may be possible to overwrite the password file (such as the /etc/passwd, common to many POSIX based systems) or a device file such as the mouse which in turn can aid further exploitation or cause a denial of service to occur.

Code Block
bgColor#ffcccc

enum { array_max = 100 };

/*
 * Program running with elevated privileges where argv[1] 
 * and argv[2] are supplied by the user 
 */

char x[array_max];
FILE *fp = fopen(argv[1], "w");

strncpy(x, argv[2], array_max);
x[array_max - 1] = '\0';

/* 
 * Write operation to an unintended file like /etc/passwd 
 * gets executed  
 */
if (fwrite(x, sizeof(x[0]), sizeof(x)/sizeof(x[0]), fp) <
    sizeof(x)/sizeof(x[0])) {
  /* Handle Error */
}

...

Another essential step is to drop superuser privileges permanently after these calls (see POS02-C. Follow the principle of least privilege). The chroot() system call is not secure against the superuser changing the current root directory (if privileges are not dropped). Successful jail creation prevents unintentional file system access even if an attacker gives malicious input, such as through command-line arguments.

Code Block
bgColor#ccccff

/*
 * Make sure that the chroot/jail directory exists within 
 * the current working directory. Also assign appropriate 
 * permissions to the directory to restrict access. Close 
 * all file system descriptors to outside resources lest 
 * they escape the jail.
 */

if (setuid(0) == -1) {
  /* Handle error */
}

if (chroot("chroot/jail") == -1) {
  /* Handle error */
}

if (chdir("/") == -1) {
  /* Handle error */
}

/* Drop privileges permanently */
if (setgid(getgid()) == -1) {
  /* Handle error */
}

if (setuid(getuid()) == -1) {
  /* Handle error */
}

/* Perform unprivileged operations */
enum {array_max = 100};

FILE *fp = fopen(argv[1], "w");
char x[array_max];
strncpy(x, argv[2], array_max);
x[array_max - 1] = '\0';

/* Write operation safe is safe within jail */
if (fwrite(x, sizeof(x[0]), sizeof(x)/sizeof(x[0]), fp) <
    sizeof(x)/sizeof(x[0])) {
  /* Handle error */
}

...

      09. Input Output (FIO)      Image Modified