Versions Compared

Key

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

This recommendation Creating a jail is a defense in depth strategy that aims at isolating a user program or a daemon from the rest of the file system. It is only applicable to programs that do not need to continually maintain superuser status. The central idea is to create a jail so that entities that the program does not need to access under normal operation are made invisible. This makes it much harder to abuse a potential flaw that could otherwise lead to unconstrained system compromise. A jail may consist of world viewable programs that require fewer resources to execute than those that possibly exist on that system. Jails are only useful when there is no way to elevate privileges in the event of program failure.

Additionally, care must be taken to ensure that all the required resources (such as libraries, files and so on) are replicated within the jail directory and no reference is made to other parts of the filesystem file system from within this directory. It is also advisable to administer restrictive read/write permissions on the jail directories and resources based on the program's privilege requirements. Although, creating jails is an effective security measure when used correctly, it is not a surrogate for additional security best practices.

...

A security flaw exists in the code shown below resulting from the absence of proper canonicalization measures on the file path. This allows an attacker to traverse the filesystem 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
/*  Program running with elevated privileges where argv[1] and argv[2] are supplied by the user */

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

strncpy(x, argv[2], 100);
x[100] = '\0';

fwrite(x, sizeof(x[0]), sizeof(x)/sizeof(x[0]), fp);   /*  Write operation to an unintended file like /etc/passwd gets executed  */

...

This non-compliant coding example also violates FIO02-A. Canonicalize path names originating from untrusted sources and FIO03-A. Do not make assumptions about fopen() and file creation.

Compliant Solution

Wiki Markup
Some Unix based systems (such as OpenBSD) encourage restricting
filesystem
 file system access by recommending the creation of a {{chroot()}} jail. The {{chroot}} jail requires care to implement securely \[[Wheeler 03|AA. C References#Wheeler 03]\]. This is achieved by passing a predefined directory name as an argument to {{chroot()}}. The call to {{chroot()}} requires superuser privileges and thus the program should be set-uid root. However, this call does not
'
 _leave
'
_ the process inside the jail directory as one would expect. The {{chdir()}} call that follows does just this and is indispensable when access is to be restricted to within the jail boundaries.

Another essential step is to drop superuser privileges permanently after these calls so as to be in agreement with 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) and may be ineffective if the current working directory is not set to the new root directory immediately following the call to chroot(). Successful jail creation prevents unintentional filesystem 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 filesystemfile 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 */

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

...