Bug 581884

Summary: latent privilege escalation via /var/lock group write permission
Product: [Fedora] Fedora Reporter: Wietse Venema <wietse>
Component: lockdevAssignee: Jiri Popelka <jpopelka>
Status: CLOSED RAWHIDE QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: low Docs Contact:
Priority: low    
Version: rawhideCC: jpopelka, ovasik
Target Milestone: ---   
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: lockdev-1.0.3-5.fc14 Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2010-04-19 16:29:55 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Wietse Venema 2010-04-13 13:41:23 UTC
Description of problem:

The directory /var/lock is writable by unprivileged processes
with the "lock" groupid, for example, processes that execute
the set-gid /usr/sbin/lockdev command.

Scripts in /etc/init.d create and remove files as root, under 
subdirectories of the /var/lock directory (see listing below).

This is a latent privilege escalation vulnerability.  If the set-gid
/usr/sbin/lockdev command has a vulnerability, then an unprivileged
user on the system can symlink /var/lock/subsys to a directory with
critical files (such as /etc), and trick the /etc/init.d scripts
into creating or removing files as root in that directory.

-rwx--s--x 1 root lock 17336 Sep 25  2009 /usr/sbin/lockdev
drwxrwxr-x 5 root lock  4096 Apr 12 15:50 /var/lock
drwxr-xr-x 2 root root  4096 Oct 16 07:46 /var/lock/dmraid
drwx------ 2 root root  4096 Apr 12 19:44 /var/lock/lvm
drwxr-xr-x 2 root root  4096 Apr 12 19:45 /var/lock/subsys

Other attacks may be possible, such as attacks that replace
the directories /var/lock/dmraid or /var/lock/lvm by symlinks to
critical directories, but these have not been investigated.

Why this is privilege escalation
--------------------------------

This is privilege escalation, because an unprivileged user who can
subvert the lockdev program would be able to symlink /var/lock/subsys
to some other directory (such as /etc), and trick the /etc/init.d
scripts into creating or removing files as root in that directory.

In other words, by making /usr/sbin/lockdev set-gid, it is given 
much of the power of a set-uid root program.

Why this is a latent vulnerability
----------------------------------

This is a latent vulnerability, as long as there is no known exploit
for /usr/sbin/lockdev.

Possible solutions
------------------

a) Do not make /var/lock group-writable. This is the configuration
of, for example, Ubuntu 9.10, It appears to break no functionality,
and is the simplest solution.

b) Do not create/remove files as root, when a directory is writable
by non-root processes. This requires changes to all the /etc/init.d
scripts.

c) Use a safe pathname resolver as discussed in Chari et al.'s NDSS
paper, see "additional information" below. This involves changes
to the library or file system code.

Version-Release number of selected component (if applicable):

Fedora Core 12 and 11. Similar file permissions are found with older
releases such as RedHat 7.3, but these systems haven't been analyzed.

How reproducible:

Exploitation requires a vulnerability in the set-gid /usr/sbin/lockdev 
command, to escalate "lock" group privilege to "root".

Steps to Reproduce:

This example exploits the commands in the /etc/init.d/killall script,
which executes at system shutdown (or reboot) time. Other exploitation
(for example, at system start-up time) may also be possible but has
not been investigated.

1. As an unprivileged user, exploit a vulnerability in the set-gid
/usr/sbin/lockdev command.

2. Having acquired group "lock" privileges, replace /var/lock/subsys
by a symlink to /etc.

3. Wait until the system shuts down (or reboots). The system will
execute the script /etc/rc0.d/S00killall (or /etc/rc6.d/S00killall),
which is symlinked to /etc/init.d/killall. The commands in this
script will be executed as root.

