From: www.itworld.com

The Hazards of Inconsistency

by Brian Hatch

April 2, 2002 —

 

Linux's inner workings are occasionally inconsistent. This is not
unique to Linux though. I want to cry, for example, every time I try to
set up an LPR printer in Windows because each version or service pack
moves things into completely different places. Of course, the fact that
I'd be forced to touch a Windows machine in the first place could be
the cause of my tears.

As to Linux's inconsistency, let's look at how 'chown' behaves. (Yes,
you'll need to run these commands as root.)

# ls -l
-rwx------ 1 root root 100 Feb 28 12:00 realfile
lrwxrwxrwx 1 root root 8 Feb 28 12:00 link -> realfile

# /bin/chown luser:luser link; ls -l
-rwx------ 1 root root 100 Feb 28 12:00 realfile
lrwxrwxrwx 1 luser luser 8 Feb 28 12:00 link -> realfile

/bin/chown changed the owner of the link, not the file pointed to by
the link. This may seem nice, but what happens if you do the same thing
in a C program using the chown(2) system call instead?

# cat sys_chown.c

#include
#include
#include

main() {
chown("link",443,443); /* userid/groupid 443 is bob */
}
/* END */

# make sys_chown
# ./sys_chown
# ls -l
-rwx------ 1 bob bob 100 Feb 28 12:00 realfile
lrwxrwxrwx 1 luser luser 8 Feb 28 12:00 link -> realfile

So using C, the chown(2) system call ended up changing the ownership of
realfile, not the symlink. What happened? Why did /bin/chown act
differently than the chown(2) system call? Which one is 'right'?

The POSIX definition of chown acts as we see in the second example --
chown on a file modifies the owner/group of the target file, not the
symlink. If you want to modify the symlink itself, you need to use the
lchown(2) system call instead.

In fact, if you run 'chown luser:luser link' on a non-Linux system,
such as Solaris, you'll see 'realfile' being changed in both cases.
This behaviour is the POSIX standard. The logic behind
Linux /bin/chown's use of lchown(2) escapes me. If you want to get true
POSIX chown behaviour on Linux, you need to use 'chown --
dereference ...'

So let's look at a possible attack. On a non-Linux system, say a
malicious user creates the following link in the Web DocumentRoot:

-rw-rw-r-- 1 baduser baduser 12 Feb 28 12:00 blah.html -
> /etc/passwd

Should root do a 'chown web:web /path/to/docroot' on this
system, /etc/passwd will now be owned by the Web user. If baduser can
get Web permissions (say he can write CGIs), then he can take over the
system rather trivially. On non-Linux machines, you'd need to
use 'chown -h ...' to make sure you affect the link itself, not the
actual target file.

Why is this a security problem for Linux? Linux' /bin/chown by default
affects the link, not the target file, which would seem to be a good
thing in this case. Well, call it a pet peeve, but I don't like things
that don't behave right. A Solaris admin must learn to use 'chown -h'
to be secure and because of it, should he write something similar in C
or Perl, he'll know to use the lchown(2) call. However, the Linux
administrator, having been blissfully unaware of the difference, may
end up falling into this symlink attack.

So what's my point? Make sure that you know the ins and outs of all
your tools -- even things you take for granted -- when security is on
the line. Try perusing man pages at least once a week for grins and see
what new things you can discover, or misconceptions you can correct.