Package: unscd Version: 0.54-1 Severity: wishlist I wrote a hardening dropin (attached) for unscd.service.
$ systemd-analyze security UNIT EXPOSURE PREDICATE HAPPY unscd.service 9.6 UNSAFE 😨 # before unscd.service 1.1 OK 🙂 # after Please consider adding some/all of it to debian/unscd.service. You may need to "dial back" the hardening a little, e.g. PADL libnss-ldap (dead since 2016, but still in Debian 11) probably needs AF_INET AF_INET6. Two further improvements require source code changes: * Removing NSCD_SOCKET_OLD from nscd.c. I *think* glibc hasn't used this path for over a decade now! Removing it will allow systemd to block write access to /run. * Make unscd only drop privileges if it starts as root (or so). This will allow systemd to drop privileges before unscd starts, and block CAP_SET[UG]ID and sete[ug]id(2). I am using unscd with its default nscd.conf. It provides a short-term cache for nss-pam-ldapd, reducing the load on the LDAP server (slapd or samba-ad) by 90% to 99%. My test case was to do this (testing passwd negative-ttl only) : # for i in {1..9999}; do touch "$i"; chown -h 1234 "$i"; done # time find -nouser -fprintf /dev/null . real 0m1.176s # unscd is stopped real 0m0.446s # unscd is running With my dropin, this test still passes, so I think unscd is both running and working. -- System Information: Debian Release: 11.0 APT prefers stable-updates APT policy: (990, 'stable-updates'), (990, 'stable-security'), (990, 'stable'), (500, 'proposed-updates'), (500, 'unstable'), (500, 'testing'), (1, 'experimental') Architecture: amd64 (x86_64) Kernel: Linux 5.10.0-8-amd64 (SMP w/8 CPU threads) Kernel taint flags: TAINT_PROPRIETARY_MODULE, TAINT_OOT_MODULE, TAINT_UNSIGNED_MODULE Locale: LANG=en_AU.UTF-8, LC_CTYPE=en_AU.UTF-8 (charmap=UTF-8), LANGUAGE not set Shell: /bin/sh linked to /usr/bin/dash Init: systemd (via /run/systemd/system) LSM: AppArmor: enabled
# This file goes in /etc/systemd/system/unscd.service.d/hardening.conf [Service] PrivateNetwork=yes ## We can't drop root privs before starting, because ## it wants to bind BOTH of these: ## ## define NSCD_SOCKET "/var/run/nscd/socket" ## define NSCD_SOCKET_OLD "/var/run/.nscd_socket" ## ## Probably the latter should just be removed from unscd.c entirely, since ## the implementations of glibc that use it are probably looooong gone. # User=unscd # DynamicUser=yes RuntimeDirectory=unscd WorkingDirectory=/run/nscd CapabilityBoundingSet= # FIXME: once we Users=unscd, tighten this up. CapabilityBoundingSet=CAP_SETUID CAP_SETGID RestrictAddressFamilies=AF_UNIX RestrictNamespaces=yes DevicePolicy=closed IPAddressDeny=any NoNewPrivileges=yes PrivateDevices=yes PrivateMounts=yes PrivateTmp=yes # FIXME: once we Users=unscd, tighten this up. # UPDATE: er, we probably need PrivateUsers=no anyway, because # nscd's job is to see & cache users. :-) #PrivateUsers=yes ProtectClock=yes ProtectControlGroups=yes ProtectHome=yes ProtectKernelLogs=yes ProtectKernelModules=yes ProtectKernelTunables=yes ProtectProc=invisible ProtectSystem=strict # FIXME: once NSCD_SOCKET_OLD is gone, remove this. ReadWritePaths=/run RestrictSUIDSGID=yes SystemCallArchitectures=native SystemCallFilter=@system-service # FIXME: once we Users=unscd, tighten this up. #SystemCallFilter=~@privileged SystemCallFilter=~@resources RestrictRealtime=yes LockPersonality=yes MemoryDenyWriteExecute=yes UMask=0077 ProtectHostname=yes ProcSubset=pid