Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
bgColor#ffcccc
langc
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 such as /etc/passwd
 * gets executed
 */
if (fwrite(x, sizeof(x[0]), sizeof(x)/sizeof(x[0]), fp) <
    sizeof(x)/sizeof(x[0])) {
  /* Handle error */
}

An attacker can control the value of argv[1] and consequently access any resource on the file system.

...

Some UNIX-based systems (such as OpenBSD) can restrict file system access by creating a chroot() jail. The chroot() jail requires care to implement securely [Wheeler 2003AA. Bibliography#Wheeler 03]. It is achieved by passing a predefined directory name as an argument to chroot(). The call to chroot() requires superuser privileges. However, this call does not leave the process inside the jail directory as might be expected. A subsequent chdir() is required to restrict access to the jail boundaries.

...

Code Block
bgColor#ccccff
langc
/*
 * 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 is safe within jail */
if (fwrite(x, sizeof(x[0]), sizeof(x)/sizeof(x[0]), fp) <
    sizeof(x)/sizeof(x[0])) {
  /* Handle error */
}

An alternative sequence is to first call chdir("chroot/jail") and then call chroot("."). However, calling chdir("/some/path"), then chroot("/some/path"), should be avoided because this sequence may be susceptible to a race condition: an attacker with sufficient privileges can arrange for /some/path to refer to different directories in the two system calls. Consequently, the program will not have its current working directory set to the new root directory. Using either chdir("/") after chroot() or chroot(".") after chdir() guarantees that the current working directory will be the same directory as the new root.

...

Bibliography

 

...

Image Modified