Re: caps in elf, next itteration (the hack get's bigger)

Albert D. Cahalan (acahalan@cs.uml.edu)
Thu, 15 Apr 1999 14:22:08 -0400 (EDT)


David L. Parsley writes:
> On Thu, 15 Apr 1999, Albert D. Cahalan wrote:
>> David L. Parsley writes:
>>> On Wed, 14 Apr 1999, Pavel Machek wrote:
>>
>>> If I were designing a secure distribution based on the stickable solution,
>>> here's how named would start:
>>>
>>> Calling process: ( I feel certain this can be easily arranged with the
>>> 'stickable' solution, and don't want to make this example longer than it
>>> already is)
>>> uid=named
>>> gid=named (only)
>>> permitted bits=0
>>> inheritable bits=0
>>> effective bits=0
>>
>> Hmmm, looks like you are already playing with the UID.
>
> Playing with the uid? I'm just specifying the uid of the calling process
> that can be setup beforehand; I'm certainly not storing it in the elf
> headers, I still think that's gross.

How did the calling process get that UID? You might as well go all the
way, and have the calling process supply all needed capabilities.

That (a sudo-like tool for capabilities) would be a perfect for named.
The tool already exists; I think I have it somewhere on my disk even.

(named is started in one place, in a script, so this is easy)

>>> Named binary:
>>> -rwsr-x--T 1 named named 432880 Jan 4 01:07 named*
>>> permitted bits=CAP_NET_BIND_SERVICE (only)
>>> inheritable bits=0
>>> effective bits=CAP_NET_BIND_SERVICE
>>> extended file attributes=immutable bit set
>>
>> OK, this has to be ext2. That sucks.
>
> NO!!! It _can_ be _any_ fs that understands the sticky bit, where you
> trust the sticky bit to enable caps! With a mount option, it can be made
> to work with UMSDOS, nfs, CODA, ... The problem with this, which I am
> well aware of, is that it means having to trust the sticky bit. The
> immutable bit was added to the spec for ext2 because it nicely solved the
> local problems.

That problem is HUGE and totally unacceptable.

>> You don't have a good backup
>> either.
>
> I don't understand what you're saying here.

The immutable bit will not survive a backup and restore. I hope
you never need to do a restore, because your system will be broken
until you remember all the places you need to set the immutable bit.

>> Why run a shell? The exploit code could transfer an executable and
>> set any special bits needed. You can not rely on an exec() to drop
>> bits, since the exec() is not needed.
>
> I used running a shell because it's the form of attack I'm most used to
> seeing. I don't see, though, how the exploit code could transfer an
> executable and 'set any special bits needed'. If you mean raise it's
> capabilities, you're incorrect. At best the exploit code could continue
> to listen on a low port.
>
>> In case named is unable to set those bits, the exploit code could
>> just transfer an object file and do a dlopen() on it. Even without
>> any filesystem access at all, you could bootstrap a huge executable
>> through a tiny buffer overflow. No exec() ever happens.
>
> It could dlopen() without cooperation from ld.so? You're losing me
> here...

Normal exploit code:
adjust UIDs as needed
exec a shell

New exploit code:
read additional code from the network
jump to the additional code
(then fork, allocate more memory, read more code...)

There are many ways to take over the named process. After transferring
any additional code needed, the exploit code could act as a telnet server.

>>> Which, IMHO, is about as secure as you can get. (dunno for sure if it
>>> can't be improved)
>>>
>>> Now, I see three situations possible with setuid0:
>>> 1) you can mark named(8) setuid root and implement exactly my scenario
>>> above. I hope you reject the idea of setuid root named as fast as I do.
>>
>> I reject true setuid root, but not use of the setuid root bit.
>> Headers may be mangled to prevent execution on old kernels.
>
> OK, so it's a one-way operation; once you modify your first binary, you
> _never_ boot to an old kernel without patching it first?

I suppose there are 3 interesting cases:

Already setuid-root --> no problem, just add capability data
Already run as root --> use sucap or execcap to fix this
Not currently root --> like setuid-root case, but mangle the header

> a patched kernel. With the sticky bit scheme, you could export /usr from
> a Linux 2.0 machine and cap-enable all the binaries. The 2.0 machine
> could run with the old security model and ignore the superflous headers,

Yeah, what fun! I just login to a 2.0 machine, add headers I like...

>> If something is dangerous, it ought to look dangerous.
>> Emacs may already be sticky and immutable.
>
> I'm sorry, but if you're gonna start running with capabilities, you'll
> have to take the time to understand how they work,

I do understand. I doubt I could explain it to the average admin.
Security features are worse than useless when they are not understood.
Every UNIX security book should explain that setuid-root executables
are a risk.

>>> but not compliant with the specification for how capabilities operate.
>>> This would be an abomination IMHO, which I hope you reject.
>>
>> The specification isn't a Standard, so that would be reasonable.
>
> Oh, for gosh sake! So now you're going to completely re-design
> capabilities to cope with the broken setuid0 scheme? Just to get
> slightly better behavior over a remote fs, and make cap binaries
> 'easily recognizable'?

If you think fixing a MASSIVE SECURITY HOLE is just slightly better,
then I ought to just ignore you.

It is critical that privileged executables be easily recognizable.
Security scripts and human admins look for the setuid bit.

>> One could have a mount option like this:
>>
>> trusted=rootowned,sticky,immutable
>
> I agree that having local and remote mount options to enable this are an
> absolute must.
>
>> By default, setuid-root executables are trusted unless mounting with
>> setuid executables disabled.
>>
>> Option list:
>>
>> rootowned owned by root
>> setuidroot setuid to root
>> sticky sticky bit set
>> immutable immutable bit set
>> system system bit set
>> pgp has a valid signature
>> ... ...
>
> Ok, again you've lost me here...

We simply need a way to mark an executable as being trusted.
There are several ways to do that. Some ways only work on ext2,
some ways are portable, and some ways work only with a patch.

The kernel should fully interpret a security header when it appears
in a trusted executable, with "trusted" being defined by the admin.
You can have your broken sticky bit solution as long as I can choose
the more reliable setuid-root solution...

>> One could also add specific trusted executables in the VMS manner.

...and the above is just another way to indicate "trusted".

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/