fcheck prior to 2.07.59 - vulnerability - improper use of perl 'magic open'

Type securityvulns
Reporter Securityvulns
Modified 2001-03-22T00:00:00


VULNERABLE: Probably all versions prior to 2.07.59 - the author of fcheck can't be bothered to note security fixes in his change log, but most likely all prior versions had this vulnerability.

Vulnerability: by placing a carefully crafted filename in a directory checked by vulnerable versions of fcheck, commands caan be executed with the rights of the user running fcheck.


fcheck is a "poor man's tripwire" - it is a file integrity checker written in perl.

To accomplish some functions, it uses external programs, such as md5, md5sum and/or file.

These are accessed by issuing something on the order of:

 open(IN, "$program_name '$filename' |");
 $filesig = <IN>;
 close IN;

The problem is with the open() statement shown above.  The '|' causes the rest of the string to be interpolated, then sent to a command interpreter (a shell, such as sh, csh or bash) for execution, with its output coupled to the filehandle IN.

In the program under consideration, $program_name is under the control of the person who configured fcheck (presumably root) but $filename can be the name of any file placed into any directory which fcheck is instructed to check.

If one goes to a directory checked by fcheck and issues:

echo "test" >exploit\'\;\touch\ blah\\'

as written (this was tested on linux running bash), then runs fcheck, you will find that the file named blah has been created because the command 'touch blah' contained in the filename created above was executed. (Using the echo, rather than just touch'ing the file is needed because fcheck doesn't run the signatures on zero length files.)

So if this run by root, but checks files/directories writable by other than root, using the -s switch or checking files which cause the external $Filefunc command to be used, a problem exists.

The workaround, implmented in good version(s), is to do the following:

  if (open(IN, "-|"))
        $filesig =  <IN>;
        close IN;

} else   {      exec $program_name, $filename;  }

instead.  The multiple-argument version of exec wholly avoids any shell and therefore the interpretation of the metacharacters.