Securing Your Daemons Using Systemd
Total Page:16
File Type:pdf, Size:1020Kb
Securing your daemons using systemd Zbigniew Jędrzejewski-Szmek [email protected] cba FOSDEM, Brussels, 2020.2.2 1 / 43 About me systemd upstream Fedora (FESCo, systemd maint., Python SIG, Rust SIG) 2 / 43 Numbers: $ dnf repoquery --releasever=32 -l --whatprovides \ '/usr/lib/systemd/system/*' \ rg -i '^/usr/lib/systemd/system/[a-z0-9_@.\\-]+$' | \ sort -u | wc -l 1740!!! Before we begin... Why use systemd for this at all? I centralization I abstraction of hardware architecture / kernel version I unprivileged operation 3 / 43 Before we begin... Why use systemd for this at all? I centralization I abstraction of hardware architecture / kernel version I unprivileged operation Numbers: $ dnf repoquery --releasever=32 -l --whatprovides \ '/usr/lib/systemd/system/*' \ rg -i '^/usr/lib/systemd/system/[a-z0-9_@.\\-]+$' | \ sort -u | wc -l 1740!!! 4 / 43 # /etc/systemd/system/mydaemon.service [Service] ExecStart=/usr/local/bin/mydaemon $ sudo systemctl start mydaemon.service $ sudo /usr/local/bin/mydameon $ sudo systemd-run /usr/local/bin/mydameon $ sudo systemd-run -t /usr/local/bin/mydameon Before we begin... Unit files 5 / 43 $ sudo /usr/local/bin/mydameon $ sudo systemd-run /usr/local/bin/mydameon $ sudo systemd-run -t /usr/local/bin/mydameon Before we begin... Unit files # /etc/systemd/system/mydaemon.service [Service] ExecStart=/usr/local/bin/mydaemon $ sudo systemctl start mydaemon.service 6 / 43 $ sudo systemd-run /usr/local/bin/mydameon $ sudo systemd-run -t /usr/local/bin/mydameon Before we begin... Unit files # /etc/systemd/system/mydaemon.service [Service] ExecStart=/usr/local/bin/mydaemon $ sudo systemctl start mydaemon.service $ sudo /usr/local/bin/mydameon 7 / 43 Before we begin... Unit files # /etc/systemd/system/mydaemon.service [Service] ExecStart=/usr/local/bin/mydaemon $ sudo systemctl start mydaemon.service $ sudo /usr/local/bin/mydameon $ sudo systemd-run /usr/local/bin/mydameon $ sudo systemd-run -t /usr/local/bin/mydameon 8 / 43 User= $ systemd-run whoami root $ systemd-run --uid=zbyszek whoami zbyszek $ systemd-run -p User=zbyszek whoami zbyszek Basics 9 / 43 $ systemd-run whoami root $ systemd-run --uid=zbyszek whoami zbyszek $ systemd-run -p User=zbyszek whoami zbyszek Basics User= 10 / 43 Basics User= $ systemd-run whoami root $ systemd-run --uid=zbyszek whoami zbyszek $ systemd-run -p User=zbyszek whoami zbyszek 11 / 43 I InaccessiblePaths= I ReadOnlyPaths= I ReadWritePaths= I BindPaths= I ReadOnlyBindPaths= Limiting access to the file system I ProtectHome=yes|read-only I ProtectSystem=yes|full|strict 12 / 43 I BindPaths= I ReadOnlyBindPaths= Limiting access to the file system I ProtectHome=yes|read-only I ProtectSystem=yes|full|strict I InaccessiblePaths= I ReadOnlyPaths= I ReadWritePaths= 13 / 43 Limiting access to the file system I ProtectHome=yes|read-only I ProtectSystem=yes|full|strict I InaccessiblePaths= I ReadOnlyPaths= I ReadWritePaths= I BindPaths= I ReadOnlyBindPaths= 14 / 43 Limiting access to the file system I PrivateTmp=yes 15 / 43 /run/foo/ I RuntimeDirectory=foo I StateDirectory=foo /var/lib/foo/ I CacheDirectory=foo /var/cache/foo/ I LogsDirectory=foo /var/log/foo/ I ConfigurationDirectory=foo /etc/foo/ Limiting access to the file system a better way 16 / 43 Limiting access to the file system a better way /run/foo/ I RuntimeDirectory=foo I StateDirectory=foo /var/lib/foo/ I CacheDirectory=foo /var/cache/foo/ I LogsDirectory=foo /var/log/foo/ I ConfigurationDirectory=foo /etc/foo/ 17 / 43 $ sudo systemd-run -t -p User=zbyszek \ -p RuntimeDirectory=foo \ ls -ld /run/foo I automatic creation and ownership I automatic removal 18 / 43 I DynamicUser=yes $ systemd-run -p DynamicUser=1 -t whoami run-u215640 $ echo -e 'asdf\nasdf' | \ systemd-run --pipe -p DynamicUser=1 \ bash -c 'grep .; whoami' | \ systemd-run --pipe -p DynamicUser=1 \ bash -c 'grep .; whoami' | \ systemd-run --pipe -p DynamicUser=1 \ bash -c 'grep .; whoami' User creation on demand? 19 / 43 $ systemd-run -p DynamicUser=1 -t whoami run-u215640 $ echo -e 'asdf\nasdf' | \ systemd-run --pipe -p DynamicUser=1 \ bash -c 'grep .; whoami' | \ systemd-run --pipe -p DynamicUser=1 \ bash -c 'grep .; whoami' | \ systemd-run --pipe -p DynamicUser=1 \ bash -c 'grep .; whoami' User creation on demand? I DynamicUser=yes 20 / 43 run-u215640 $ echo -e 'asdf\nasdf' | \ systemd-run --pipe -p DynamicUser=1 \ bash -c 'grep .; whoami' | \ systemd-run --pipe -p DynamicUser=1 \ bash -c 'grep .; whoami' | \ systemd-run --pipe -p DynamicUser=1 \ bash -c 'grep .; whoami' User creation on demand? I DynamicUser=yes $ systemd-run -p DynamicUser=1 -t whoami 21 / 43 $ echo -e 'asdf\nasdf' | \ systemd-run --pipe -p DynamicUser=1 \ bash -c 'grep .; whoami' | \ systemd-run --pipe -p DynamicUser=1 \ bash -c 'grep .; whoami' | \ systemd-run --pipe -p DynamicUser=1 \ bash -c 'grep .; whoami' User creation on demand? I DynamicUser=yes $ systemd-run -p DynamicUser=1 -t whoami run-u215640 22 / 43 systemd-run --pipe -p DynamicUser=1 \ bash -c 'grep .; whoami' | \ systemd-run --pipe -p DynamicUser=1 \ bash -c 'grep .; whoami' | \ systemd-run --pipe -p DynamicUser=1 \ bash -c 'grep .; whoami' User creation on demand? I DynamicUser=yes $ systemd-run -p DynamicUser=1 -t whoami run-u215640 $ echo -e 'asdf\nasdf' | \ 23 / 43 systemd-run --pipe -p DynamicUser=1 \ bash -c 'grep .; whoami' | \ systemd-run --pipe -p DynamicUser=1 \ bash -c 'grep .; whoami' User creation on demand? I DynamicUser=yes $ systemd-run -p DynamicUser=1 -t whoami run-u215640 $ echo -e 'asdf\nasdf' | \ systemd-run --pipe -p DynamicUser=1 \ bash -c 'grep .; whoami' | \ 24 / 43 systemd-run --pipe -p DynamicUser=1 \ bash -c 'grep .; whoami' User creation on demand? I DynamicUser=yes $ systemd-run -p DynamicUser=1 -t whoami run-u215640 $ echo -e 'asdf\nasdf' | \ systemd-run --pipe -p DynamicUser=1 \ bash -c 'grep .; whoami' | \ systemd-run --pipe -p DynamicUser=1 \ bash -c 'grep .; whoami' | \ 25 / 43 User creation on demand? I DynamicUser=yes $ systemd-run -p DynamicUser=1 -t whoami run-u215640 $ echo -e 'asdf\nasdf' | \ systemd-run --pipe -p DynamicUser=1 \ bash -c 'grep .; whoami' | \ systemd-run --pipe -p DynamicUser=1 \ bash -c 'grep .; whoami' | \ systemd-run --pipe -p DynamicUser=1 \ bash -c 'grep .; whoami' 26 / 43 I PrivateNetwork=yes “PrivateNetwork=yes is the recommeded way to run network services” What about the network? 27 / 43 “PrivateNetwork=yes is the recommeded way to run network services” What about the network? I PrivateNetwork=yes 28 / 43 What about the network? I PrivateNetwork=yes “PrivateNetwork=yes is the recommeded way to run network services” 29 / 43 Two types of socket activation: Accept=yes Accept=no → a single instance of the → a single instance of the service is started for each service is started for each connection connection → “wait” under inetd/xinetd → “nowait” under inetd/xinetd Socket Activation A daemon does not open a socket itself, it receives a socket from the manager 30 / 43 Socket Activation A daemon does not open a socket itself, it receives a socket from the manager Two types of socket activation: Accept=yes Accept=no → a single instance of the → a single instance of the service is started for each service is started for each connection connection → “wait” under inetd/xinetd → “nowait” under inetd/xinetd 31 / 43 Per-service network firewall I IPAddressAllow=10.20.30.0/24 1.2.3.4 I IPAddressDeny=* I IP{Ingress,Egress}FilterPath= BPF! 32 / 43 Low-level stuff 33 / 43 I MemoryDenyWriteExecute=yes I PrivateDevices=yes I NoNewPrivileges=yes I RestrictSUIDSGID=yes I ProtectKernelTunables=yes I ProtectClock=yes I ProtectHostname=yes I ProtectKernelLogs=yes I LockPersonality=yes 34 / 43 Capability limits I CapabilityBoundingSet= I Capability= I DropCapability= I AmbientCapabilities= 35 / 43 I SyscallFilter=... implemented using libseccomp I syscall1 | syscall2 | @group I @basic-io I @̃obsolete I SystemCallArchitectures=native|x86_64|i386|... I RestrictAddressFamilies=AF_UNIX|AF_INET|AF_INET6 |AF_CAN|AF_APPLETALK|... $ systemd-analyze syscall-filter @obsolete System call filtering “seccomp mode 2” 36 / 43 I SystemCallArchitectures=native|x86_64|i386|... I RestrictAddressFamilies=AF_UNIX|AF_INET|AF_INET6 |AF_CAN|AF_APPLETALK|... $ systemd-analyze syscall-filter @obsolete System call filtering “seccomp mode 2” I SyscallFilter=... implemented using libseccomp I syscall1 | syscall2 | @group I @basic-io I @̃obsolete 37 / 43 $ systemd-analyze syscall-filter @obsolete System call filtering “seccomp mode 2” I SyscallFilter=... implemented using libseccomp I syscall1 | syscall2 | @group I @basic-io I @̃obsolete I SystemCallArchitectures=native|x86_64|i386|... I RestrictAddressFamilies=AF_UNIX|AF_INET|AF_INET6 |AF_CAN|AF_APPLETALK|... 38 / 43 System call filtering “seccomp mode 2” I SyscallFilter=... implemented using libseccomp I syscall1 | syscall2 | @group I @basic-io I @̃obsolete I SystemCallArchitectures=native|x86_64|i386|... I RestrictAddressFamilies=AF_UNIX|AF_INET|AF_INET6 |AF_CAN|AF_APPLETALK|... $ systemd-analyze syscall-filter @obsolete 39 / 43 systemd-analyze security $ systemd-analyze security systemd-resolved.service 40 / 43 Fedora 32: systemd-analyze security * 41 / 43 Stacking the application systemd sandboxing selinux | apparmor | ... kernel 42 / 43 The End https://github.com/systemd/systemd docs: https://systemd.io/ https://www.freedesktop.org/wiki/Software/systemd/ this: https://github.com/keszybz/systemd-security-talk/ blob/master/systemd-security.pdf 43 / 43.