
On Mon, Apr 12, 2021 at 6:58 PM Christian Boltz <opensuse@cboltz.de> wrote:
Hello,
Am Samstag, 10. April 2021, 14:05:02 CEST schrieb Attila Pinter:
Not sure if I can give you a link that covers everything instead I share this (sorry ^_^):
TL;DR: AppArmor has no MLS/MCS support,
I have to admit that I'm not really familiar with SELinux, but after reading the page you linked at the end of the mail [0], I hope that I can answer nevertheless.
(If something I wrote about SELinux is incorrect, please correct me.)
My understanding is that MLS/MCS is about security/sensitivity levels, and basically allows to make objects (files) read-only, read-write or write-only depending on the trust level of a program, right? ["program" is probably simplified]
You can also do this with AppArmor, a profile can have: /tmp/writeonly w, /tmp/readwrite rw, /tmp/readonly r,
And you can have these permissions different for each program / in each profile, so that another program can for example only read /tmp/readwrite.
In a real-world usage example, you'll need to allow apache to (only) read your SSL certs and keys, while dehydrated needs to write your certs and keys, but probably doesn't ever need to read the cert's key. That's easily doable by having separate profiles for apache and dehydrated. You can even have child profiles in the dehydrated profile that limit some permissions to the openssl binary, and have an as-restrictive-as- possible child profile for the part with network access that talks to the letsencrypt server.
(In case someone wonders - I don't have a profile for dehydrated yet, but the only reason is that I still use acmetool for historical reasons. I'm sure I could create a profile for dehydrated in less than an hour.)
policy generation depends on a single wrapper, can't generate policies for containers,
Not sure what you mean with "single wrapper" here, can you please explain?
What I know is that docker and podman come with a very permissive default AppArmor profile that is applied _inside_ the container [1], and that you also have the option to run a container with a separate (and hopefully more restrictive) profile using docker run --rm -it--security-opt apparmor=your_profile $container (see https://docs.docker.com/engine/security/apparmor/ for details, and https://www.suse.com/c/demystifying-containers-part-iv-container-security/ confirms that podman also supports this).
Note: This is about the profile _inside_ the container, and while it's very (IMHO: too) permissive, it also blocks access to some security- relevant things in /proc/.
So far, I avoided working with containers ;-) and I don't know too much about them, but I'm quite sure that you can also apply a profile on the "outside" of the container, using different profiles for each container so that it can only access its own stuff. (However, I'm not sure if docker and podman currently support this, but if not, it should be easy to implement.) If you do this, the profiles outside and inside the container will be stacked, and only actions that are permitted in both profiles will be allowed.
security is unfortunately not easy.
While I agree in general, I'd argue that AppArmor is quite easy ;-) I'd even claim that my ~30 minutes "AppArmor Crash Course" talk gets you started good enough to understand AppArmor profiles and to create and update your own profiles with the aa-* tools.
So far, I haven't seen a talk about SELinux that gets me started in that timeframe ;-)
I could probably give such a talk if you wanted one. :) I'm fairly good with SELinux policy stuff and have written my fair share of policy modules. But Thomas Cameron has given a similar talk on SELinux over the years that you might find enlightening: https://www.youtube.com/watch?v=_WOKRaM-HI4
AppArmor and SElinux are very similar in what and how they're doing
Well, yes and no. Yes for "they both make the system more secure" ;-)
One big difference is that AppArmor aims at securing specific programs (for example deamons that have a network port open), while SELinux does full system confinement (right?). (AppArmor can also do full system confinement, but so far I'd call it a more exotic way of using AppArmor, and only a few people reported doing it.)
Aiming at specific programs has the big advantage that you can focus on the biggest risks (if you run a server, obvious attack surfaces are for example attacks against your webserver - actually not the webserver itsself, but the forums software it hosts. Therefore restricting what that virtual host on your webserver can do is a) important and b) very worth the time spent. (Actually I auto-generate profiles for my vhosts that allow the usually needed things, so "time spent" for additional virtual hosts means a few seconds to run my script.)
OTOH, running other programs is less risky. For example, I trust logrotate ;-) and I also don't think that it makes too much sense to confine the login shell of an admin. Sure, the admin can also do evil things, but then, that admin probably also knows ways to get rid of the confinements and then do the evil things.
This doesn't mean that you can't confine users - quite the opposite, there's even the pam_apparmor module to do this ;-) It allows you to put a user under a specific profile that allows only what you want to allow, and for sure can be useful in some cases.
things. Major difference to note is that SELinux is labeling every object while AppArmor is using paths.
Right, and both ways have pros and cons.
However, my biggest beef with AppArmor is that it lacks tooling and it is absolutely incapable of
What exactly do you mean with "lacks tooling"?
Since you mentioned audit2allow later - do you know aa-genprof (to generate a profile based on audit.log), aa-logprof (to update existing profiles based on audit.log) and all the little aa-* helpers?
I'd argue that this doesn't really match "lacks tooling" ;-)
running in an environment where fine grained security is important or mandatory (govt, data center etc) as it lack MLS and MCS capabilities. Sure it is easier - and I'm using the word easy very loosely as it is a matter of experience and knowledge - to create policies, but that is mostly because that it is not able to do as much as SELinux does (no MLS/MCS) making it a lot less complex than SELinux. Thanks to this AppArmor is also not a good choice for containers as it is unable to separate container from each other or from the host properly due to the lack of MLS/MCS. In an era when micro-services and containers are the de facto way of deploying applications this is a critical problem and pretty sure that this is one of the reasons why MicroOS has moved to SELinux.
It might make sense for MicroOS and containers (however, see above), but I somewhat doubt that SELinux makes sense on desktops or more traditional servers running services (without using containers).
Nevertheless, I'm always happy to learn, therefore I'll give you some usecases where I'd be interested how to implement them with SELinux (I actually have AppArmor profiles for them, and want to keep these things as secure as they are now):
- quilt: You might know that "quilt setup" expands all variables in a spec file, which might also mean executing programs in cases like define serverroot %(/usr/sbin/apxs -q datadir ) (Evil specfiles could also have something like "%(rm -rf /)" - and even if file permissions would limit the damage to "just" deleting the home directory, it would still be more than enough damage.) Therefore I have a profile for quilt that - while allowing to execute several programs - only allows to read files in my package directory, and only to write to *.diff, *.patch and in subdirectories of each package (when unpacking the tarball and applying the patches). Obviously this is something that is based on paths and filenames a lot, therefore I wonder how SELinux would manage to restrict quilt in a similar way.
- samba: We ship AppArmor profiles for samba that are enabled by default, and these profiles get updated to allow access to all samba shares automatically with a script when samba starts. (Shameless plug: the samba profiles prevented SambaCry (CVE-2017-7494, remote code execution from a writeable share) from being exploited.) But back to the automatically updated profiles - is SELinux scriptable in a similar way? And does it also automatically remove the permissions again if you remove a samba share from your config?
- lessopen.sh: That's a nice script that makes 'less' more useful for compressed files, converts PDFs to text etc. It comes with a profile that we enable by default to make sure the helpers used by lessopen.sh can read everything, but can only write tempfiles. Since 'less' gets used to look at files from various (including untrusted) sources, making sure that for example an archive exploiting unzip can't overwrite random files or execute random programs is quite useful. How would you do this with SELinux?
- apache and php-fpm can switch to separate AppArmor profiles depending on the virtual host they serve. These profiles can have completely different permissions, the typical usecase is to make sure that scripts in one virtual host can only access files of that virtual host, and block them from reading or writing files of other virtual hosts.
- similar: dovecot can switch to a different profile based on the currently logged in user, restricting access to only that user's own data.
- what about files hosted on a NFS or samba server? AppArmor profiles can easily restrict access to specific files or directories on the NFS/cifs mount. Can SELinux also do that?
- backups - I use rsnapshot for my backups, and with a combination of a ssh key and an AppArmor profile, I allow root logins from my backup server (so that it can read all files), but at the same time only allow to execute rsync and to read (not: write) the files to backup. I could also easily deny access to some files - for example, not everybody likes backups of /etc/shadow. (If someone is interested in details how to do this - it's part of my "AppArmor crash course" [3].)
- AppArmor can apply different profiles depending on who/what executed a program, which is very useful - "rsync started by my backup script" needs different permissions than "rsync uploading my homepage" or "rsync downloading the latest Tumbleweed". (Technically, I'm talking about ix, Px and Cx rules, and also Px/Cx -> target_profile.)
I'm looking forward to some details if and how SELinux supports these cases, and how much time I'd have to spend to, for example, make quilt and lessopen.sh as secure as I have it with AppArmor now.
Surely a good come back would be that SELinux can't generate policies, which is true, however that is a conscious decision and it does provide tooling (audit2allow) instead of relying on a single wrapper. Also on what you mentioned about relabeling takes time and resources: I was deploying, running and maintaining CentOS and RHEL servers for about 8 years before we moved everything to openSUSE and this happened to me about twice and took only a 5-10 minutes on boot.
"only"? ;-)
All my AppArmor profiles (and I have much more than what we have enabled by default) take a few seconds to load if the cache is empty/outdated, and maybe one second with an up-to-date cache.
For fairness, I'll repeat that my AppArmor profiles don't do full system confinement - but then, you could also do the full system confinement with a small number of profiles, so the timings won't change too much. (Of course, you could also go crazy with full system confinement and have separate profiles for each program - that's not technically hard, but creating 1000 profiles would be quite some work.)
IMO SELinux is a necessary next step to take.
Sorry, but I disagree - and I also admit that I might be biased ;-)
Offer SELinux as an _option_ in the installer? Fine, why not - openSUSE has always been about choice.
However, I seriously doubt that making it the default for usecases outside of container-focused setups (MicroOS) is a good idea. It will be very hard to get it setup in a way that doesn't break someone's usecase, and you really don't want people to start recommending "just turn SELinux off, and it will work". Yes, it does work. Goodbye, security.
Regards,
Christian Boltz
[0]
[1] I looked at the docker profile some years ago, was completely scared, and the only way I can recommend to use this profile is as a bad example when giving a talk ;-) AFAIK podman uses the same profile. (On the positive side - this is about the profile inside the container, therefore it isn't as terrible as it might sound.)
[2] My AppArmor profile for quilt:
include <tunables/global>
# packages directory # expected layout is @{packages_dir}/$project/$package/ @{packages_dir} = /home/cb/packages/
/usr/bin/quilt { include <abstractions/base> include <abstractions/bash> include <abstractions/consoles> include <abstractions/perl>
deny network inet dgram,
/bin/bash mrix, /etc/group r, /etc/host.conf r, /etc/magic r, /etc/nsswitch.conf r, /etc/passwd r, /etc/resolv.conf r, /etc/rpm/ r, /etc/rpm/* r, /etc/vimrc r, /proc/filesystems r, /run/nscd/db* r, /tmp/ r, /usr/bin/* mrix, /usr/etc/nsswitch.conf r, /usr/lib*/python*/**.so mr, /usr/lib*/ruby/**.so mr, /usr/lib/sysimage/rpm/Packages rk, /usr/lib/sysimage/rpm/Packages.db rk, /usr/share/apache2/build/config_vars.mk r, /usr/share/misc/magic.mgc r, /usr/share/pkgconfig/udev.pc r, /usr/share/quilt/ r, /usr/share/quilt/** r, /usr/share/quilt/scripts/* mrix, /usr/share/vim/** r, /var/lib/nscd/group r, /var/lib/nscd/passwd r, owner /home/*/.exrc r, owner /home/*/.quiltrc r, owner /home/*/.vim/** r, owner /home/*/.viminfo rw, owner /home/*/.viminfx.tmp rw, owner /home/*/.vimrc r, owner /proc/*/fd/ r, owner /proc/*/maps r, owner /tmp/* rw, owner /var/tmp/quilt??????/ rw, owner /var/tmp/quilt??????/* rw, owner /var/tmp/quilt??????/bin/ rw, owner /var/tmp/quilt??????/bin/* w, owner /var/tmp/quilt??????/build/ rw, owner /var/tmp/quilt??????/build/** rw, owner /var/tmp/rpm-tmp.?????? rw, owner @{packages_dir}/** r, owner @{packages_dir}/*/*/*.diff rw, owner @{packages_dir}/*/*/*.diff~ rw, owner @{packages_dir}/*/*/*.patch rw, owner @{packages_dir}/*/*/*.patch~ rw, owner @{packages_dir}/*/*/*/ rw, owner @{packages_dir}/*/*/*/** rwl, }
While SELinux policies don't use rwx style grants for file paths directly, it is possible to construct relatively simple ones that do effectively the same thing. The tricky part is that since SELinux operates on contexts and domains, you can't just outright use file paths. But you can define file paths with a context and lock a process domain to those contexts to get the same result. -- 真実はいつも一つ!/ Always, there's only one truth!