lkml.org 
[lkml]   [1999]   [Apr]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
Date
From
SubjectRe: caps in elf, next itteration (the hack get's bigger)
Hi Albert,

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.

> > 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.

> You don't have a good backup
> either.

I don't understand what you're saying here.

> > named process after exec'ed by calling process: (CAP_NET_BIND_SERVICE
> > abbrev. to CAP_NET)
> > uid=named
> > gid=named (only)
> > permitted bits: pP' = fP | ( fI & pI ) = CAP_NET | ( 0 & 0 ) = CAP_NET
> > inheritable bits: pI' = pI = 0
> > effective bits: pE' = pP' & fE = CAP_NET & CAP_NET = CAP_NET
> >
> > bash binary:
> > -r-xr-xr-T 1 root root 426980 Oct 19 22:57 bash*
> > permitted bits=0
> > inheritable bits=(all)
> > effective bits=(all)
> > extended file attributes=immutable bit set
> >
> > Now, let's say another remotely-exploitable buffer overflow is found in
> > named(8). A black hat overflows the buffer, and manages to exec a bash
> > shell. Now let's compute the state of the bash shell that's been exec'ed:
> >
> > bash shell process running parameters:
> > uid=named; rights in fs: read rights only to: /etc/named.conf,
> > /var/named/*, and /usr/sbin/named; write rights to
> > /var/named/(secondaries); execute right to /usr/sbin/named
> > gid=named; rights in fs: read and execute /usr/sbin/named
> > permitted bits: pP' = fP | ( fI & pI ) = 0 | ( (all) & 0 ) == 0
> > inheritable bits: pI' = pI = 0
> > effective bits: pE' = pP' & fE = 0 & (all) = 0
> >
> > So after the attack, the attacker is left only with a shell that can:
> > - trash /var/named/(secondaries)
> > - re-start named(8), but not modify it in any way.
>
> 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...

> > 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? What about
operation over nfs, where the remote filesystem now holds a setuid root
named? Of course, it's useless on that other machine unless it's running
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,
and the 2.2 enhanced machine could run capability-enabled. Under the
setuid0 scheme, you'll have to mark named, inetd, apache and others setuid
root. Or, you allow them to inherit their caps, but then they are able to
spawn processes which can _also_ inherit those caps.

> 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, and that setuid root
doesn't mean what it used to. That, or you're breaking the implementation
of capabilities, which is what a few of you seem hell-bent on doing.

> > 2) you make the named binary have no permitted, and inheritable=CAP_NET,
> > with the calling process having only CAP_NET in it's inheritable, and
> > otherwise the same as my example. This is your _best_ scenario IMHO, and
> > I'll come back to this in a moment.
> > 3) You put whatever you want in the cap elf headers, _don't_ mark the file
> > 'setuid 0', and interpret your cap elf headers in whatever way you wish,
> > 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'? I'll eat your gym socks if such a patch ever gets in the
kernel. Really. I've done my damnedest to stay logical and unemotional
on this, but it's getting really ridiculous. I've just shown above that
the stickybit/immutable scheme has a better shot at being useful over nfs;
or at least, the tradeoffs between the two schemes is a wash. But
stickybit/immutable (ext2 only) is a truer implementation of the
capability semantics.

> > already derived this behavior. Also, I beg that you re-consider the
> > stickybit+immutable bit solution; it appears you understand well enough
> > how it operates. I'm considering trying to modify your patch myself; I
> > have the C coding skills, but no experience with kernel data structures
> > and API's. I _would_ give it a shot, however.
>
> 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...

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

I'm just not in favor of turning Linux into VMS (in the security system at
least). The capabilities support looks to me plenty flexible for most
uses, and most of it is already in the kernel.

I'm sorry if I used all caps one too many times, I'm just starting to
wonder why some people are holding on so hard to the setuid0 scheme. I
was _completely_ in favor of it for quite a while. Then I started reading
the linux-privs specification, and thinking of the philosophy behind it
and how it was designed to be used, and how I would use it in a real-world
situation. To do things correctly (and I strongly emphasize correct) the
setuid0 scheme just didn't cut it. So I cast about for a better
solution...

Don't get me wrong, I'd be thrilled to see an even _better_ suggestion.
Ecstatic, even, if people would finally let go of using setuid0.

cheers,
David

- --
David L. Parsley
Network Specialist
City of Salem Schools


-
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/

\
 
 \ /
  Last update: 2005-03-22 13:51    [W:0.063 / U:0.172 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site