Blog-Icon_5_100x385

System Archaeology Through Testing

As you may be aware, I have been working on a Chef audit-mode cookbook
that implements the CIS Benchmarks. I recently added coverage for
Ubuntu 14.04. In this post, I want to share a discovery about OS-level
configuration that is inherently against the recommendation from the
benchmark, and the way users can remediate this using Chef.

In the CIS Benchmark for Ubuntu 14.04, section 13.7 states:

“Description: While the system administrator can establish secure permissions for users’ home directories, the users can easily override these.”

“Rationale: Group or world-writable user home directories may enable malicious
users to steal or modify other users’ data or to gain another user’s
system privileges.”

To implement this in Chef’s audit mode, I wrote a control that looks
like this:

control_group '13 Review User and Group Settings' do
  let(:user_dirs) do
    ud = {}
    Etc::Passwd.each do |u|
      unless (%w(root halt sync shutdown).include?(u.name) ||
        u.shell =~ /(\/sbin\/nologin|\/bin\/false)/)
        ud[u.name] = u.dir
      end
    end
    ud
  end

  control '13.7 Check Permissions on User Home Directories' do
    it 'has correct permissions for all non-system user home directories' do
      user_dirs.each_value do |user_dir|
        if File.directory?(user_dir)
          expect(file(user_dir)).to_not be_writable.by('group')
          expect(file(user_dir)).to_not be_readable.by('others')
          expect(file(user_dir)).to_not be_writable.by('others')
          expect(file(user_dir)).to_not be_executable.by('others')
        end
      end
    end
  end
end

Here, user_dirs is used in some other tests within the control group in the full file. It ensures that we’re only looking at the home directories for “non system” users – those who are not specifically root, halt, sync, or shutdown, or users with their shell set to nologin or false. I’m using the “bento” box that we publish for Ubuntu 14.04. Unfortunately, on this default installation, the test fails:

1) 13 Review User and Group Settings 13.7 Check Permissions on User Home Directories has correct permissions for all non-system user home directories
   Failure/Error: expect(file(user_dir)).to_not be_writable.by('group')
pected File "/var/lib/libuuid" not to be writable

This was surprising to me. This is distinctly a “system” home
directory, since it is in /var/lib, right? What is this
directory, and why is it writable by the group?

$ ls -ld /var/lib/libuuid
drwxrwsr-x 2 libuuid libuuid 4096 Apr 16  2014 /var/lib/libuuid

$ getent passwd | grep /var/lib/libuuid
libuuid:x:100:101::/var/lib/libuuid:

There is a libuuid “system” user – it has a low UID/GID. But what is creating the user and this directory? One might think there’s a libuuid package that creates this directory, as that is customary on Debian-based systems.

$ dpkg -S /var/lib/libuuid
dpkg-query: no path found matching pattern /var/lib/libuuid

No package owns this directory. We do have two “uuid” packages installed:

$ dpkg -l | grep uuid
ii  libuuid1:amd64 2.20.1-5.1ubuntu20  amd64 Universally Unique ID library
ii  uuid-runtime   2.20.1-5.1ubuntu20  amd64 runtime components for the Universally Unique ID library

These are part of the larger util-linux package. Since the packages themselves don’t manage this directory, perhaps there’s a postinst script that does.

$ grep /var/lib/libuuid /var/lib/dpkg/info/*.postinst
libuuid1:amd64.postinst:   useradd -d /var/lib/libuuid -K UID_MIN=$FIRST_SYSTEM_UID -K UID_MAX=$LAST_SYSTEM_UID -g libuuid libuuid
libuuid1:amd64.postinst:mkdir -p /var/lib/libuuid
libuuid1:amd64.postinst:chown libuuid:libuuid /var/lib/libuuid
libuuid1:amd64.postinst:chmod 2775 /var/lib/libuuid
libuuid1:amd64.postrm: rm -rf /var/lib/libuuid
uuid-runtime.postinst:   Useradd -d /var/lib/libuuid -K UID_MIN=1 -K UID_MAX=499 -g libuuid libuuid

Once the libuuid1 package is installed, it creates the libuuid user, makes its home directory, sets the owner and group, and then sets the permission to 2775. This mode causes the audit control test to fail, because it is group writable. This isn’t unusual, other packages in Ubuntu/Debian (and RHEL, to be fair), will create user for the package, or a service it provides, and may perform other system changes.

How do we remediate this finding? Can we just remove the offending packages?

$ sudo dpkg --purge libuuid1 uuid-runtime
dpkg: dependency problems prevent removal of libuuid1:amd64:
 rsyslog depends on libuuid1 (>= 2.16).
 util-linux depends on libuuid1 (>= 2.16).
 libcryptsetup4 depends on libuuid1 (>= 2.16).
 e2fsprogs depends on libuuid1 (>= 2.16).
 libblkid1:amd64 depends on libuuid1 (>= 2.16).
 wget depends on libuuid1 (>= 2.16).
 libxapian22 depends on libuuid1 (>= 2.16).
 libparted0debian1:amd64 depends on libuuid1 (>= 2.16).

dpkg: error processing package libuuid1:amd64 (--purge):
 dependency problems - not removing
(Reading database ... 48682 files and directories currently installed.)
Removing uuid-runtime (2.20.1-5.1ubuntu20) ...
Purging configuration files for uuid-runtime (2.20.1-5.1ubuntu20) ...
Processing triggers for man-db (2.6.7.1-1) ...
Errors were encountered while processing:
 libuuid1:amd64

Here, uuid-runtime is removed cleanly. However, libuuid1 is an dependency of other essential packages, and it’s the one that has a postrm that cleans up this directory. At this point, we still won’t pass the control (13.7) with the uuid-runtime package removed. There are a few possible remediations we can try.

  1. Remove the libuuid user/group. This may cause some libraries to fail, as it’s not clear why libuuid1 creates this user.
  2. Change the permission on the /var/lib/libuuid to remove the offending permission, g+ws.
  3. Change the home directory for the libuuid user to something else that doesn’t have group write permission. This may have unintended side effects though, for programs that write to the home directory of libuuid directly (since it’s in /var/lib).
  4. Change the audit mode test to allow the libuuid user, similar to how it allows the root, halt, sync, or shutdown users.
  5. Set a non-login shell for the libuuid user. I opened a bug for Ubuntu 14.04 proposing this. It’s fixed in later versions of Ubuntu, by way of import from Debian (version 8, recently released).

Since the audit-cis cookbook itself only implements audit mode tests, it does no remediation of findings. It’s up to end users to correct this in their own cookbooks.

user 'libuuid' do
  shell '/bin/false'
  home '/var/lib/libuuid'
  system true
end

The newly published libuuid-user cookbook serves to remediate the issue by managing the libuuid user, and also provide two levels of validation:

  1. Use audit mode to verify that the user’s shell is /bin/false.
  2. Use Serverspec to verify that the root user cannot su to the libuuid user.

It’s important to know that none of this addresses that the postinst does not specify a UID for the libuuid user, nor a GID for the libuuid group. In testing this, I uninstalled the uuid-runtime package (as output above shows), but reinstalled it, which recreated the user. The UID was different, but the home directory already existed without modification. This caused the control “13.13 check user home directory ownership” to fail. The recipe in the libuuid-user cookbook mentioned above does not handle this, as it is an unlikely scenario, but it’s something to be aware of when considering the list of potential remediation steps above.

Joshua Timberman

Joshua Timberman is a Code Cleric at CHEF, where he Cures Technical Debt Wounds for 1d8+5 lines of code, casts Protection from Yaks, and otherwise helps continuously improve internal technical process.