AppArmor for Complete System - Including init, PID1, Systemd, Everything! - Full System MAC policy

Glad you like it!

I couldn’t stop myself and implemented most of what I said in my previous post regarding restricted APT. Took the liberty to add to git.

Please have a look. I think I can do a good job wrt rapt, not so much inventing the apparmor stuff. Let me know any other requirements for rapt, I’ll see what I can do or send pull requests.

2 Likes

It looks great!

Whenever running it with the update command or no command at all (just ./rapt), I get this error:

E: Command line option --simulate is not understood in combination with the other options

Also, in the top comment, it says “apparmor-profile-anondist” when it should be “apparmor-profile-everything”. That was my mistake.

1 Like

A compromise would be having a static full system MAC mode in GRUB that’s not meant to support arbitrary application installs for it to be more maintainable and not an entire separate spin.

3 Likes

Fixed.

There might still be a ton of test cases… This also deserves unit tests for common apt commands.

What about exit codes for rapt? Usually, forward the exit code by real apt. But in case of rapt error out…? Start with exit code 150 (or else)? Then for each failure case exit with a different exit code?

http://tldp.org/LDP/abs/html/exitcodes.html

That would be useful for the unit testing. To check if it exit with errors as expected for that test case.

1 Like

Please let me know

  • all kinds of APT commands which should be restricted. (or not so much since we use white listing),
  • which ones should be permitted,
  • and a list of packages which should be refused removal.

So I can implement and test.

1 Like

More boot modes…? But it could get a bit convoluted. This was as far as it was discussed earlier:


Alright. So for future when apparmor-profile-everything is ready…

  • persistent + regular [apparmor-profile-everything]
  • persistent + full-root (DANGER!)
  • live + regular [apparmor-profile-everything]
  • persistent + full-root (DANGER!)

And later if no-root gets implemented…

  • persistent + no-root [apparmor-profile-everything]
  • persistent + root [apparmor-profile-everything]
  • persistent + full-root (DANGER!)
  • live + no-root [apparmor-profile-everything]
  • live + root [apparmor-profile-everything]
  • persistent + full-root (DANGER!)

(Didn’t think much yet about the wording. Open for suggestions. Can be done when time has come.)

Related: multiple boot modes for better security: persistent user | live user | persistent secureadmin | persistent superadmin | persistent recovery mode


Now we have more suggestions which could be different boot modes.

  • “read-only root” (no modifications at all) [0]
  • No arbitrary apt package installation.

[0] No apt package installation, removal, upgrades. Similar to “read-only root”. Not really “real” read-only root.


I am not sure “no arbitrary package installation” gives us any more flexibility / features than “read-only root”. At the same time “no arbitrary package installation” is probably more difficult to implement than “read-only root”. Or perhaps better called “no APT”.

I don’t know what @madaidan thinks about a “no APT” or “no writing to /etc/ /usr/bin” or “non-admin” boot mode.

Perhaps this is the same as “noroot boot mode”? Perhaps the “noroot boot mode” should have a more restrictive full system apparmor profile?

2 Likes

Probably best to develop this on plain Debian? (Non-Whonix) Worry about Whonix integration later. Does this work on Debian yet?

There is a lot of bad things a compromised root can do with mount such as remounting apt / rapt with a script of its choice. Not sure how this could be contained? Can you let the “system” use mount but any “users” (those using serial console, virtual terminal or ) not using mount?

