[prev in list] [next in list] [prev in thread] [next in thread] 

List:       apparmor-dev
Subject:    Re: [Apparmor-dev] [ANN] FastRPC, a continuation of imsep
From:       Crispin Cowan <crispin () novell ! com>
Date:       2006-08-30 20:33:02
Message-ID: 44F5F5FE.9010003 () novell ! com
[Download RAW message or body]

Mark Seaborn wrote:
> Crispin Cowan <crispin@novell.com> wrote:
>   
>> Mark Seaborn wrote:
>>     
>>> You're right, this is a big problem with systems that only allow
>>> static security policies.  They don't allow programs to follow the
>>> principle of least authority in many cases, because the
>>> statically-specified privileges that a process is given end up being
>>> much greater than what it would need if it were granted authority
>>> dynamically.  
>>>       
>> The thing to understand about static policies is that the policy may be
>> static, but the privilege of a given principal (process) is not: It
>> changes on exec. In AppArmor, it changes with calls to change_hat(). In
>> LOMAC, it changes when you read from lower integrity files. So the
>> privilege is dynamic, changing at some granularity in accordance with
>> the static policy.
>>     
> Yes, you can change between profiles dynamically, but the profiles are
> statically defined, so the criticism still applies.
>   
Your criticism is that privilege is too permissive; true enough, tighter
policy is always better, all other things being equal. The claim is that
static policy is what makes it too permissive. Well, maybe. My point is
that privilege is dynamic, even if the policy is static. IMHO it remains
to be seen whether static policy necessarily results in looser
privilege, though it does seem to be a pretty good intuition.

>> The thing to understand about least privilege is that it is always an
>> approximation to strict least privilege. In principle, you *could* make
>> a call to a hypervisor after every single CPU instruction to have your
>> privilege level adjusted for the next instruction. This would suck in
>> many ways :) but it what is required to achieve *strictly* least
>> privilege in the dynamic sense.
>>     
> Are you talking about addressing the Confused Deputy problem?  If so:
>   
No, that is not what I am referring to. I am referring to the basic
problem that the *exact* set of privileges that a given process needs at
a given time can only be approximated by any reasonable access control
system. Further, the exact set of privileges that the process needs
changes over time, and to achieve tight least privilege, the process
would have to advise the kernel every time it can drop a privilege, and
every time it needs a new privilege.

Worse, the system would need some way to determine if the process should
get that new privilege, or if it has been compromised and is asking for
a privilege it should not have. Static policy is one way to deal with
this: give the process the union set of all privileges it needs for its
lifetime, and don't worry about the fact that it doesn't need all of
those privileges all the time.

Object capabilities is another way of dealing with it, trying to make it
tighter by allowing applications to delegate privileges in the form of
capabilities. This is both a strength and a weakness. It is a strength
because a deputy process doesn't have the privilege to mess with my
files until I delegate the capability to do so. It is a weakness because
a trusted application with a lot of privilege could delegate
capabilities improperly if the application is hijacked by an attacker.


> If you replace "instruction" with "invocation of the kernel", what you
> describe is sort of how an object-capability system works.  The
> "privilege level" in this case is not a piece of per-process state
> that is set with a call such as change_hat(), but an argument of the
> invocation, and it doesn't specify a set of privileges, it specifies a
> specific object.
>   
Sort of. Object capabilities are one instance of how privilege level can
change dynamically. Privilege level changes *necessarily* involve
invoking the kernel.

>>> Object-capabilities are a good mechanism for granting authority
>>> dynamically, and file descriptors are an example of
>>> object-capabilities.  However, by preventing file descriptors from
>>> being transferred between processes (and then used), AppArmor and
>>> SELinux are taking away one of the properties that makes FDs
>>> capabilities.  My question is: In doing this, are the developers
>>> intending to prevent deliberate delegation of file descriptors, or
>>> accidental delegation?
>>>   
>>>       
>> I can't speak for what the SELinux developers intended. What the
>> AppArmor design intended was that the policy for the program receiving
>> the FD should describe all of the files it can access, regardless of how
>> it came to access them.
>>     
> The policy for the program receiving the FD cannot itself limit the
> set of files that the program can access.  Another process can
> delegate it the ability to access a file by proxying requests
> (assuming that the two processes are able to communicate with each
> other).
>   
"Cannot"? I'm afraid that is precisely what AppArmor does. There is no
way for a program confined by AA to delegate a privilege, unless the
external static AA security policy says that the deputy can have that
privilege. You can do that by specifying a broad set of privileges for
the deputy, or you can do that by exec'ing the deputy with "ix"
permissions in the policy, so that the deputy runs with the *same* set
of privileges as the parent.

