Hardening systemd and apparmor profile
Hello,
I use usbguard on Ubuntu 16.04 LTS with KDE5 (systemd 229) and have set the following settings for a while without trouble.
On the systemd service file
[Service]
ProtectSystem=full
ProtectHome=true
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true
PrivateTmp=true
NoNewPrivileges=true
CapabilityBoundingSet=CAP_CHOWN CAP_FOWNER
MemoryDenyWriteExecute=true
RestrictNamespaces=yes
And an apparmor profile
#include <tunables/global>
/usr/bin/usbguard-daemon {
#include <abstractions/base>
#include <abstractions/nameservice>
capability chown,
capability fowner,
/dev/shm/qb-usbguard-{request,response,event}-[0-9]*-[0-9]*-[0-9]*-{header,data} rw,
/etc/usbguard/** r,
/etc/usbguard/usbguard-daemon.conf w,
/usbguard/rules.conf w,
/usr/sbin/usbguard-daemon ixr,
/sys/bus/usb/devices/ r,
/sys/bus/usb/devices/** r,
/sys/devices/pci*/*/uevent r,
/sys/devices/pci*/*/usb[0-9]*/**/authorized_default rw,
/sys/devices/pci*/*/usb[0-9]*/authorized_default rw,
/sys/devices/pci*/*/usb[0-9]*/**/authorized rw,
/sys/devices/pci*/*/usb[0-9]*/authorized rw,
/sys/devices/pci*/*/usb[0-9]*/**/descriptors r,
/sys/devices/pci*/*/usb[0-9]*/descriptors r,
/sys/devices/pci*/*/usb[0-9]*/**/idProduct r,
/sys/devices/pci*/*/usb[0-9]*/idProduct r,
/sys/devices/pci*/*/usb[0-9]*/**/idVendor r,
/sys/devices/pci*/*/usb[0-9]*/idVendor r,
/sys/devices/pci*/*/usb[0-9]*/**/product r,
/sys/devices/pci*/*/usb[0-9]*/product r,
/sys/devices/pci*/*/usb[0-9]*/remove rw,
/sys/devices/pci*/*/usb[0-9]*/**/serial r,
/sys/devices/pci*/*/usb[0-9]*/serial r,
/sys/devices/pci*/*/usb[0-9]*/**/uevent rw,
/sys/devices/pci*/*/usb[0-9]*/uevent rw,
/tmp/log/usbguard-audit.log rw,
}
/usr/bin/usbguard {
#include <abstractions/base>
/dev/shm/qb-usbguard-{request,response,event}-[0-9]*-[0-9]*-[0-9]*-{header,data} rw,
/usr/bin/usbguard ixr,
}
/usr/bin/usbguard-applet-qt {
#include <abstractions/base>
#include <abstractions/fonts>
#include <abstractions/freedesktop.org>
#include <abstractions/gnome>
#include <abstractions/kde>
#include <abstractions/nameservice>
#include <abstractions/X>
#include <abstractions/private-files>
#include <abstractions/private-files-strict>
/dev/shm/qb-usbguard-{request,response,event}-[0-9]*-[0-9]*-[0-9]*-{header,data} rw,
/etc/xdg/Trolltech.conf k,
/etc/xdg/sni-qt.conf rk,
owner @{HOME}/.config/USBGuard/ rw,
owner @{HOME}/.config/USBGuard/** rwk,
owner @{HOME}/.kde/share/config/kdeglobals k,
/usr/bin/usbguard-applet-qt ixr,
/usr/share/icons/*/index.theme k,
owner /{,var/}run/user/[0-9]*/sni-qt_usbguard-applet-qt_[0-9]*-[a-zA-Z0-9]*/ rw,
owner /{,var/}run/user/[0-9]*/sni-qt_usbguard-applet-qt_[0-9]*-[a-zA-Z0-9]*/** rw,
}
Surely there will have to be some adaptions to different desktop environments.
Hi, thanks for this contribution! Could you please explain what the systemd settings mean and provide some installation instruction for the apparmor profile (where to put it, how to detect whether to put it somewhere, ... etc).
The systemd settings apply some restrictions on the usbguard daemon. The more recent the user´s systemd is the more settings are supported. Unknown values will be ignored. usbguard-daemon is started in a sandbox/namespace with the root filesystem mounted read-only, its home folder made inaccessible and forbidden to get new capabilities than the granted. Some settings in /proc and /sys are denied, too. The daemon further gets its own private /tmp. See the systemd.exec manpage.
The lines should be added to your (service block) systemd service file (usually /lib/systemd/system) or the user can append them in their local area (usually /etc/systemd/system). If the unit file is "usbguard.service", a folder /etc/systemd/system/usbguard.service.d must be created and the lines pasted into a file called "override.conf". An internet search with "override systemd unit file" should help, if in doubt.
The apparmor profile is just a textfile copied to /etc/apparmor.d and puts an additional layer of security around the daemon. Enabling this access control system is depending on the distribution. Ubuntu enables it by default, Debian users should add "apparmor=1 security=apparmor" to their kernel command line (in /etc/default/grub). Distributions using "selinux", like Fedora/CentOS/RedHat, cannot use apparmor as both are mutually exclusive. My contributed profile requires some shared files all apparmor profiles use called "abstractions". The distributions usually have them in their repositories and must be installed. On a debian-based system this is "apt install apparmor-profiles". Again a internet search can help with specific instructions. If the profile is existing in the named directory, it will be loaded automatically on system bootup. To check the enforcing the command "aa-status" can be issued or "ps auxfZ" shows the security label on the left side of all running processes.
Some minor corrections to my profile:
3: /usr/sbin/usbguard-daemon { 20: /{,var/}run/usbguard.pid rwk, 43: /var/log/usbguard/usbguard-audit.log rw,
To test the profiles they can be switched into a "complain" mode. To do so the first line of a profile with the full path to the binary must have an option between the path and the ending bracket. Like:
/folder/to/binary flags="(complain)" {
The profile and the daemon must be reloaded to apply the settings. In case of apparmor you can use "apparmor_parser -r usr.sbin.usbguard-daemon" with the current working directory in /etc/apparmor.d. Any violations to the access control settings will be logged to the system log. Usually rsyslogd or systemd-journal. But debugging apparmor profiles is another story ;)
I'm using these apparmor profiles for usbguard. But of course some of the rules has to be customized, for instance there's no gtk abstraction upstream and some of its rules have to be added manually to the main profile. The rest works fine on debian sid, but the profiles need testing and some files probably should be denied if usbguard can work without them, time will show.
The next thing is the usbguard systemd service. In my case setting ProtectKernelTunables=true generates the following messages in the syslog:
Aug 28 18:40:09 morfikownia usbguard-daemon[58954]: device enumeration exception: /sys/bus/usb/devices/usb1: SysFSDevice: uevent: Read-only file system
Aug 28 18:40:09 morfikownia usbguard-daemon[58954]: device enumeration exception: /sys/bus/usb/devices/usb2: SysFSDevice: uevent: Read-only file system
Aug 28 18:40:09 morfikownia usbguard-daemon[58954]: device enumeration exception: /sys/bus/usb/devices/1-1: SysFSDevice: uevent: Read-only file system
Aug 28 18:40:09 morfikownia usbguard-daemon[58954]: device enumeration exception: /sys/bus/usb/devices/2-1: SysFSDevice: uevent: Read-only file system
Aug 28 18:40:09 morfikownia usbguard-daemon[58954]: device enumeration exception: /sys/bus/usb/devices/1-1.3: SysFSDevice: uevent: Read-only file system
Aug 28 18:40:09 morfikownia usbguard-daemon[58954]: device enumeration exception: /sys/bus/usb/devices/2-1.2: SysFSDevice: uevent: Read-only file system
Aug 28 18:40:09 morfikownia usbguard-daemon[58954]: device enumeration exception: /sys/bus/usb/devices/2-1.2.1: SysFSDevice: uevent: Read-only file system
Aug 28 18:40:09 morfikownia usbguard-daemon[58954]: device enumeration exception: /sys/bus/usb/devices/2-1.2.2: SysFSDevice: uevent: Read-only file system
which makes usbguard-applet-qt useless (empty listing). So the ProtectKernelTunables has to be set to false in order to make it work. The other options seem to work fine so far.
I updated to Bionic (Ubuntu 18.04) a while ago and did some changes to the settings. It is right that "ProtectKernelTunables" do not work. The systemd version in my old Ubuntu ignored this setting because it did not support it. Thus to me it had no effect, but to people have a newer systemd. I had not noticed this.
At the moment my (override) systemd unit file is looking like this:
[Service]
ProtectSystem=strict
ProtectHome=true
ProtectKernelModules=true
ProtectControlGroups=true
PrivateTmp=true
NoNewPrivileges=true
ReadWritePaths=/var/log/usbguard /run
RestrictAddressFamilies=AF_UNIX AF_NETLINK
CapabilityBoundingSet=CAP_CHOWN CAP_FOWNER
MemoryDenyWriteExecute=true
RestrictNamespaces=yes
ExecStart=
ExecStart=/usr/sbin/usbguard-daemon -C -f -s -c /etc/usbguard/usbguard-daemon.conf
The apparmor profile like this:
#include <tunables/global>
/usr/sbin/usbguard-daemon flags=(attach_disconnected) {
#include <abstractions/base>
#include <abstractions/nameservice>
#include <abstractions/consoles>
network netlink dgram,
unix (bind,connect,listen,accept,send,receive) type=stream addr="@usbguard*",
capability chown,
capability fowner,
/dev/shm/qb-usbguard-{request,response,event}-[0-9]*-[0-9]*-[0-9]*-{header,data} rw,
/etc/usbguard/** r,
/etc/usbguard/usbguard-daemon.conf w,
/usbguard/rules.conf w,
/usr/sbin/usbguard-daemon ixr,
/{,var/}run/usbguard.pid rwk,
/sys/bus/usb/devices/ r,
/sys/bus/usb/devices/** r,
/sys/devices/pci*/*/uevent r,
/sys/devices/pci*/*/usb[0-9]*/**/authorized_default rw,
/sys/devices/pci*/*/usb[0-9]*/authorized_default rw,
/sys/devices/pci*/*/usb[0-9]*/**/authorized rw,
/sys/devices/pci*/*/usb[0-9]*/authorized rw,
/sys/devices/pci*/*/usb[0-9]*/**/descriptors r,
/sys/devices/pci*/*/usb[0-9]*/descriptors r,
/sys/devices/pci*/*/usb[0-9]*/**/idProduct r,
/sys/devices/pci*/*/usb[0-9]*/idProduct r,
/sys/devices/pci*/*/usb[0-9]*/**/idVendor r,
/sys/devices/pci*/*/usb[0-9]*/idVendor r,
/sys/devices/pci*/*/usb[0-9]*/**/product r,
/sys/devices/pci*/*/usb[0-9]*/product r,
/sys/devices/pci*/*/usb[0-9]*/**/remove rw,
/sys/devices/pci*/*/usb[0-9]*/remove rw,
/sys/devices/pci*/*/usb[0-9]*/**/serial r,
/sys/devices/pci*/*/usb[0-9]*/serial r,
/sys/devices/pci*/*/usb[0-9]*/**/uevent rw,
/sys/devices/pci*/*/usb[0-9]*/uevent rw,
/var/log/usbguard/usbguard-audit* rw,
}
/usr/sbin/usbguard-dbus {
#include <abstractions/base>
#include <abstractions/dbus>
#include <abstractions/dbus-session>
#include <abstractions/dbus-accessibility-strict>
unix (connect,send,receive) type=stream addr=none,
/dev/shm/qb-usbguard-{request,response,event}-[0-9]*-[0-9]*-[0-9]*-{header,data} rw,
/usr/sbin/usbguard-dbus ixr,
}
/usr/bin/usbguard {
#include <abstractions/base>
unix (connect,send,receive) type=stream addr=none,
/dev/shm/qb-usbguard-{request,response,event}-[0-9]*-[0-9]*-[0-9]*-{header,data} rw,
/usr/bin/usbguard ixr,
}
/usr/bin/usbguard-applet-qt {
#include <abstractions/base>
#include <abstractions/fonts>
#include <abstractions/freedesktop.org>
#include <abstractions/gnome>
#include <abstractions/kde>
#include <abstractions/nameservice>
#include <abstractions/X>
#include <abstractions/private-files-strict>
#include <abstractions/dbus-session-strict>
#include <abstractions/dbus-accessibility-strict>
dbus receive
bus=session
path=/MenuBar,
dbus (send,receive)
bus=session
path=/StatusNotifierItem,
dbus send
bus=session
path=/StatusNotifierWatcher,
dbus send
bus=session
path=/org/a11y/bus,
dbus send
bus=session
path=/org/freedesktop/Notifications,
unix (connect,send,receive) type=stream addr=none,
/dev/dri/ r,
/dev/shm/qb-usbguard-{request,response,event}-[0-9]*-[0-9]*-[0-9]*-{header,data} rw,
/etc/glvnd/egl_vendor.d/ r,
/etc/glvnd/egl_vendor.d/* r,
/etc/xdg/Trolltech.conf k,
/etc/xdg/sni-qt.conf rk,
@{PROC}/sys/kernel/core_pattern r,
owner @{HOME}/.cache/icon-cache.kcache rw,
owner @{HOME}/.cache/mesa_shader*/** rw,
owner @{HOME}/.config/USBGuard/ rw,
owner @{HOME}/.config/USBGuard/** rwk,
owner @{HOME}/.config/*rc r,
owner @{HOME}/.config/kdeglobals rk,
owner @{HOME}/.kde/share/config/kdeglobals k,
/sys/devices/pci*/**/drm/ r,
/sys/devices/pci*/**/{device,subsystem_device,subsystem_vendor,uevent,vendor} r,
/usr/bin/usbguard-applet-qt ixr,
/usr/lib/x86_64-linux-gnu/qt5/plugins/** m,
/usr/share/icons/*/index.theme k,
/usr/share/glvnd/egl_vendor.d/ r,
/usr/share/glvnd/egl_vendor.d/* r,
/usr/share/libdrm/** r,
/usr/share/plasma/** r,
/usr/share/qt5/translations/* r,
owner /{,var/}run/user/[0-9]*/sni-qt_usbguard-applet-qt_[0-9]*-[a-zA-Z0-9]*/ rw,
owner /{,var/}run/user/[0-9]*/sni-qt_usbguard-applet-qt_[0-9]*-[a-zA-Z0-9]*/** rw,
}
@dkopecek some service hardning would be cool, can we have a revisit on this report?