[apparmor] environment variables
John Johansen
john.johansen at canonical.com
Tue Nov 8 07:13:49 UTC 2011
So we have been looking into handling the environment variable problem, and
it was discussed at our UDS planning session. To summarize several
applications, and frameworks are leveraging environment variables to
control execution behavior.
For glibc this behavior is controlled by secure exec which filters out,
certain environment variables, eg. LD_PRELOAD. However secure exec only
defines a small black list, and currently only removes the specified
variables from the environment. A more flexible and generic solution is
needed, preferably one we can tie to policy.
Python, Perl, gtk, etc. all have environment variables that can affect
program execution. We can currently control attacks(1) using environment
variables that redirect elf object library files by ensuring w and m
permissions do not overlap, so that an application can not map something
it has written as executable. However m does not tend to work for
scripting languages which may not map code as executable.
A dumb extension of secure exec does not seem to be a viable solution
either, as some environment variables need to be set for applications
to work, eg. the dbus session bus address, and yet we would like to be
able to control the value or range of values a variable could have.
(1) The use of m does not work for U/u x transitions, as the target is
not confined.
There are a few potential solutions and implementations, we could extend
filtering, extend exec matching, or create a hybrid solution. Each
solution has its own issues, and design decisions.
1. Matching
The idea here is to extend the exec matching rules, with a conditional
match.
Eg. something like
env={LD_PRELOAD=/usr/bin/*,FOO=bar} /bin/foo Ux,
The specifics of what it would actually look like is dependent on a few
points.
1a. Should environment variable matching be on the rule, profile or both?
Placing environment matching on the profile seems to make sense until
you consider the Ux case, as there is no profile to match against.
It would be possible to place the match on Ux rules, or to define
a special dummy profile for Ux transitions.
1b. Should failing to match result in a failed exec or should it fall back,
and try continuing the match against a more generic, or alternate target.
This would allow things like
env={VAR_FOO=BAR} /bin/foo Ux,
/bin/* ix,
The fall back approach seems appealing at first glance but it might
provide an attacker control over which profile is applied by setting
the environment variables.
1c. What should the match expression look like, should it be a white list,
or a black list. Should it use aare syntax, or perhaps pcre syntax?
I will note that we do want to be able to make positive assertions
like (ie. that is the value it should have).
DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-iOIxOeHCR6,guid=435b295c9d1fc4337e6f1ac100000271
while at the same time, also allow many generic environment variables
match. This is needed because environment variables carry a lot of
variables that change from system to system, application to application.
Policy will be hard to write unless there is some generic env var matching.
The is also hard to express in the current aare white listing syntax.
1d. Compatibility. Should the env conditional matching be able to be dropped
by the kernel if it doesn't support it and still match a profile/exec
rule.
2. Environment filtering
Environment filtering would be like extending the existing secure exec, except
with policy involvement, so the environment variable filtering could be defined
per rule or profile.
It has many of the same questions as Matching.
2a. Should environment variable filtering be on the rule, profile or both?
2b. Should environment filtering be a white list or a black list?
2c. Should it use aare, or pcre syntax, or maybe multiple entries.
2d. Should env filtering be backwards compatible.
In general environment variable filtering should be easier to develop policy
for as it won't fail because it encounter variables it doesn't have rules for.
3. Hybrid
It would be possible to have a hybrid of matching and environment filter if
there is a compelling need and we can devise a reasonable syntax.
4. Implementation
The likely implementation seems to be in the kernel in the bprm hook called
during exec. Environment filtering could be achieved by extending secure
exec in the libc loader. However this solution is problematic in that it
relies on all binaries to be linked against the revised loader which
in many cases is not an assumption that can be made.
Another point is that with kernel variables we could support better matching
of values that change per session but should be static during the session.
For example the dbus session bus, shouldn't change for the duration of the
session, so a kernel var could be set when the session is setup, and then
that value would be matched against for all processes in the session.
This is of course assuming certain unimplemented features exist. For the
moment we would be limited to asserting static values with an eye towards,
dynamic values in the future.
More information about the AppArmor
mailing list