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

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

The initrd looks alright in so far that it contains strings of the changes to initrd.

mkdir /tmp/initrd
cd /tmp/initrd
zcat /boot/initrd.img-4.19.0-6-amd64 | cpio -idmv
grep -r -i apparmor

scripts/init-bottom/apparmor-profile-everything:echo “profile init-systemd /lib/systemd/systemd flags=(complain) {}” | /sbin/apparmor_parser -a
scripts/init-bottom/ORDER:/scripts/init-bottom/apparmor-profile-everything “$@”
Binary file usr/sbin/apparmor_parser matches
Binary file usr/bin/udevadm matches
Binary file usr/lib/systemd/systemd-udevd matches

1 Like

The binary the wrapper script executes would have to be whitelisted. We can’t just whitelist the wrapper.

We could probably make a list of programs to use hardened_malloc with and whitelist them but then that would also allow any malicious LD_PRELOAD tricks on those programs.

Or, maybe we can make an issue on the apparmor gitlab repo about adding specific variables that can be whitelisted when using environment scrubbing if that’s even possible.

e.g.

/bin/bash Pix allow_var="LD_PRELOAD=/usr/lib/libhardened_malloc.so",

So this would only allow preloading hardened_malloc and nothing else.

1 Like

apparmor-profile-everything breaks Qubes upgrading
https://phabricator.whonix.org/T936

1 Like

Thank you for submitting this feature request!

1 Like

Got a response:

This one will not come quickly: the environment scrubbing isn’t actually performed by AppArmor but by the system c library. AppArmor sets the same flag that’s used when setuid/setgid programs are executed, and when the program starts, libc notes the flag and scrubs environment before going very far.

Providing granularity when scrubbing the environment is something we want to do but I don’t think it’ll happen for a while.

The good news is that you could steal the environment scrubbing routine from glibc, add it as a constructor to your libhardened_malloc.so, and modify AppArmor policy to stop setting the secure exec flag when you want to use this library. That way you could still get a mostly-scrubbed environment and use the different allocator. It might not be as easy as this fine-grained scrubbing feature but you could be using it a lot sooner.

I think the bottom part is suggesting we modify hardened_malloc to scrub the environment for us instead of using apparmor for it.

2 Likes

Worth contacting hardened malloc upstream?

Can you make head or tail of this? If not, let’s ask?

1 Like

Probably.

It means to make the apparmor policy execute those binaries without scrubbing the environment as hardened_malloc would handle it (with the proposed solution).

1 Like
2 Likes