Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Harden nsncd.service #156

Open
KenMacD opened this issue Feb 15, 2025 · 3 comments
Open

Harden nsncd.service #156

KenMacD opened this issue Feb 15, 2025 · 3 comments

Comments

@KenMacD
Copy link

KenMacD commented Feb 15, 2025

Where the authors are probably most familiar with what access is required, it would be nice if the nsncd.service file was updated with a good and secure default hardening setup.

When the service is running on NixOS there is some hardening applied, but the service still gets a rating of 8.2 EXPOSED 🙁 in systemd-analyze security nscd.service. The existing hardening is available here (here's another users config), and is obviously not very strict.

There is an issue in the Nix repo focused on hardening system services. While hopefully someone will pick up nsncd it would probably be better if the info was available here.

@KenMacD
Copy link
Author

KenMacD commented Feb 15, 2025

systemd-analyze output:

  NAME                                                        DESCRIPTION                                                             EXPOSURE
✓ RemoveIPC=                                                  Service user cannot leave SysV IPC objects around                       
✗ RootDirectory=/RootImage=                                   Service runs within the host's root directory                                0.1
✓ User=/DynamicUser=                                          Service runs under a static non-root user identity                      
✗ CapabilityBoundingSet=~CAP_SYS_TIME                         Service processes may change the system clock                                0.2
✓ NoNewPrivileges=                                            Service processes cannot acquire new privileges                         
✓ AmbientCapabilities=                                        Service process does not receive ambient capabilities                   
✗ PrivateDevices=                                             Service potentially has access to hardware devices                           0.2
✗ ProtectClock=                                               Service may write to the hardware clock or system clock                      0.2
✗ CapabilityBoundingSet=~CAP_SYS_PACCT                        Service may use acct()                                                       0.1
✗ CapabilityBoundingSet=~CAP_KILL                             Service may send UNIX signals to arbitrary processes                         0.1
✗ ProtectKernelLogs=                                          Service may read from or write to the kernel log ring buffer                 0.2
✗ CapabilityBoundingSet=~CAP_WAKE_ALARM                       Service may program timers that wake up the system                           0.1
✗ CapabilityBoundingSet=~CAP_(DAC_*|FOWNER|IPC_OWNER)         Service may override UNIX file/IPC permission checks                         0.2
✗ ProtectControlGroups=                                       Service may modify the control group file system                             0.2
✗ CapabilityBoundingSet=~CAP_LINUX_IMMUTABLE                  Service may mark files immutable                                             0.1
✗ CapabilityBoundingSet=~CAP_IPC_LOCK                         Service may lock memory into RAM                                             0.1
✗ ProtectKernelModules=                                       Service may load or read kernel modules                                      0.2
✗ CapabilityBoundingSet=~CAP_SYS_MODULE                       Service may load kernel modules                                              0.2
✗ CapabilityBoundingSet=~CAP_BPF                              Service may load BPF programs                                                0.1
✗ CapabilityBoundingSet=~CAP_SYS_TTY_CONFIG                   Service may issue vhangup()                                                  0.1
✗ CapabilityBoundingSet=~CAP_SYS_BOOT                         Service may issue reboot()                                                   0.1
✗ CapabilityBoundingSet=~CAP_SYS_CHROOT                       Service may issue chroot()                                                   0.1
✗ SystemCallArchitectures=                                    Service may execute system calls with all ABIs                               0.2
✗ CapabilityBoundingSet=~CAP_BLOCK_SUSPEND                    Service may establish wake locks                                             0.1
✗ MemoryDenyWriteExecute=                                     Service may create writable executable memory mappings                       0.1
✗ RestrictNamespaces=~user                                    Service may create user namespaces                                           0.3
✗ RestrictNamespaces=~pid                                     Service may create process namespaces                                        0.1
✗ RestrictNamespaces=~net                                     Service may create network namespaces                                        0.1
✗ RestrictNamespaces=~uts                                     Service may create hostname namespaces                                       0.1
✗ RestrictNamespaces=~mnt                                     Service may create file system namespaces                                    0.1
✗ CapabilityBoundingSet=~CAP_LEASE                            Service may create file leases                                               0.1
✗ CapabilityBoundingSet=~CAP_MKNOD                            Service may create device nodes                                              0.1
✗ RestrictNamespaces=~cgroup                                  Service may create cgroup namespaces                                         0.1
✗ RestrictNamespaces=~ipc                                     Service may create IPC namespaces                                            0.1
✗ ProtectHostname=                                            Service may change system host/domainname                                    0.1
✗ CapabilityBoundingSet=~CAP_(CHOWN|FSETID|SETFCAP)           Service may change file ownership/access mode/capabilities unrestricted      0.2
✗ CapabilityBoundingSet=~CAP_SET(UID|GID|PCAP)                Service may change UID/GID identities/capabilities                           0.3
✗ LockPersonality=                                            Service may change ABI personality                                           0.1
✗ ProtectKernelTunables=                                      Service may alter kernel tunables                                            0.2
✗ RestrictAddressFamilies=~AF_PACKET                          Service may allocate packet sockets                                          0.2
✗ RestrictAddressFamilies=~AF_NETLINK                         Service may allocate netlink sockets                                         0.1
✗ RestrictAddressFamilies=~AF_UNIX                            Service may allocate local sockets                                           0.1
✗ RestrictAddressFamilies=~…                                  Service may allocate exotic sockets                                          0.3
✗ RestrictAddressFamilies=~AF_(INET|INET6)                    Service may allocate Internet sockets                                        0.3
✗ CapabilityBoundingSet=~CAP_MAC_*                            Service may adjust SMACK MAC                                                 0.1
✗ RestrictRealtime=                                           Service may acquire realtime scheduling                                      0.1
✓ ProtectSystem=                                              Service has strict read-only access to the OS file hierarchy            
✗ ProtectHome=                                                Service has read-only access to home directories                             0.1
✗ CapabilityBoundingSet=~CAP_SYS_RAWIO                        Service has raw I/O access                                                   0.2
✗ CapabilityBoundingSet=~CAP_SYS_PTRACE                       Service has ptrace() debugging abilities                                     0.3
✗ CapabilityBoundingSet=~CAP_SYS_(NICE|RESOURCE)              Service has privileges to change resource use parameters                     0.1
✓ SupplementaryGroups=                                        Service has no supplementary groups                                     
✗ DeviceAllow=                                                Service has no device ACL                                                    0.2
✓ PrivateTmp=                                                 Service has no access to other software's temporary files               
✗ CapabilityBoundingSet=~CAP_NET_ADMIN                        Service has network configuration privileges                                 0.2
✗ ProtectProc=                                                Service has full access to process tree (/proc hidepid=)                     0.2
✗ ProcSubset=                                                 Service has full access to non-process /proc files (/proc subset=)           0.1
✗ CapabilityBoundingSet=~CAP_NET_(BIND_SERVICE|BROADCAST|RAW) Service has elevated networking privileges                                   0.1
✗ CapabilityBoundingSet=~CAP_AUDIT_*                          Service has audit subsystem access                                           0.1
✗ CapabilityBoundingSet=~CAP_SYS_ADMIN                        Service has administrator privileges                                         0.3
✗ PrivateNetwork=                                             Service has access to the host's network                                     0.5
✗ PrivateUsers=                                               Service has access to other users                                            0.2
✗ CapabilityBoundingSet=~CAP_SYSLOG                           Service has access to kernel logging                                         0.1
✓ KeyringMode=                                                Service doesn't share key material with other services                  
✓ Delegate=                                                   Service does not maintain its own delegated control group subtree       
✗ SystemCallFilter=~@clock                                    Service does not filter system calls                                         0.2
✗ SystemCallFilter=~@cpu-emulation                            Service does not filter system calls                                         0.1
✗ SystemCallFilter=~@debug                                    Service does not filter system calls                                         0.2
✗ SystemCallFilter=~@module                                   Service does not filter system calls                                         0.2
✗ SystemCallFilter=~@mount                                    Service does not filter system calls                                         0.2
✗ SystemCallFilter=~@obsolete                                 Service does not filter system calls                                         0.1
✗ SystemCallFilter=~@privileged                               Service does not filter system calls                                         0.2
✗ SystemCallFilter=~@raw-io                                   Service does not filter system calls                                         0.2
✗ SystemCallFilter=~@reboot                                   Service does not filter system calls                                         0.2
✗ SystemCallFilter=~@resources                                Service does not filter system calls                                         0.2
✗ SystemCallFilter=~@swap                                     Service does not filter system calls                                         0.2
✗ IPAddressDeny=                                              Service does not define an IP address allow list                             0.2
✓ NotifyAccess=                                               Service child processes cannot alter service state                      
✓ PrivateMounts=                                              Service cannot install system mounts                                    
✓ RestrictSUIDSGID=                                           SUID/SGID file creation by service is restricted                        
✗ UMask=                                                      Files created by service are world-readable by default                       0.1

→ Overall exposure level for nscd.service: 8.2 EXPOSED 🙁

@leifwalsh
Copy link
Collaborator

I'd be happy to review a change and read enough docs to understand it, but I don't actually feel familiar enough with systemd to attempt the change on my own, or at least, I could try but I have a feeling you'd do a better job if you know enough to file this. Any chance you'd like to send a PR?

@geofft
Copy link
Collaborator

geofft commented Feb 15, 2025

A lot of these seem like they ought to be irrelevant, or trivial to enable, for a service that runs as non-root + no ambient caps + NoNewPrivs. For instance, we have no ability to ever gain any of the caps in the bounding set, so the bounding set may as well be empty. We therefore have no ability to read/write kernel logs since we cannot ever gain the caps needed to use /dev/kmsg or /proc/kmsg, so whether we can see those files is irrelevant. (Without NoNewPrivs there would be an argument that an exploited service can pivot to invoking or attacking a setuid program like sudo, but setuid doesn't work under NoNewPrivs.) Has NixOS discussed automatically turning most of these on if a service runs as a non-root user with no ambient caps and NoNewPrivs? I think you could do this systematically.

(I also think that the practical benefit of flipping all these knobs on is basically nil; any exploit that puts an attacker in a position to write to the NoNewPrivs flag or the kernel UID field for your process's kernel data structure is also going to put an attacker in a position to regain most of these without much more difficulty. So I'm a little surprised that upstream systemd-analyze bothers to report on those things. Reducing protocols, system calls, etc. makes sense because they actually limit attack surface.)

One problem with coming up with a list of restrictions for nsncd is that it depends a lot on what the third-party NSS modules are and what they do. Generally you use nsncd because you have some interesting NSS config, whether that's an enterprise LDAP or SSSD setup, Avahi, nss_systemd, nss_docker, nss_libvirt, etc., and in turn that module will need to get its data from somewhere, usually the network. It may also have dependencies on other libraries and config on the system, other running daemons specifically for the NSS module (as in the case of SSSD, nss_ldapd, and winbind IIRC), or other running services on the system (in the case of nss_systemd, nss_docker, nss_libvirt, etc.). So while, for instance, nsncd technically doesn't do any network access on its own, we can't restrict network access.

Of the X marks above, here's my quick thoughts:

  • RootDirectory is probably unwise to change, given the need for third-party modules to access configs and data.
  • CapabilityBoundingSet can safely be empty by the argument above about caps.
  • PrivateDevices also safe because caps.
  • ProtectClock also safe because caps.
  • ProtectKernelLogs also safe because caps.
  • ProtectControlGroups also safe because caps.
  • ProtectKernelModules also safe because caps.
  • SystemCallArchitectures is almost certainly safe. (The case where it wouldn't is if an NSS module spawns a helper program, which is a little weird already, and that helper program is a different architecture from nsncd, which seems unlikely to be a useful configuration.)
  • MemoryDenyWriteExecute is likely safe but I can't say for sure what third-party NSS modules are going to need.
  • RestrictNamespaces is almost certainly safe. (The case where it wouldn't is if an NSS module forks and creates a user namespace, which would be pretty weird. Certainly none of us know of any libraries that create user namespaces....)
  • ProtectHostname also safe because caps.
  • LockPersonality is almost certainly safe. (Same argument as SystemCallArchitectures but even less likely to happen.)
  • ProtectKernelTunables also safe because caps.
  • RestrictAddressFamilies is probably unwise to change. Certainly we need AF_INET, AF_INET6, AF_UNIX, and AF_NETLINK for very common NSS modules. AF_PACKET is unlikely to be needed given that it's about raw sockets. I can't say about "exotic" families—if it's how the network is accessed on some system, it might be realistic.
  • RestrictRealtime is almost certainly safe.
  • ProtectHome I'm unsure about; in theory an NSS module shouldn't need to see if home directories actually exist, it just needs to report their paths.
  • DeviceAllow is a subset of ProtectDevices.
  • ProtectProc I'm unsure about, in that I can maybe see something that communicates with a daemon/service wanting to see those processes?
  • ProcSubset also safe because caps.
  • PrivateNetwork is definitely unsafe.
  • PrivateUsers I'm unsure about, especially for NSS modules that need to communicate with the rest of the system, but maybe it will work? It does seem a little weird for the daemon that provides user naming information to not be able to see user IDs in use, but it also doesn't seem like it's necessarily a problem.
  • SystemCallFilter=~@clock,@raw-io,@reboot,@swap should be safe because caps.
  • SystemCallFilter=~@cpu-emulation,@debug,@module,@mount,@obsolete,@privileged,@resources are almost certainly safe, in that I can't think of a reasonable NSS module that would need them, but as with some of the other ones above I can't rule it out.
  • IPAddressDeny, if I understand it correctly, is definitely unsafe.
  • UMask, if I understand it correctly, is unsafe, in that we need /var/run/nscd/socket to be accessible by other users.

If you're in a position to either let users choose between multiple hardening profiles or automatically determine what is needed and unneeded by the specific NSS libraries in use, you can probably be more aggressive with the settings.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants