Bug 4647 - Insecure temporary file handling in the Globus Toolkit
: Insecure temporary file handling in the Globus Toolkit
Status: CLOSED FIXED
: Java WS Security
Authentication
: 4.0.2
: PC Windows XP
: P3 normal
: 4.0.3
Assigned To:
:
:
:
:
  Show dependency treegraph
 
Reported: 2006-08-08 08:56 by
Modified: 2008-01-11 15:56 (History)


Attachments
Fixes for patching the Java Components (534 bytes, text/plain)
2006-08-08 19:46, Rachana Ananthakrishnan
Details
Update Java Component fixes (773 bytes, text/plain)
2006-08-09 11:50, Rachana Ananthakrishnan
Details


Note

You need to log in before you can comment on or make changes to this bug.


Description From 2006-08-08 08:56:23
Insecure temporary file handling in the Globus Toolkit
Alex Lambert   lamberta@ncsa.uiuc.edu

Background
In my work with MyProxy, I found a temporary file handling vulnerability. While
researching this issue, I found similar issues in other components of the
Globus Toolkit.

Temporary file use today
myproxy-admin-adduser is a Perl script that an administrator runs (as
root) to add a user to the local MyProxy database.

   $certfile = "/tmp/myproxy_adduser_cert.pem";
   $reqfile = "/tmp/myproxy_adduser_cert_request.pem";
   $keyfile = "/tmp/myproxy_adduser_key.pem";
   ...
   system("grid-ca-sign", "-in", $reqfile, "-out", $certfile, "-force");
   system("myproxy-admin-load-credential", "-c", $certfile, "-y", $keyfile);

grid-ca-sign is a shell script that signs a given certificate request.
It is invoked internally by myproxy-admin-adduser; it can also be run on its
own. It is part of the SimpleCA package.

   TMP_REQ_FILE=/tmp/tmp_cert_req.pem.$$
   TMP_CERT_FILE=/tmp/tmp_cert.pem.$$
   cp ${INPUT_REQ_FILE} ${TMP_REQ_FILE}
   ...
   openssl ca ... -in ${TMP_REQ_FILE} -out ${TMP_CERT_FILE}

grid-security-config is a shell script that installs a new certificate
authority. It is run by setup-gsi after a new CA package is installed.
Each CA package created by SimpleCA includes a customized version of
grid-security-config. (The following is from the Globus Certificate Service
package.)

   TEMP_FILE1=/tmp/grid-security-config_1.$$
   ...
   cp ${TEMP_FILE1} /etc/grid-security.conf.b38b4d8c

The problem
A secure program ensures that each temporary file is exclusively under its
control. Several Globus tools fail to take appropriate precautions before using
temporary files.

Attacks
The attacker can set up a link from the temporary file to a sensitive file. For
example, linking /tmp/myproxy_adduser_key.pem to /etc/passwd would cause the
password file to be overwritten with a certificate request the next time
myproxy-admin-adduser is run.

The attacker can also create the file himself and set relaxed permissions. For
example, an attacker could create /tmp/grid-security-config_1.$$ as a
world-readable, world-writable file. The attacker could examine and modify the
temporary file as grid-security-config is running. (The attacker would need to
know the process ID of grid-security-config. Predicting a process ID is easy on
many systems. Alternatively, he could create a file for each of the system's
possible process IDs.)

Real-world exploits
I have exploits for both myproxy-admin-adduser and grid-ca-sign. An attacker
can force the CA to sign an arbitrary certificate request. The attacker must be
able to write to files in /tmp and win several race conditions. The method is
the same for both targets: create a world-writable file in /tmp with the
appropriate name, and then replace the temporary certificate request with a
request generated by the attacker at the appropriate time.

I also have a exploit for grid-security-config. An attacker can gain the
privileges of the user running the setup-gsi script (usually, root). The
attacker must be able to write to files in /tmp and win several race
conditions. The grid-security.conf file is a shell script. After the temporary
grid-security.conf file is written, the attacker appends his own commands to
the end of the file. (In my particular exploit, I drop a setuid copy of /bin/sh
into /tmp.) Later in the setup process, when the configuration file is sourced
by grid-cert-request-config, the attacker's commands are executed.

I have not evaluated the feasibility of winning the race conditions in any of
these exploits.

Fixing the problem in C
The mkstemp(3) function securely creates a temporary file. It accepts one
argument, a pointer to the first character of a string containing a template
for the file name. Trailing 'X' characters in the template are replaced with
random characters. For example, the template
/home/lamberta/.tmp/globus-XXXXXXXXXX could become
/home/lamberta/.tmp/globus-iYthHkHFfW.

The secure temporary file algorithm (used in mkstemp(3)) is:

   create a random file name based on the template
   try to open() that file with flags O_CREAT | O_EXCL
      O_CREAT is "create the file if it does not exist"
      O_EXCL is "fail if the file already exists"
   if successful, stop and return the file name; otherwise, repeat

Fixing the problem in Perl: myproxy-admin-adduser A Perl module, File::Temp,
provides for secure temporary file creation.
File::Temp is included with Perl  5.6.1 and later. (I have submitted a patch
for myproxy-admin-adduser.)

Python has a similar module, tempfile.

Fixing the problem in shell scripts: grid-ca-sign, grid-security-config No
widely-portable mechanism exists for securely creating temporary files in shell
scripts.

In general, there is no way to open a file with flags O_CREAT | O_EXCL in a
shell script.

One workaround is to create a temporary directory and then store files within
that directory. This works because the mkdir(1) command will fail if the
directory already exists. (The GNU libc documentation says that "directory
creation always works like open with O_EXCL.")

Another workaround is to use an external utility to implement temporary file
creation. mktemp(1), first implemented in OpenBSD, is a wrapper around
mkstemp(3). It is present in recent Linux and BSD systems, but it is not
installed by default on (e.g.) Solaris < 10.

Scope of the problem
I downloaded the Globus CVS repository and ran grep with strings like "/tmp"
and "$$". I found a number of places in which temporary files may be used
insecurely. (I have not done more than a casual inspection of each instance,
though.)

* gsi/ssl_utils/source/library/sslutils.c proxy_marshal_tmp() (writes a user's
proxy!)
* common/source/library/globus_object_hierarchy.h.sh
* common/source/programs/globus-sh-exec.in
*
data_management/multirft/src/org/globus/ogsa/impl/base/multirft/TransferClient.java
noTptNonExtendedTransfer() noTptTransfer()
* gram/jobmanager/source/globus_gram_job_manager_request.c
globus_gram_job_manager_request_open_logfile()
* gsi/{cert,ssl}_utils/source/programs/grid-cert-renew.in
* gsi/simple_ca/setup/setup-simple-ca generate_ca_certificate()
* io/source/library/globus_io_error_hierarchy.h.sh
* ogsa-c/build_tools/cvs-build-ogsa my_system()
* replica/rls/client/java/RLSGui.java actionPerformed()
* replica/rls/server/conf.c conf_read()
* workspace/vm/backend/workspace/vms/xen/xen_v2.py run_guc()
* ws-rendezvous/client/c/test/rendezvous-notification-test.pl
* ws-transfer/reliable/client/c/crft_util/test/simple-trans.pl

For many of these issues, the fix is easy: use the language's implementation of
mkstemp(3). There is no straightforward solution for fixing the shell scripts,
though.

A general solution for shell scripts
It is not reasonable to expect that mktemp(1) is installed on every machine
running Globus.

Globus already has a small library for handling command-line arguments in shell
scripts. Another small library, for safe temporary file handling, should be
added.

The temporary file library for Globus shell scripts The library is just a
simple wrapper around mktemp(1) and mkdir(1).

Several convenience functions could exist; they would wrap
globus_create_temp().

Psuedocode for globus_create_temp():

globus_create_temp(is_file, prefix, parent, perms):
   if is_file
      set umask; try mktemp $parent/$prefix-XXXXXXXXXX
      if successful
         set permissions
         return name
      else   /* mktemp didn't work */
         fail
   else   /* is directory */
      set umask; try mktemp -d $parent/$prefix-XXXXXXXXXX
      if successful
         set permissions
         return name
      else   /* mktemp didn't work */
         set umask; try mkdir $parent/$prefix-$$-${RANDOM}...
         if successful
            set permissions
            return name
         else   /* mkdir didn't work */
            fail

Since creating a temporary file will fail on systems without mktemp(1),
existing scripts should be changed to use files within temporary directories.

If a directory is requested and mktemp(1) is not available, the function will
attempt to generate a unique directory name. The name consists of the
appropriate prefix, the process ID, and several random numbers from ${RANDOM},
a built-in random number generator present in some shells.

The shell's PRNG is not likely to be cryptographically strong, and not all
shells implement ${RANDOM}. (Perhaps we can use OpenSSL's command-line utility
instead...) It is possible that an attacker will be able to predict the name of
the temporary directory and create it before the script can; in this case, the
directory creation will fail. Scripts must be modified to safely handle this
situation.

A complication
Michal Zalweski proposed that even mkstemp(3) is insufficient for safely
creating temporary files in /tmp. He says:

'tmpwatch' is a handy utility that removes files which haven't been accessed
for a period of time...By default, it is installed with a crontab entry that
sweeps /tmp directory on a daily basis, deleting files that have not been
accessed for past few days...Numerous Linux systems, such as Red Hat, ship with
cron daemon running and 'tmpwatch'
configured to sweep /tmp.

He suggests that if it is possible to force a process to pause for several days
(either by sending it SIGSTOP, or by creating a large amount of work), a
tmpwatch-like utility could remove a file that is still in use. The attacker
could then take control of the file.

Zalweski recommends avoiding /tmp and using private temporary directories (e.g.
in the user's home) whenever possible.

All of the Globus applications that I have seen would work with a private
temporary directory.

Future solutions
The mktemp(1) utility is under the BSD license. Additionally, the author
states, "If you are an OS vendor who would like to bundle mktemp(1) but its
license is unacceptable to you, please contact me - we can probably work
something out." Could mktemp(1) be included or made a prerequisite in a future
version of the Toolkit?

Sources
Python Library Reference: tempfile
   http://docs.python.org/lib/module-tempfile.html

mktemp(1)
   http://www.mktemp.org/mktemp/

"Common use of 'tmpwatch' utility and alikes triggers race conditions,"
Michal Zalewski
   http://lcamtuf.coredump.cx/tmp_paper.txt

"Secure Programming for Linux and Unix HOWTO: Temporary Files," David Wheeler
   http://www.dwheeler.com/secure-programs/Secure-Programs-HOWTO

"Safely creating temporary files in shell scripts," Stefan Nordhausen
   http://www.linuxsecurity.com/content/view/115462/151/

The GNU C Library: Temporary Files

http://www.gnu.org/software/libc/manual/html_node/Temporary-Files.html

Changes in Perl 5.6.1
   http://perldoc.perl.org/perl561delta.html

Perl Documentation: File::Temp
   http://perldoc.perl.org/File/Temp.html
------- Comment #1 From 2006-08-08 08:59:33 -------
Summary of Java side fixes: 

A utility method has been added to CoG (org.globus.util.Util::createFile), that
can be used to "securely" create a file. That method checks if file already
exists, if so tries to delete it and create again. If either deletion of old
file or creation of new one fails for any reason, an exception is thrown.

The "Util.setPermissions(fileName, 600)" method has been encapsulated into a
separate method, setOwnerAccessOnly(fileName).

All files created in GSI code in CoG and the Java WS Security code has been
updated to use the above utility to create file and set permissions before
anything is written to the file. These fixes have been pushed to trunk, 4.0
branch and community branch.

No soulution has been found to atomically create a file and set relevant
permissions as yet. The current plan is to add a note about it in the advisory
and ask folks to use a umask that would restrict access created to the file.
------- Comment #2 From 2006-08-08 13:36:26 -------
A few of these are not real problems:

* gsi/ssl_utils/source/library/sslutils.c proxy_marshal_tmp() (writes a user's
proxy!)
* gsi/ssl_utils/source/programs/grid-cert-renew.in

The ssl_utils package is obsolete since GT 2, so these aren't an issue. I've
removed these from 3.2 branch and the trunk.

joe
------- Comment #3 From 2006-08-08 13:50:15 -------
RFT related updates:
John removed ws-transfer/reliable/client/c/crft_util/test/simple-trans.pl as it
is  not being used at all. 
I will fix the other two files under data-management/multirft once new cog jar
with utility api is added to 3.2 cvs.
------- Comment #4 From 2006-08-08 15:06:25 -------
grid-cert-renew is also not part of any 3.2 or later distribution (included,
but not in the makefile so never seen).

I committed fix for gsi/simple_ca/setup/setup-simple-ca to 3.2, 4.0, 4.0
community, and trunk

joe
------- Comment #5 From 2006-08-08 15:21:20 -------
Since grid-cert-renew isn't installed by the Makefile.am, I removed
grid-cert-renew.in and the configure.in line which creates it from the
cert_utils/source package

joe
------- Comment #6 From 2006-08-08 15:43:07 -------
ws-gram (trunk and 4.0 branch) code uses File.createTemp file and sets
permissions for a temporary file it creates and other file write is to
$G_L/var. The delegated proxy is written out to file using a tool, but to
~/.globus directory, so no issues there.

ws-rendezvous does not have any file access.
------- Comment #7 From 2006-08-08 19:46:53 -------
Created an attachment (id=1028) [details]
Fixes for patching the Java Components
------- Comment #8 From 2006-08-09 09:28:35 -------
Fixes for myproxy have been committed to myproxy cvs head.
------- Comment #9 From 2006-08-09 11:22:25 -------
Temp file creations are fixed in ws-transfer in globus_4_0_branch and trunk.
Still need to fix globus_3_2_branch
------- Comment #10 From 2006-08-09 11:42:23 -------
1) Java GSI: Fixes committed to trunk, globus_4_0_branch, globus_4_0_community
and globus_3_2_branch.

2) CAS: Fixes applied to all branches.

3) Delegation Service: No fixes were required, since only persistence of
resource uses files.

4) GRAM: No fixes were required in Java code in any of the branches. 4.x code
uses some tools to write out proxy and Joe Bester reviewed that code, no fixes
were required.
------- Comment #11 From 2006-08-09 11:45:28 -------
No file handling code was found in ws-rendezvous module.
------- Comment #12 From 2006-08-09 11:50:22 -------
Created an attachment (id=1029) [details]
Update Java Component fixes
------- Comment #13 From 2006-08-09 13:32:58 -------
Dynamic accounts, virtual workspaces, and GridShib are not currently released
with GT.  The python temp file use in the candidate list under workspace/ is
from code in development, these issues will be addressed before next release.
------- Comment #14 From 2006-08-09 13:44:41 -------
Fixes committed in globus_3_2_branch and multirft under ogsa trunk.
------- Comment #15 From 2006-08-09 13:56:50 -------
Committed changes to job manager to use mkstemp for script interface files.
Don't fall back to writing a log file in /tmp if /home is not writable.
------- Comment #16 From 2006-08-09 14:04:51 -------
* io/source/library/globus_io_error_hierarchy.h.sh

This is not part of any supported release.  It was replaced by xio and
io/compat in 3.2.
------- Comment #17 From 2006-08-10 14:14:50 -------
WS-MDS is now okay (there were minor problems with two test programs, neither
of which is run by default.

3.2 MDS looks like it has a few issues in information providers; I'm working on
those now.
------- Comment #18 From 2006-08-10 15:01:53 -------
Committed fixes to c wsrf core tests, ws-rendezvous and ws-gram tests. Add new
perl module to globus_c_wsrf_core_tools to start containers without using any
files in /tmp and updated tests to use that.

Committed fix to pre-ws GRAM to use mkstemp for creating files in /tmp

joe
------- Comment #19 From 2006-08-11 03:03:10 -------
Committed fix to globus_rls_server to prevent inadvertent use of /tmp for bloom
filter storage. Fixed in trunk, globus_4_0_branch, and globus_3_2_branch. No
other fixes pending for RLS or DRS.
------- Comment #20 From 2006-08-11 12:01:37 -------
Checked in 3.2 MDS fixes.
------- Comment #21 From 2006-08-16 09:29:46 -------
Security Advisory:
http://www-unix.globus.org/mail_archive/security-announce/2006/08/msg00001.html