System-wide sandboxing framework - sandbox-app-launcher

We’re currently working on a full system apparmor policy to confine all userspace processes but this has 2 issues:

  1. It doesn’t use more restrictive profiles for user applications. A PDF viewer shouldn’t have the same profile as init.

  2. It can’t make use of technologies like namespaces and seccomp. Seccomp especially is vital for kernel attack surface reduction.

We should automatically sandbox user applications for better confinement with more restrictive rules.

I think we should create a “Whonix app launcher” which sets up a restrictive sandbox. It should:

  • Use different users for each applications. This ensures apps can’t access each other’s data.

  • Be confined by a far more restrictive apparmor profile.

  • Use namespaces and seccomp (preferably via bubblewrap).

  • Not break too many legitimate usecases.

I’ve created a non-working draft to do this.

Main script: Debian paste error

Apparmor profile: Debian paste error

Config file: Debian paste error

I’m not sure how we’re going to choose which apps to sandbox. Maybe via packages’ Section:?

Mobile OSes take a similar approach which we can use for inspiration:

https://source.android.com/security/app-sandbox

Apple Platform Security - Apple Support

https://developer.mozilla.org/en-US/docs/Archive/B2G_OS/Security/System_security (now defunct)

Edit by Patrick:

4 Likes

Sounds really good in theory.

Would apparmor profiles and other default hardening by packages if any be added “on top”?

Could you please scratch Whonix from the name / folder names? I guess this could be generic. Could be part of apparmor-profile-everything?

main_app_dir=“/usr/share/whonix-apps”

Possibly better in user’s /home folder?

How would an application by started by default using the sandbox wrapper without needing to prepend on command line? The good old problem of non-existence of stackable wrappers.

I guess this sandbox wrapper could be implemented without solving the stackable wrappers issue but to really make applications benefit by default (actual Kicksecure / Whonix integration) would require that to be done.

TODO: X11 sandbox

Rather than bothering with X11 (which’s days are numbered hopefully in any case), could you figure out change XFCE’s window manager with a window manager that uses wayland? (Wayland and that idea was mentioned here Enlightenment DE - #10 by Patrick)

1 Like

Yes. They’d be good for even further confinement as they can be tuned for the program.

I think they should be separate. A sandboxing framework can have a lot of use without a full system apparmor policy.

No, all apps are meant to have their own user with their own home folder and be completely isolated from the user’s own home folder. A sandbox isn’t much good if the app can easily access all of the user’s files and other app data.

We could add a few folders that are accessible by all apps so they can share files across.

A post was merged into an existing topic: Stackable Wrappers

A post was merged into an existing topic: Stackable Wrappers

madaidan via Whonix Forum:

Yes. They’d be good for even further confinement as they can be tuned for the program.

Nice.

I think they should be separate. A sandboxing framework can have a lot of use without a full system apparmor policy.

Ok, makes sense.

No, all apps are meant to have their own user with their own home folder and be completely isolated from the user’s own home folder. A sandbox isn’t much good if the app can easily access all of the user’s files and other app data.

We could add a few folders that are accessible by all apps so they can share files across.

Yes.

Running an application under a different user will cause a usability
mess. Imagine downloading a file with Tor Browser and then the user
trying to find that file. Maybe at the same time symlinks to these
folders could be added to the user’s home folder or something?

1 Like

Yes, that’s what I had in mind. We can e.g. symlink "${app_homedir}/Downloads" to /home/user/Downloads.

1 Like

What should the name be? I’m not good with naming things.

1 Like

What about safe or sandbox app launcher?

2 Likes

I’ve made some changes including adding a seccomp filter.

I tested this (manually, the script probably doesn’t work yet) with the Tor Browser and it ran flawlessly.

The seccomp filter has to be generated with a C program. The script compiles and executes https://github.com/madaidan/sandbox-app-launcher/blob/master/usr/share/sandbox-app-launcher/seccomp.c which then creates the seccomp-filter.bpf file (the actual filter). It currently blacklists a bunch of syscalls but a whitelist would be far better.

3 Likes

Any suggestions for apps to test?

Off the top of my head:

  • Tor Browser
  • Hexchat
  • Thunderbird
1 Like

That C code looks short enough.
(I don’t count the many different DENY_SYSCALL since these don’t represent a challange in understanding C code.)
Please keep the C code short as I have to ask favors to get review for these.

/* TODO: Use a whitelist */

Dunno what that means but hopefully not 100s of lines of C code. Ideally any wrappers could be in script languages outside of C if a lot more complexity is required.

We could compile during postinst. Similar to sdwdate.
sdwdate/debian/sdwdate.postinst at master · Kicksecure/sdwdate · GitHub

That keeps the package platform independent.

Could you compile please with a similar command?

gcc /usr/lib/sdwdate/sclockadj.c -o /usr/lib/sdwdate/sclockadj -ldl -D_GNU_SOURCE -Wdate-time -D_FORTIFY_SOURCE=2 -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wl,-z,relro -Wl,-z,now

And then use hardening-check and checksec --file. (Both programs available from packages.debian.org buster repository.)

2 Likes

I will. Much C code isn’t needed for this.

It’d essentially just change DENY_SYSCALL to ALLOW_SYSCALL and then have a list of syscalls to allow rather than a list of syscalls to deny. All syscalls not listed will be denied. It’s far more effective than a blacklist.

checksec output:

RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH	Symbols		FORTIFY	Fortified	Fortifiable  FILE
Full RELRO      No canary found   NX enabled    PIE enabled     No RPATH   No RUNPATH   76 Symbols	No	0		0	seccomp

hardening-check output:

seccomp:
 Position Independent Executable: yes
 Stack protected: no, not found!
 Fortify Source functions: unknown, no protectable libc functions used
 Read-only relocations: yes
 Immediate binding: yes
 Stack clash protection: unknown, no -fstack-clash-protection instructions found
 Control flow integrity: unknown, no -fcf-protection instructions found!
1 Like

Any compile time options that can be improved nowadays? Could you enable please stack canary, stack clash protection and CFI?

1 Like

AFAIK stack canaries and stack clash protection are only useful when the program is doing some memory management stuff which this one doesn’t.

This program also doesn’t use function pointers so CFI won’t help.

1 Like

Btw we can do a lot more with seccomp than just bluntly blacklisting syscalls. For example, I just added a way to blacklist unused socket families Blacklist unused socket families · madaidan/sandbox-app-launcher@7bfdf96 · GitHub

It does this by only allowing specific uses of the socket() syscall rather than blocking it entirely. We can use this for other things like ioctl filtering too (via the ioctl() syscall).

1 Like

Some info on ioctl filtering: https://kernsec.org/files/lss2015/vanderstoep.pdf

1 Like

SIOCGIFHWADDR could be another good ioctl to blacklist. It retrieves the MAC address which may be a privacy issue (although not for Whonix as everyone uses the same MAC). I’ve tested this and it kills ifconfig but ip a seems to still get the MAC.

I’m also going to look into implementing W^X via restricting mmap() and mprotect() calls (systemd does this with MemoryDenyWriteExecute=).

2 Likes

https://github.com/madaidan/sandbox-app-launcher/commit/cbf69006cb4679485081994d4b5478daae4bc8d6

1 Like