...
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.
...