[apparmor] RFC: handling xdg-open and similar helpers
John Johansen
john.johansen at canonical.com
Thu Jan 25 19:29:26 UTC 2018
On 01/25/2018 10:15 AM, Vincas Dargis wrote:
> On 1/25/18 9:31 AM, John Johansen wrote:
>> On 01/21/2018 08:27 AM, Vincas Dargis wrote:
>>> Hi,
>>>
>>> I have some WIP AppArmor profiles for applications that uses `xdg-open` to open link or attachment. For example, `usr.bin.dragon` profile (KDE multimedia player) has this line [0]:
>>>
>>> ```
>>> /usr/bin/xdg-open Cx -> sanitized_helper,
>>> ```
>>>
>>> Aaand.. I don't like it.
>>>
>> you are not the only one. It was meant as a temporary solution. However the real solution or better control over environment scrubbing was deprioritized. But its important and needs to be finished off once the current delta is upstream
>
> Even if environment scrubbing would work, should it still allow execute xdg-open _anything_ (like that example) directly?
it would depend on how you structure your policy, you certainly don't have to allow it
>
> My idea is to limit what these kind of helpers could execute, regardless if environment is scrubbed or not. I am focusing on that example where Dragon should be allowed to launch only browsers and email clients via xdg-helper helper.
>
sure, and that should basically eliminate the problem that sanitized_helper is trying to deal with
> Without that limitation, if user has ".sh" associated with "gnome-terminal -x %s" for some convenience reason, Dragon would launch xdg-open that would launch an interpreter for the attacker.
>
yep
>>> Dragon only needs to open browser (for clicking "Help -> Report a bug") and email client (when clicking translator's email button in About dialog), and that's it. So I figure that a more secure approach (by limiting allowed target applications to open something with) could be implemented by using abstraction in a child profile. Consider this alternative:
>>>
>>> ```
>>> /usr/bin/xdg-open Cx -> xdg_open,
>>>
>>> profile xdg_open {
>>> #include <abstractions/xdg-open> # or should it be xdg-open-common ?
>>>
>>> # Dragon only needs to open http: and mailto: links
>>> #include <abstractions/ubuntu-browsers>
>>> #include <abstractions/ubuntu-email>
>>> }
>>> ```
>>>
>> sure this will work for this situation
>
> I am kinda imaginary adding emphasis on *this*" :) . Do you have something specific in mind, what could be other situations that I should be aware of (I really don't have that much experience in all of this) ?
>
So you have to understand my reply was in the context of not liking sanitized helpers, they unfortunately still have a role. As long as we are talking confinement on the targets we should be fine. The sanitized helpers were specifically for going from a confined to a "lightly" confined or unconfined situation. To quote abstractions/ubuntu-helpers
# Lenient profile that is intended to be used when 'Ux' is desired but
# does not provide enough environment sanitizing. This effectively is an
# open profile that blacklists certain known dangerous files and also
# does not allow any capabilities. For example, it will not allow 'm' on files
# owned be the user invoking the program. While this provides some additional
# protection, please use with care as applications running under this profile
# are effectively running without any AppArmor protection. Use this profile
# only if the process absolutely must be run (effectively) unconfined.
#
# Usage:
# Because this abstraction defines the sanitized_helper profile, it must only
# be #included once. Therefore this abstraction should typically not be
# included in other abstractions so as to avoid parser errors regarding
# multiple definitions.
#
# Limitations:
# 1. This does not work for root owned processes, because of the way we use
# owner matching in the sanitized helper. We could do a better job with
# this to support root, but it would make the policy harder to understand
# and going unconfined as root is not desirable any way.
#
# 2. For this sanitized_helper to work, the program running in the sanitized
# environment must open symlinks directly in order for AppArmor to mediate
# it. This is confirmed to work with:
# - compiled code which can load shared libraries
# - python imports
# It is known not to work with:
# - perl includes
# 3. Sanitizing ruby and java
#
# Use at your own risk. This profile was developed as an interim workaround for
# LP: #851986 until AppArmor utilizes proper environment filtering.
>>> Another applications, like Skype, might need much more abstractions included to open various attachement files for example.
>>>
>>> I know (but only know, now actual experience) that there are `exo-open` relevant for XFCE desktop, that also could have it's own abstraction prepared too.
>>>
>>> If this approach seems sensible for AppArmor team, I could start working on this.
>>>
>> I am not opposed where it makes sense but we have to be careful when it comes to transitions with applications that use an interpreter (bash, python, perl java), because currently we can't sanitize Env vars that can affect the interpreters behavior. As long as the transition is to a tight confinement we are okay, but if its to unconfined or a loose generic interpreter profile env vars become away for the attacker to control the child
>
> So, if <abstraction/ubuntu-email> would have[0] `/usr/bin/thunderbird` rule, and it is actually a bash script, we are kinda.. screwed?
>
no, its only if that bash script consults the environment variables to determine what to execute and that decision can be used to change the confinement to something looser than would be allowed.
Lets say I have a script that responds to $HELPER
the profile
/bin/foo px,
/bin/bar px,
is fine, because even if $HELPER is set by an attack to something else confinement transition is limited to those 2
now if I have a profile
/bin/foo px,
/bin/bar px,
/** ux,
allowing an attacker to control $HELPER could be used to unconfined state
> Does my xdg_open child profile makes situation worse?
no
> I imagine if that child profile uses abstractions, and these abstractions also use sanitized_helper, I see improvement against `xdg-open -> sanitized_helper`, or I am wrong / missing something?
>
> ... epiphany happens ...
>
> Oh, I see that xdg-open _itself_ is a shell script, maybe that's the problem here?
>
>
I think I have covered above
>>> Or maybe there are, or going to be implemented, some other alternatives? Maybe upcoming delegation could offer different approach?
>>>
>> delegation could help some but we really need to finish with the better control over env var scrubbing, relying on the secure exec flag in glibc isn't enough in some cases
>
> Maybe you mean like that _capital_ C in "Cx" does not help here enough?
>
correct the env var scrubbing is done by setting a flag in the kernel that the elf loader/linker responds to scrubbing certain dangerous environment variables. But script interpreters have their own dangerous set beyond what the elf loader scrubs, we plan to make it so you can specify additional scrubbing in policy.
> Thanks!
>
> [0] P.S. it does not. It's a missing rule I guess, as xdg-open runs kde-open5 that actually runs /usr/bin/thunderbird` in the end, not that /usr/lib/thunderbird... we currently have:
>
> $ sudo sysdig "(proc.name=xdg-open or proc.name=kde-open5) and evt.type=execve"
>
> $ xdg-open "mailto:foo at example.com"
>
> Sysdig output:
>
> 69924 19:56:04.319244632 0 xdg-open (7664) < execve res=0 exe=/bin/sh args=/usr/bin/xdg-open.mailto:foo at example.com. tid=7664(xdg-open) pid=7664(xdg-open) ptid=2446(bash) cwd= fdlimit=1024 pgft_maj=0 pgft_min=35 vm_size=440 vm_rss=4 vm_swap=0 comm=xdg-open cgroups=cpuset=/.cpu=/.cpuacct=/.io=/.memory=/.devices=/user.slice.freezer=/.net_cls=... env=GS_LIB=/home/vincas/.fonts.KDE_FULL_SESSION=true.LANG=lt_LT.UTF-8.PROFILEHOME... tty=34818
>
> 70049 19:56:04.321695532 0 xdg-open (7665) > execve filename=/usr/bin/kde-open5
>
> 70054 19:56:04.321926012 4 kde-open5 (7665) < execve res=0 exe=kde-open5 args=mailto:foo at example.com. tid=7665(kde-open5) pid=7665(kde-open5) ptid=7664(xdg-open) cwd= fdlimit=1024 pgft_maj=0 pgft_min=21 vm_size=344 vm_rss=4 vm_swap=0 comm=kde-open5 cgroups=cpuset=/.cpu=/.cpuacct=/.io=/.memory=/.devices=/user.slice.freezer=/.net_cls=... env=KDE_FULL_SESSION=true.PROFILEHOME=.GS_LIB=/home/vincas/.fonts.HISTTIMEFORMAT=... tty=34818
>
> 107801 19:56:04.410087956 1 kde-open5 (7668) > execve filename=/usr/bin/thunderbird
More information about the AppArmor
mailing list