Since initrd is unconfined for now… Are there things in initrd (processes) which are still lingering after boot and unconfined? Writing to the initrd (in memory, not disk image after booting is done shouldn’t have bad effects and is blocked anyhow?

2 Likes

Thinking about this to prevent choice proliferation:

What would be the use case for a root system with apparmor everything?

You might as well make no-apt synonymous with apparmor-everything because there is no functional advantage to having apt on a system with apparmor-everything (unless you are editing system policy and adding support for more programs).

These are the only boot combinations that make sense to me:

persistent + full-root (DANGER!)
persistent + no-root
persistent + no-root [apparmor-profile-everything]
live + root (*)
live + no-root
live + no-root [apparmor-profile-everything]

(*) I am not sure there’s any useful usecase for having full root in live mode since you can install stuff in no-root mode without needing the full root access.

On the contrary. This mode would be useful if a user wants to install and use arbitrary packages from a safe source without risking full system compromise in case the software has a vuln. Apparmor-everything would make this impossible I think.

2 Likes

I don’t think there should be a “no apt” boot mode. Just unneeded complexity.

Root is far more privileged than ordinary users even with apparmor everything.

Yes there is. Apt works fine with apparmor-profile-everything. Even kernel updates do.

2 Likes

I haven’t tested it on Debian and I don’t see why we’d want to when getting it working in Whonix is our main goal.

Is that possible without being able to write to rapt? All binaries/libraries are read-only by default (except in the apt-get profile).

We can probably restrict it to specific users with MLS but preventing even root from doing it won’t work as root is what mounts/unmounts the filesystems at boot/shutdown.

The best option I can think of is to restrict mount to specific directories and mount options https://manpages.debian.org/buster/apparmor/apparmor.d.5.en.html#Mount_Rules

Initrd is temporary and only used to prepare the actual root filesystem. I don’t think there’s anything lingering after boot.

Besides, I don’t see how it would even be possible to confine the initrd unless somehow modifying the bootloader to only run the initrd in apparmor.

1 Like

Would this still make sense with rapt’s package removal blacklist?

I think it would be good for defense in depth. We can also verify hashes to be sure.

1 Like

Yes, we shouldn’t make this a usability mess.
There is even recovery mode (already, standard feature of any/most linux distribution).

That even root cannot escalate to kernel space. Therefore cannot (or harder) to attack the virtualizer or install a rootkit. This might break various malware or exclude classes of exploits.

related: Untrusted Root - improve Security by Restricting Root

Makes sense as per above. apt dist-upgradeing the system while preventing third party repositories.

Yes, aka “full admin mode”. Just as Whonix works right now.

I don’t see what the latter would be good for.

live+noroot: Install software to home folder and execute it?
live+root: could install software from repository. Test upgrades. (The test’s usefulness is limited but non-zero.)
Tails has an optional root mode for live sessions too.
But indeed, I am not sure a live+root option is important enough to have it easily accessible through grub boot menu as our space there is limited. Could be accessible in custom configurations / grub manual boot kernel parameter.

noroot: install to home folder?
noroot meaning: “sudo apt” cannot be used.

Ok.

Since you’re implementing this, that’s fair. Also indeed too many options may be confusing. We can’t perfect this in every aspect for every use case.

Yes. Any file can be remounted with any other file. Another file can be mounted “on top” of another file. The file “below” will be no longer accessible (as much as I know).

2 Likes

Then in that case, until we properly restrict mount rules, wouldn’t deny mount /usr/bin/rapt, be enough?

1 Like

No, I wouldn’t know a good reason for that now. Threat model is here: an attacker specifically targeting apparmor-profile-everything, right? An attacker that manages to remove apparmor even though rapt should prevent that probably has sufficient capability to also modify initrd.

Not easy. Create the hashed. Or get them. From where. Then at initramfs time, make sure they’ve not been tampered with. And update these hashes after upgrades to avoid false positives. Seems really complex. Hopefully not needed.

I don’t think so. Because rapt will be using bash and apt. And these need libraries. By re-mourning any library files with malicious versions, anything is possible. The mount command opens the door for a lot creativity.

1 Like

Android seems to use an equivalent of apparmor environment scrubbing (AT_SECURE on everything).

https://android.googlesource.com/platform/system/sepolicy/+/refs/heads/master/public/init.te#597

# The use of sensitive environment variables, such as LD_PRELOAD, is disallowed
# when init is executing other binaries. The use of LD_PRELOAD for init spawned
# services is generally considered a no-no, as it injects libraries which the
# binary was not expecting. This is especially problematic for APEXes. The use
# of LD_PRELOAD via APEXes is a layering violation, and inappropriately loads
# code into a process which wasn't expecting that code, with potentially
# unexpected side effects.

I’m thinking of using apparmor’s environment scrubbing on all binaries although that would break using LD_PRELOAD for hardened_malloc.

Also, using a different environment for apt is not enough. Attackers can still write to /etc/ld.so.preload and other /etc/ld.so.* files so everything preloads their malicious library, including apt even with a new environment.

But, using environment scrubbing and disallowing writing to /etc/ld.so.preload will prevent us from using hardened_malloc at all unless we build it into glibc ourselves which doesn’t seem like a good idea unless debian provides a glibc-hardened-malloc package or similar.

2 Likes

I would say go for ld preload scrubbing. Far to dangerous. And I don’t think users use hardened malloc much. (We’d have to preconfigure that and/or simply.)

Could we have a wrapper that adds hardened malloc ld preload?

Also sudo can filter env vars. Maybe some “sudo - u user something” sudoers exception could help?

Maybe a wrapper script (whitelisted in apparmor) that sets hardened malloc ld preload?

2 Likes

With Qubes dom0 kernel:

Does not work with dom0 kernel. This is expected since by using dom0 kernel it also used dom0 initrd. Therefore apparmor-profile-everything cannot function. The good news about this is, that it does not seem to break anything either.

sudo aa-status

apparmor module is loaded.
16 profiles are loaded.
16 profiles are in enforce mode.
/**/*-browser/Browser/firefox
/usr/bin/apt-get
/usr/bin/man
/usr/bin/whonixcheck
/usr/lib/sdwdate/url_to_unixtime
/usr/lib/security-misc/pam_tally2-info
/usr/lib/security-misc/permission-lockdown
/usr/sbin/haveged
bootclockrandomization
firejail-default
init-systemd
man_filter
man_groff
nvidia_modprobe
nvidia_modprobe//kmod
system_tor
0 profiles are in complain mode.
1 processes have profiles defined.
1 processes are in enforce mode.
/usr/sbin/haveged (519)
0 processes are in complain mode.
0 processes are unconfined but have a profile defined.


With Qubes VM Kernel:

Results coming soon.

1 Like

Nov 23 10:49:09 host audit[961]: AVC apparmor=“DENIED” operation=“exec” profile=“/usr/lib/security-misc/pam_tally2-info” name=“/usr/sbin/pam_tally2” pid=961 comm=“pam_tally2-info” requested_mask=“x” denied_mask=“x” fsuid=0 ouid=0
Nov 23 10:49:09 host audit[961]: AVC apparmor=“DENIED” operation=“open” profile=“/usr/lib/security-misc/pam_tally2-info” name=“/usr/sbin/pam_tally2” pid=961 comm=“pam_tally2-info” requested_mask=“r” denied_mask=“r” fsuid=0 ouid=0
Nov 23 10:49:09 host kernel: audit: type=1400 audit(1574506149.778:19): apparmor=“DENIED” operation=“exec” profile=“/usr/lib/security-misc/pam_tally2-info” name=“/usr/sbin/pam_tally2” pid=961 comm=“pam_tally2-info” requested_mask=“x” denied_mask=“x” fsuid=0 ouid=0
Nov 23 10:49:09 host kernel: audit: type=1400 audit(1574506149.778:20): apparmor=“DENIED” operation=“open” profile=“/usr/lib/security-misc/pam_tally2-info” name=“/usr/sbin/pam_tally2” pid=961 comm=“pam_tally2-info” requested_mask=“r” denied_mask=“r” fsuid=0 ouid=0

1 Like
1 Like

No, doesn’t work yet.

cat /proc/version

Linux version 4.19.0-6-amd64 (debian-kernel@lists.debian.org) (gcc version 8.3.0 (Debian 8.3.0-6)) #1 SMP Debian 4.19.67-2+deb10u2 (2019-11-11)

sudo aa-status

apparmor module is loaded.
16 profiles are loaded.
16 profiles are in enforce mode.
/**/*-browser/Browser/firefox
/usr/bin/apt-get
/usr/bin/man
/usr/bin/whonixcheck
/usr/lib/sdwdate/url_to_unixtime
/usr/lib/security-misc/pam_tally2-info
/usr/lib/security-misc/permission-lockdown
/usr/sbin/haveged
bootclockrandomization
firejail-default
init-systemd
man_filter
man_groff
nvidia_modprobe
nvidia_modprobe//kmod
system_tor
0 profiles are in complain mode.
1 processes have profiles defined.
1 processes are in enforce mode.
/usr/sbin/haveged (431)
0 processes are in complain mode.
0 processes are unconfined but have a profile defined.

[user@dom0 ~]$ sudo xl console whonix-ws-15

.[30m.[47mWelcome to GRUB!

.[37m.[40m.[37m.[40m.[37m.[40m.[3;35H [ grub-xen.cfg 424B 100% 1.53KiB/s ].[3;1Herror: no such device: /boot/xen/pvboot-x86_64.elf.
Reading (xen/xvda,gpt3/boot/grub/grub.cfg
.[H.[J.[1;1H.[1;36H [ grub.cfg 5.67KiB 100% 8.15KiB/s ].[1;1Herror: file /boot/grub/fonts/unicode.pf2' not found. error: no suitable video mode found. .[H.[J.[1;1H Booting Whonix GNU/Linux’

Loading Linux 4.19.0-6-amd64 …
.[4;24H [ vmlinuz-4.19.0-6-amd 5.03MiB 100% 4.95MiB/s ].[4;1HLoading initial ramdisk …
.[5;22H [ initrd.img-4.19.0-6- 25.46MiB 100% 23.39MiB/s ].[5;1H[ 0.000000] Linux version 4.19.0-6-amd64 (debian-kernel@lists.debian.org) (gcc version 8.3.0 (Debian 8.3.0-6)) #1 SMP Debian 4.19.67-2+deb10u2 (2019-11-11)
[ 0.000000] Command line: BOOT_IMAGE=/boot/vmlinuz-4.19.0-6-amd64 root=/dev/xvda3 ro xen_scrub_pages=0 root=/dev/mapper/dmroot console=hvc0 console=tty0 swiotlb=8192 noresume intel_iommu=on amd_iommu=on slab_nomerge slub_debug=FZP mce=0 pti=on mds=full,nosmt

user@host:~$ sudo update-initramfs -u

update-initramfs: Generating /boot/initrd.img-4.19.0-6-amd64
I: The initramfs will attempt to resume from /dev/xvdc1
I: (UUID=aa5657bd-b175-42e0-93df-833b6cd3f8c7)
I: Set the RESUME variable to override this.
user@host:~$ ls /boot/initrd.img-4.19.0-6-amd64
/boot/initrd.img-4.19.0-6-amd64
user@host:~$ ls -la /boot/
total 31436
drwxr-xr-x 3 root root 4096 Nov 23 11:09 .
drwxr-xr-x 20 root root 4096 Nov 23 10:40 …
-rw-r–r-- 1 root root 206361 Nov 11 00:30 config-4.19.0-6-amd64
drwxrwxr-x 2 root root 4096 Nov 23 10:43 grub
-rw-r–r-- 1 root root 26696863 Nov 23 11:09 initrd.img-4.19.0-6-amd64
-rw-r–r-- 1 root root 5270768 Nov 11 00:30 vmlinuz-4.19.0-6-amd6

1 Like