...
Code Block | ||||
---|---|---|---|---|
| ||||
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 | ||||
---|---|---|---|---|
| ||||
/*
* 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
...