The main body of this script is:

    for i in /var/lock/subsys/* ; do
            # Check if the script is there.
            [ -f "$i" ] || continue

            # Get the subsystem name.
            subsys=${i#/var/lock/subsys/}

            # Networking could be needed for NFS root.
            [ $subsys = network ] && continue

            # Bring the subsystem down.
            if [ -f /etc/init.d/$subsys.init ]; then
                    /etc/init.d/$subsys.init stop
            elif [ -f /etc/init.d/$subsys ]; then
                    /etc/init.d/$subsys stop
            else
                    rm -f "$i"
            fi
    done

For example, if /var/lock/subsys is symlinked to /etc, then this
script will remove any file named /etc/FOO for which no script file
exists named /etc/init.d/FOO or /etc/init.d/FOO.init.

Actual results:

File destruction. Other exploits may create files in unexpected 
places, but this has not been investigated.

Expected results:

An exploit in a set-gid program should never allow random users
to create or delete files as root.

Additional info:

Suresh Chari. Shai Halevi Wietse Venema. Where Do You Want to Go
Today? Escalating Privileges by Pathname Manipulation. 17th Annual
Network & Distributed System Security Conference (NDSS 2010).
http://www.isoc.org/isoc/conferences/ndss/10/pdf/19.pdf.

Comment 1 Ondrej Vasik 2010-04-13 15:58:08 UTC
Thanks for report.
Adding lockdev maintainer to cc to know his opinion about the change to 755 ... I think you have other possibilities - like lowering capabilities for lockdev setgid binary, some SELinux rules for /sbin/lockdev . Basic unix file rights are not perfect anyway (as they do depend on UID/GID numbers, which may differ on various systems). I'll investigate it a bit more ...

Comment 2 Jiri Popelka 2010-04-16 09:38:43 UTC
(In reply to comment #0)
> Possible solutions
> ------------------
> a) Do not make /var/lock group-writable. This is the configuration
> of, for example, Ubuntu 9.10, It appears to break no functionality,
> and is the simplest solution.

Hi,
/usr/sbin/lockdev is a set-gid binary that creates lock files for e.g. ttyS0 in
/var/lock so regular users don't need write access there.

AFAIK Debian/Ubuntu do not ship this set-gid binary like Fedora.
Liblockdev1 package in Debian/Ubuntu ships only the shared library.

I looked into Debian testing / Ubuntu 10.04 and
/var/lock is group-writable there:
drwxrwxrwt  2 root root 4096 2010-04-15 07:47 /var/lock

I'm sorry, but I still don't understand how the set-gid lockdev could create lock files in /var/lock when we make /var/lock not group-writable.

I'll be thinking about some lowering capabilities for lockdev.

Comment 3 Ondrej Vasik 2010-04-16 10:21:06 UTC
Thanks, Jiri ... I think it should be kept group writable. Lowering capabilities in lockdev seems to be good compromise for me. Reassigning to lockdev, I'm not going to reduce permissions on /var/lock in filesystem package. If you still think that it is better way to lower the permissions on /var/lock, feel free to propose it on devel.org list to know opinion of wider audience.

Comment 4 Wietse Venema 2010-04-16 13:09:18 UTC
[Wietse Venema here - sorry my name did not show up in the bugzilla signup procedure]

The real problem is that /etc/init.d/* scripts create/remove files as root under a directory that is under control by an unpriviliged user (in this case a group).

There are two types of fixes: "type 1" fixes that address the underlying problem, and "type 2" fixes that address specific symptoms.

A clean "type 1" fix is to change the lockdev program so that it creates application locks in a new directory /var/lock/lockdev. Then, /var/lock can be made writable only by root. This eliminates not only the problem that init.d scripts create/delete files under a directory that is group writable, but it also eliminates any problem with creating or removing files as root under the other /var/lock/* directories.

A simple "mixed type 1 and 2" fix is to make /var/lock sticky and to rely on the system to create /var/lock/subsys etc. at boot or install time. Then, no-one except root can replace /var/lock/subsys etc. by a symlink, and cause /etc/init.d/* to blow away files as documented in the initial bug report. This fix is more fragile due to the use of special directory permissions.

An example of the "symptom only fix" is to complicate the lockdev program with extra configuration for capabilities, selinux, etc. That seems even more fragile than setting the sticky bit.

Comment 5 Wietse Venema 2010-04-16 13:24:20 UTC
In case this is not 100% clear: with

> A simple (part symptom, part fundamental) fix is to make /var/lock sticky
> and to rely on the system to create /var/lock/subsys etc. at boot or
> install time.

I mean ADD the sticky bit, KEEP the root and group write permission, i.e. drwxrwxr-t root lock /var/lock

Comment 6 Ondrej Vasik 2010-04-16 13:27:07 UTC
Making /var/lock 1775 was already proposed and was rejected CANTFIX - see https://bugzilla.redhat.com/show_bug.cgi?id=145264 - and e.g. http://marc.info/?l=linux-security-audit&m=96441626707601&w=2 which problems might be caused by sticky bit.

Comment 7 Wietse Venema 2010-04-16 13:48:31 UTC
And what are your thoughts about the better fix: having lockdev create locks under its own directory?

drwxr-wr-x root root /var/lock        <<<<=== No group write permission
drwxr-xr-x root root /var/lock/dmraid
...
drwxrwxr-x root lock /var/lock/lockdev <<<=== Group write permission here
drwxr-xr-x root root /var/lock/subsys

Now, the subsys directory is "safe" and my privilege esclation exploit no longer works. This also addresses any problems with creating/deleting files as root under the  /var/lock/drmraid etc. directories or any directories that might be added in the future.

With this, the lockdev program no longer has write permission on the parent of /var/lock/subsys, /var/lock/dmraid, and so on.

Comment 8 Jiri Popelka 2010-04-16 14:15:29 UTC
Filesystem Hierarchy Standard
http://www.pathname.com/fhs/pub/fhs-2.3.html#VARLOCKLOCKFILES
doesn't say, that lock files have to be stored directly in /var/lock, but
"Lock files should be stored within the /var/lock directory structure."
so
drwxr-xr-x root root /var/lock        <<<<=== No group write permission
drwxrwxr-x root lock /var/lock/lockdev <<<=== Group write permission here
looks like a solution to me.

Comment 9 Jiri Popelka 2010-04-19 15:48:02 UTC
Lockdev now (lockdev-1.0.3-5.fc14) creates it's own
drwxrwxr-x root lock /var/lock/lockdev
directory during installation.
Lock files are placed into this directory,
so /var/lock doesn't need to be group-writable anymore.

Comment 10 Ondrej Vasik 2010-04-19 16:29:30 UTC
Built as filesystem-2.4.35-1.fc14 ... permissions on /var/lock are now 755:root:root

Comment 11 Wietse Venema 2010-04-19 16:51:22 UTC
I agree that this solution solves the problem at its root cause. Now, can someone undo the change that was made to the subject of this report? The idea to solve the problem by playing with capabilities is a mistake, as it addresses a symptom (lockdev can do nasty stuff to root) and not the cause (lockdev should not have write permission to a path that is used by root).