[apparmor] [RFC PATCH 1/1] libapparmor: Create man page for aa_stack_profile()/aa_stack_onexec()

Tyler Hicks tyhicks at canonical.com
Wed Jan 13 06:10:16 UTC 2016


Thanks, John - I hadn't given a lot of thought to the policy changes
required and this email was very helpful.

On 2016-01-12 15:10:28, John Johansen wrote:
> On 01/11/2016 06:27 PM, Seth Arnold wrote:
> > On Mon, Jan 11, 2016 at 05:41:43PM -0800, John Johansen wrote:
> >>>> +Stacking another profile via aa_stack_profile() is permanent and the process is not
> >>>> +permitted to revert to the previous confinement context. Unlike
> >>>> +aa_change_profile(2), confined programs wanting to use aa_stack_profile() need
> >>>> +no special rules in their profile to stack a new profile since the operation
> >>>> +does not broaden the allowed permissions.
> > 
> >>> I'm also afraid that this kind of rule might also allow these APIs to be
> >>> used by exploit code to unreasonably manipulate profile transitions in
> >>> ways that aren't expected by policy authors.
> >>>
> >> how so?
> >>
> >> the policy will have to allow stacking, and stacking is purely restrictive.
> >> If the profile allows the stack, then and only then can it take priority
> >> over the profiles exec transitions, just like with change_profile.
> > 
> > Earlier in the manpage it was suggested that policy does _not_ have to
> > have syntax to allow stacking.
> > 
> > If the stacking is entirely under the control of the program and not
> > influenced by policy (as suggested in this manpage) then the following
> > attack is feasible:
> > 
> > Presume we're running in a confined sshd-alike application. The profile
> > for the sshd-alike includes the following rule:
> > 
> > /bin/bash Px -> user_shell,
> > 
> > The intention is that users are confined to a specific profile once they
> > are authenticated, one that doesn't allow system administration tasks.
> > 
> > If an exploit during user authentication is allowed to call
> > aa_stack_onexec("administrator_shell");
> > and this API call overrides the Px in the profile, then an exploit could
> > bypass the restricted profile and get a profile that allows administration
> > tasks.
> > 
> not necessarily so. There are in fact 3 different semantics stack_onexec
> could take on, and we will have to be precise about what it is doing and
> why.
> 
> The desire to delay the stack to exec is similar to change_onexec so that
> you don't have to implement a stub profile in policy for the brief period
> between change_profile and the exec.
> 
> Eg.
> 
> basic change_profile: replaces the current profile immediately
>   A  -- change_profile --> B
> 
> change_onexec: replaces the current profile, but delays it until exec
>   A  -- change_onexec ... exec --> B
> 
> this avoids having to make policy where what you do is
>   A  -- change_profile --> STUB
>   STUB --> exec --> B
> 
> where STUB has to have permissions for intermediate operation and then
> the exec transition.
> 
> With change_profile you could skip the STUB profile portion and include
> any permissions granted in STUB into the B profile. However since
> change_profile is usually being used to reduce permissions, that is not
> desirable, where change_onexec includes the STUB profile permissions
> into A.
> 
> Now lets move on to stacking.
> 
> basic stack: reduce the current permissions immediately
>   A -- stack B -->  A//&B
> 
> notice how A wasn't replaced or removed. Once we come to the exec
> the exec rules for both A and B are applied. Lets say A transitions
> to C and B to D then we get
>   A -- stack B --> A//&B -- exec --> C//&D
> 
> if however A and B both transition to C then we get
>   A -- stack B --> A//&B -- exec --> C//&C -- collapses to --> C

Interesting stuff. Now I know what you mean when you say, "The stack
collapses".

> now lets look at the stack on exec case. The stack addition is delayed
> until exec.  The current profile will have the stack added on top, the
> question is when and how.
> 
> 1. stack_onexec as stack + change_onexec: stack is computed immediately
>     but the transition is delayed until exec (this overrides any
>     transitions and is how Tyler described it)
>   A -- stack_onexec B -- exec --> A//&B

Yes, this is what I pictured when a program, confined by "A", calls
aa_stack_onexec("B").

> 
> 2. stack_onexec, stack delayed until exec applied pre-exec transitions
>   A -- stack_onexec B -- exec apply stack -- A//&B -- exec trans --> C//&D

I can't imagine much use for this flow. Unless there's a good use case,
I think we should throw it out.

> 
> 3. stack_onexec, stack delayed until exec applied post-exec transitions
>   A -- stack_onexec B -- exec trans -- C -- apply stack --> C//&B

I was actually thinking that this would happen when a program, confined
by "A", calls aa_change_onexec("C//&B"). It is changing to a specific
stack of profiles on exec instead of stacking an additional profile on
top of its current confinement.

> each is a viable definition and each could have their uses.
> 
> Example 1: is like change_onexec in that it completely replaces the
> domain transition, with a profile set computed at the time it is called.
> Neither A nor B require a domain transition, A requires a change_profile
> or stack_profile rule, and all intermediary permissions between
> stack_onexec and exec need to be included in B
> 
> This is the most like change_onexec in behavior. However a better
> description of it is stack and apply at exec.
> 
> Example 2: follows what happens with aa_stack, contrary to change_onexec
>   mimics what happens with straight stacking, and like change_onexec
>   puts all intermediary permissions between stack_onexec and exec into A.
>   However A//&B must have exec permissions and this is contrary to how
>   change_onexec works. That is change_onexec has a rule in A that defines
>   the exec permission and has priority over regular domain transition
>   rules and the target B does NOT need an exec rule.
> 
>   We could and should have a stack_onexec or use the change_onexec rule to
>   mitigate the first difference but that B requires and exec rule is odd,
>   and I don't think it is a viable definition.
> 
> Example 3: is similar to example 2 except B does not require a domain
>   transition. It can be thought of stack on top of what ever current is
>   after exec.
> 
>   Rules wouldn't be required in this model but still might be desirable.
> 
> Whether to go with 1, 3 or both depends on use cases, and how these are
> implemented. So lets look at the exec side some more. Because exec rules
> are also going to pickup the ability to specify stacking. Note the syntax
> here is not final but sufficient for the discussion.
> 
> exec rules allow naming a profile to transition to
>   px /foo/bar -> A,
>   px /** -> A,
> 
> this will be extended to support specifying an explicit stack
>   px /foo/bar -> A//&B,
>   px /** -> A//&B,
> 
> however we may want to be able to specify the stack based off the target
> profile, this works for
>   px /foo/bar -> /foo/bar//&B,
> 
> but does not work for the rule with globbing because there can be
> multiple targets matched.
>   px /** -> ??//&B,
> 
> we can get around this by either introducing a special variable
>   px /** -> @{TARGET}//&B,

This feels like we're bending over backwards to appease the lazy policy
author. He/She already has to define the profiles for each one of those
targets so why not make him/her include a transition rule for each
target?

> or extending the stacking syntax a little to mean use the target and
> what is specified.
>   px /** -> &B,   # leading & specifies use target and stack B
> 
> however neither of these syntaxes are sufficient (for globbing rules) to
> specify the final confinement when we want the execed process to have
> current confinement and B. We can extend each syntax to support this.
> 
>   px /** -> @{SELF}//&B,
>   #Note: @{PROFILE} is not correct as the task may already have
>   #      a stack of profiles, so it is current confinement
> 
> and
>   ix /** -> &B,			# notice ix instead of px
> 
> 
> notice how the choices 1 and 3 for stack_onexc parallel the above exec
> rules.
>   1. is the same as
>       px /** -> @{SELF}//&B,
>     or
>       ix /** -> &B,
> 
>   3. is the same as
>      px /** -> @{TARGET}//&B,
>    or
>      px /** -> &B,
> 
> both cases have their uses, and I believe we need to support both. So
> the stack api should probably support both as well.

I already mentioned this above but I think the stack API does, as
proposed, if aa_change_onexec() can be made to accept a string
representing a profile stack.

> 
> Now to the matter of whether stacking rule in the profile is required.
> 
> 1. requires a rules otherwise it can be exploited, as Seth has
>    already pointed out.
> 
> 3. doesn't require a rule but it probably should use them, mostly
>    so for consistency with 1.
> 
> The question still remains whether we use change_profile rules or
> introduce a separate stacking rule.
> 
> If we go with change_profile rules then
>   change_profile -> A,
>   change_profile -> B,
> 
> grants enough permissions for stacking to A//&B, however it grants wider
> permissions than necessary as it also allows a transition to just B,
> which may not be desired. Which means at the least we need to augment
> change_profile to support the more restrictive case.
>   change_profile -> A//&B,
> 
> we could do the same with a special stack rule
>   stack -> A//&B,
>   stack -> @{SELF}//&B,
> 
> but I see no reason to limit the change_profile api to not allow
> specifying compound targets. ie. I can see using change_profile to
>   change_profile  C//&D,

Agreed.

The existing change_profile rule could be used for specifying specific
compound targets while a new stack_profile rule could be introduced for
stacking a single or compound target with the current confinement.

> this is an immediate change to this confinement and there is no exec
> target involved. Further once delegation lands we will want to be able
> to specify targets with delegation.
>   change_profile  A//+E,
> 
> at which point I think change_profile, stacking and delegation rules are
> more complex than combining into a single rule as each of them are going
> to have to support bits of the other.
> 
> yes this does mean the stacking api is really just a convenience layer
> on top of change_profile, but that isn't a bad thing.

There's certainly a lot of overlap but if we are consistent in policy,
API, and documentation about the differences between "change" and
"stack" then I think everyone will benefit. At the minimum, everyone
will suffer a little less... :)

Tyler
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <https://lists.ubuntu.com/archives/apparmor/attachments/20160113/dd9b764c/attachment.pgp>


More information about the AppArmor mailing list