...
| Code Block | ||
|---|---|---|
| ||
/* 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'; /* Write operation to an unintended file like /etc/passwd * gets executed */ fwrite(x, sizeof(x[0]), sizeof(x)/sizeof(x[0]), fp); |
...
| 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 */
FILE * fp = fopen(argv[1], "w");
char x[100];
strncpy(x, argv[2], 100);
x[100] = '\0';
/* Write operation safe is safe within jail */
fwrite(x, sizeof(x[0]), sizeof(x)/sizeof(x[0]), fp);
|
An alternative sequence is to call chdir("chroot/jail") first and then chroot("."). However, calling chdir("/some/path") then chroot("/some/path") should be avoided as this sequence may be susceptible to a race condition. This is because 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.
...