>> This is the core abstraction of the AppArmor policy model, and we
>> would be inconsistent if a program was allowed to access files
>> outside the policy merely because the FD was provided in an unusual
>> way.
>>     
> It is not inconsistent if you base your analysis on authority (de
> facto powers) rather than privileges (de jure powers).  I am taking
> the terminology here from "Paradigm Regained: Abstraction Mechanisms
> for Access Control" (http://www.erights.org/talks/asian03/).
>   
Uh, ok. I have seen people make the distinction between "least
privilege" and "least authority" before, but I have never understood it.
Your distinction between de jure/principal/privilege and
defacto/practice/authority doesn't help me much. In human society, there
is lots of wiggle room between what the law permits and what people
actually do; many people speed, jay walk, and cheat on their taxes. In
computer security systems, there is no such difference: the only things
that are considered "secure" are those that have enforcement mechanisms,
so principle and practice appear to be the same.

> To take the concrete example of an image decoder process, there are
> two ways you can implement this in a system like AppArmor:
>
> 1) Give the process privileges (as defined by the access control
>    system) that are minimal, and dynamically grant it further
>    necessary authority by proxying or similar means.  For the image
>    decoder, this might mean sending a copy of the image to the process
>    via a socket.  This is secure (i.e. the process is granted the
>    minimum necessary authority), but inefficient.
>
> 2) Give the process excess but sufficient privileges, and do no
>    proxying.  This might mean granting access to all *.png files.
>    This is efficient (because the process can use read() to read the
>    file directly from the FD), but less secure (because the process
>    can access files it doesn't need to be able to access).
>   
Ok
.
> You can achieve de facto delegation of file descriptors by proxying,
> so do you gain anything by disallowing de jure delegation?
What does "de jure" mean here? We disallow delegation of privileges.

>   What does
> it achieve besides forcing a choice between a more awkward and less
> efficient implementation (case 1), or a less secure implementation
> (case 2)?
>   
It gains you assurance. Process X will never do anything other than what
is permitted by its static policy, which you can read right here. If
delegation were allowed, then process X can do all this static stuff,
plus whatever privileges someone might pass in. Since delegable
privileges are under application control, the set of privileges that
could be handed in is undecidable.

It gains you manageability. AppArmor policies are, largely, intended to
be constructed by system administrators using the AA tools, to confine
legacy applications. Object capabilities are alien concepts to both
system administrators and legacy applications, so the question of "what
capabilities can this program receive" is weird and hard to answer for
the person trying to build a policy, and I don't know how to make our
tools do it automatically.

I am not saying that object capability systems are bad. I like them. But
AppArmor had a different design objective than EROS did. AA was designed
to achieve reasonable least privilege with little effort and no
application changes. EROS was designed to achieve tight least privilege
using a new programming paradigm that requires substantial application
changes, if not complete re-writes.

As a result, it is quite true that you can produce examples where an
application that wants to do privilege delegation cannot be expressed
well in AppArmor, and you get the ugly trade off you describe above of
either inefficiently pass a large data object, or insecurely grant the
deputy large privileges. That is a design trade off: we don't solve that
problem, in order to make it easier to solve other problems, such as
making it easy to produce a static and comprehensible application policy.

Crispin

-- 
Crispin Cowan, Ph.D.                      http://crispincowan.com/~crispin/
Director of Software Engineering, Novell  http://novell.com
     Hack: adroit engineering solution to an unanticipated problem
     Hacker: one who is adroit at pounding round pegs into square holes


_______________________________________________
Apparmor-dev mailing list
Apparmor-dev@forge.novell.com
http://forge.novell.com/mailman/listinfo/apparmor-dev
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic