[apparmor] Apparmor: Query

Murali Selvaraj murali.selvaraj2003 at gmail.com
Wed Aug 5 02:46:46 UTC 2020


Thanks for the explanation.

Goal: Converting root process to non-root process by enabling required
capabilities for the process.

Scope: Am trying to find out required capabilities for the process which is
going to run as "non-root"

How to use Apparmor to find the capabilities specific to process:

-> As per above discussion, Apparmor does not grant the required
capabilities.

-> We had thought that, from apparmor logs, we would be able to find the
required capabilities.

-> To find this, we would be following the steps to find the capabilities.

Process (A) will be running in "non-root" but with all enabled capabilities
and check the apparmor logs.
Apparmor logs will show the required capabilities.
Capture these CAPS and use this CAPS in the process code to convert that
process root to non-root by only enabling this CAPs observed in apparmor
logs.

Is above understanding correct? please confirm the steps if anything is
missing.

*General Query:*

In any event, AppArmor will usually see capability requests after the usual
DAC permissions are handled.

Can you please explain this above statement with simple example?

For example, Process (x) tries to open a file (/etc/security) which is root
permission but the process (x) runs in "non-root mode.
Pls note, process (x) does not have permission to open this file
((/etc/security) )

open => sys_open() => kernel further code for handing the code.

sys_open() => will return permission denied error due to permission issue.

Here, capable() check won't happen. Does DAC take care of this check
without using capability (CAP_DAC_READ_SEARCH)?

In such a case, trying to understand when Kernel uses capable() to check
CAP_DAC_READ_SEARCH/CAP_DAC_OVERRIDE before/after DAC.
Can you please explain the relation between DAC, apparmor and linux
capability with this context?

Thanks
Murali.S

On Tue, Aug 4, 2020 at 6:08 AM John Johansen <john.johansen at canonical.com>
wrote:

> On 8/3/20 8:02 PM, Murali Selvaraj wrote:
> >
> > Hi Seth,
> >
> > Thanks for the detailed explanation. Please go through below details and
> clarify further queries.
> >
> > I do not see a capability difference when this script runs in root
> (UID:0)  and nobody (UID>0).
> > If we are observing the required capabilities when the script runs in
> root, that would be easy for us to find
> > the needed capabilities for this script. Then we will apply this
> capability when it runs in nobody user.
> >
> > #!/bin/sh
> > echo "Testing"
> > while [ 1 ]
> > do
> > cat /etc/foo   =================> Ensure this file belongs to root
> permission
> > echo "TESTING" > /nvram/foo
> > killall <root_process_name>
> > sleep 5
> > done
> >
> >  ls -ltr /etc/foo
> > -rw-r--r--    1 root     root             8 Aug  3 20:31 /etc/foo
> >
>
> can you please add
>
> echo -n "Confinement:"
> cat /proc/self/attr/current || echo "Failed to obtain confinement" ; exit 1
>
> to your script after the killall or something similar, this will dump the
> confinement of the "cat" command but unless you have a transition for "cat"
> it should have the confinement of it parent or be denied.
>
> I should note that apparmor does have a dedup cache around logging
> capabilities. It is a single entry per processor (or virtual processor),
> and will prevent a previously seen cap from being logged IFF no other
> PROFILE has mediated a cap on that processor since the last time that
> profile previously logged the CAP in question.
>
> There is no manual switch to clear the cache, but it can be effectively
> cleared by replacing the profile but you need to actually make a change to
> the profile so that profile load dedup doesn't drop the replacement.
>
>
> >
> > Can you please check this script in your environment and share your
> observation. Please do the needful.
> > Please execute in root and non-root mode and find the capability list
> from apparmor log events.
> >
>
> not exactly your script but roughly equivalent
>
> unconfined non-root user killing root process
>
>   $ kill 23579
>   bash: kill: (23579) - Operation not permitted
>
> no apparmor log message.
>
> ----
>
> unconfined root user killing root process
>
>   $ sudo kill 23579
>
> success, no apparmor log message
>
> ----
>
> confined non-root user without signal or CAP permissions killing root
> process
>
>   $ aa-exec -p demo -- kill 23965
>   kill: (23965): Operation not permitted
>
> no apparmor log message
>
> ----
>
> confined root user without signal or CAP permissions killing root process
>
>   $ sudo aa-exec -p demo -- kill 23965
>   kill: (23965): Permission denied
>
> apparmor log messages
>
> [987021.379719] audit: type=1400 audit(1596533293.878:234):
> apparmor="DENIED" operation="signal" profile="demo" pid=24036 comm="kill"
> requested_mask="send" denied_mask="send" signal=term peer="/usr/bin/man"
> [987021.379727] audit: type=1400 audit(1596533293.878:235):
> apparmor="DENIED" operation="signal" profile="/usr/bin/man" pid=24036
> comm="kill" requested_mask="receive" denied_mask="receive" signal=term
> peer="demo"
>
> notice no capabilities are needed to send the signal because its being
> sent from root to a root process
>
> ----
>
> confined root user without signal or CAP permission kill a non-root
> process (different uids)
>
>   $ sudo aa-exec -p demo -- kill 24690
>   kill: (24690): Operation not permitted
>
> apparmor log message
>
> [989073.431936] audit: type=1400 audit(1596535345.981:238):
> apparmor="DENIED" operation="capable" profile="demo" pid=24717 comm="kill"
> capability=5  capname="kill"
>
> finally we get a CAP request for kill
>
>
> The reason for this is that the kernel applies DAC mediation before LSM
> (apparmor) mediation. AppArmor never sees the permission request unless DAC
> allow the operation.
>
> > *Need further clarifications:*
> >
> > My aim is to identify the required capabilities for the process when it
> runs in "non-root" user.
> > Currently, this process runs in root mode, so by default all CAPs are
> enabled in Effective/Permitted CAPs.
> >
> > Analysis:
> >
> > -> While the process runs in non-root mode, we are planning to apply the
> capabilities before switching to non-root from root.
> >    So, we need to set appropriate capabilities in order to run the
> application successfully in "non-root".
> >
> yes
>
> > -> As per my assumption, we will find the required capabilities when the
> process runs in root-mode. To find the required CAPs list
> >    we thought to use "apparmor" logs while the process runs in compliant
> mode.
>
> this doesn't quite work but you will be able to collect capabilities that
> don't rely on a uid check. This is because of how the kernel doesn't always
> apply a capability check, Eg. for kill CAPS are not always checked in the
> same way when subject uid == object uid vs. subject uid != object uid. The
> same can be said for DAC_OVERRIDE, DAC_READSEARCH, ...
>
> Some capabilities however aren't guarded by uid checks and you should be
> able to collect these caps when run as root. What you need to do to collect
> the full list of capabilities is give the non-root process all capabilities
> and run it. This should collect the full set of CAPs with how you are using
> uids.
>
>
> >    Once we get the CAPs list from Apparmor logs, then we shall use the
> same required CAPS only ( NOT all the CAPs) for the
> >    process when it runs in non-root mode.
> >
> > -> The idea is that we are trying to drop root privilege using this
> method.
> >
> > Can you please confirm , the above method is possible in apparmor event
> logs to find the required CAPs at least when run
> > in "root" mode.
> >
>
> close but see above, also you need to make sure exercise the application
> to get proper coverage
>
> > Thanks
> > Murali.S
> >
> > On Mon, Aug 3, 2020 at 8:21 PM Seth Arnold <seth.arnold at canonical.com
> <mailto:seth.arnold at canonical.com>> wrote:
> >
> >     Hello Murali,
> >
> >     On Mon, Aug 03, 2020 at 02:03:38PM -0400, Murali Selvaraj wrote:
> >     > Query 1:
> >     >
> >     > - But I do not see CAP_DAC_OVERRIDE and CAP_KILL in apparmor event
> logs.
> >
> >     AppArmor does not have a mechanism to grant capabilities that a
> process
> >     does not already have. The kernel will query LSMs to see if a
> capability
> >     is allowed to be used if the process already has the capability in
> >     question. (There may be exceptions to this, there's hundreds of these
> >     checks scattered throughout the kernel.)
> >
> >     You'll only see these requests in AppArmor logs if the process had
> these
> >     capabilities. By using su to switch to the 'nobody' account, you
> only have
> >     access to whatever privileges the nobody account already has:
> additional
> >     access to root_squashed files on NFS, any other processes mistakenly
> >     running as user nobody, etc.
> >
> >     Because this doesn't include any capabilities in the process's
> >     capabilities sets, AppArmor won't even see the requests.
> >
> >     > Query 2:
> >     >
> >     > - How apparmor identities how many capabilities are needed for the
> process?
> >
> >     The kernel will call capable() in the codepaths as necessary; the
> security
> >     module interface will get the calls, without context, after the rest
> of
> >     the kernel's capabilities handling. It's difficult to follow because
> it's
> >     been heavily optimized for performance.
> >
> >     In any event, AppArmor will usually see capability requests after the
> >     usual DAC permissions are handled.
> >
> >
> >     > Query 3:
> >     >
> >     > - Does all system calls need capability when it runs in a non-root
> process,
> >     > how does apparmor mapping the linux capabilities?
> >
> >     "root processes" means both uid 0 as well as having capabilities in
> the
> >     effective capability set. (Perhaps it'd also make sense to consider
> the
> >     other capability sets in the process?) A uid 0 process with no
> >     capabilities still has considerable power, since many important
> files like
> >     /etc/sudoers are owned by uid 0, and modifying these files through
> DAC
> >     permissions alone could be used to then gain capabilities. However,
> a uid
> >     0 process with no capabilities couldn't itself initiate a reboot in
> the
> >     kernel, or override DAC restrictions on files, etc.
> >
> >     A process with capabilities need not be uid 0 though I can't
> immediately
> >     point any common examples.
> >
> >     Linux's uid namespaces makes things a bit more complicated: a
> process can
> >     have namespace-level capabilities that do not extend to capabilities
> in
> >     the init namespace. (Consider something like an LXD guest: there may
> be
> >     different users within the guest, and the 'root' user with the LXD
> guest
> >     can do privileged operations over the namespace, eg manage the
> routing
> >     table used for that network namespace, but not be able to manage the
> >     routing table used by the network namespace for the init process.)
> >
> >     See the user_namespaces(7) and unshare(2) manpages for some more
> information.
> >
> >     > Can someone please clarify these queries?
> >
> >     I'm afraid my description probably made things worse.
> >
> >     Let me try one quick simple thing:
> >
> >     Run your example with and without root privileges. You'll see the
> >     difference in AppArmor log output. Hopefully that helps. :)
> >
> >     Thanks
> >
> >
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.ubuntu.com/archives/apparmor/attachments/20200804/50f7a591/attachment.html>


More information about the AppArmor mailing list