nix-community / srvos

NixOS profiles for servers [maintainer=@numtide]
https://nix-community.github.io/srvos
MIT License
528 stars 28 forks source link

GitHub Actions hardening #50

Open zimbatm opened 1 year ago

zimbatm commented 1 year ago

Is your feature request related to a problem? Please describe.

Right now, the runners are accepting multiple jobs, and that can leave some files around. Runners can run arbitrary code and are open to the world to be executed.

Describe the solution you'd like

I don't know if that's already the case but the design would be:

Describe alternatives you've considered

Additional context

What do you think @jfroche ?

zimbatm commented 1 year ago

See also https://github.com/Mic92/dotfiles/blob/05daca459d96557eeeb72196258e6bffc73c1360/nixos/eve/modules/drone/exec-runner.nix for further hardening.

zimbatm commented 1 year ago

See also https://www.ctrl.blog/entry/systemd-application-firewall.html

Mic92 commented 1 year ago

Helsinki systems also had some useful apparmor presets that can be added on top.

jfroche commented 1 year ago

Is your feature request related to a problem? Please describe.

Right now, the runners are accepting multiple jobs, and that can leave some files around. Runners can run arbitrary code and are open to the world to be executed.

Describe the solution you'd like

I don't know if that's already the case but the design would be:

  • Use a DynamicUser
  • Use a PreStart that wipes the WorkingDirectory
  • Configure the runner so that it only runs a single job and then exists
  • Configure the unit, so it gets restarted on exit.

I think we have all that:

We are also running ephemeral by default in the role.

jfroche commented 1 year ago

See also https://github.com/Mic92/dotfiles/blob/05daca459d96557eeeb72196258e6bffc73c1360/nixos/eve/modules/drone/exec-runner.nix for further hardening.

The service is running with ProtectSystem = "strict"; so everything should be read only. But I guess we better follow the principle of least privilege and chroot + mount only the required paths. I didn't know about that confinement option, will look into it.

The service has been optimized for the current systemd-analyze security: systemd-analyze security github-runner-numtide-github-runner-1.service NAME DESCRIPTION EXPOSURE ✗ SystemCallFilter=~@swap System call deny list defined for service, and @swap is not included (e.g. swapoff is allowed) 0.2 ✗ SystemCallFilter=~@resources System call deny list defined for service, and @resources is not included (e.g. ioprio_set is allowed) 0.2 ✓ SystemCallFilter=~@reboot System call deny list defined for service, and @reboot is included ✓ SystemCallFilter=~@raw-io System call deny list defined for service, and @raw-io is included ✗ SystemCallFilter=~@privileged System call deny list defined for service, and @privileged is not included (e.g. chown is allowed) 0.2 ✓ SystemCallFilter=~@obsolete System call deny list defined for service, and @obsolete is included ✓ SystemCallFilter=~@mount System call deny list defined for service, and @mount is included ✓ SystemCallFilter=~@module System call deny list defined for service, and @module is included ✗ SystemCallFilter=~@debug System call deny list defined for service, and @debug is not included (e.g. lookup_dcookie is allowed) 0.2 ✓ SystemCallFilter=~@cpu-emulation System call deny list defined for service, and @cpu-emulation is included ✓ SystemCallFilter=~@clock System call deny list defined for service, and @clock is included ✓ 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 transient non-root user identity ✓ RestrictRealtime= Service realtime scheduling access is restricted ✓ CapabilityBoundingSet=~CAP_SYS_TIME Service processes cannot change the system clock ✓ 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 ✗ SystemCallArchitectures= Service may execute system calls with all ABIs 0.2 ✗ MemoryDenyWriteExecute= Service may create writable executable memory mappings 0.1 ✗ LockPersonality= Service may change ABI personality 0.1 ✗ RestrictAddressFamilies=~AF_NETLINK Service may allocate netlink sockets 0.1 ✗ RestrictAddressFamilies=~AF_UNIX Service may allocate local sockets 0.1 ✗ RestrictAddressFamilies=~AF_(INET|INET6) Service may allocate Internet sockets 0.3 ✓ ProtectSystem= Service has strict read-only access to the OS file hierarchy ✓ ProtectProc= Service has restricted access to process tree (/proc hidepid=) ✓ SupplementaryGroups= Service has no supplementary groups ✓ CapabilityBoundingSet=~CAP_SYS_RAWIO Service has no raw I/O access ✓ CapabilityBoundingSet=~CAP_SYS_PTRACE Service has no ptrace() debugging abilities ✓ CapabilityBoundingSet=~CAP_SYS_(NICE|RESOURCE) Service has no privileges to change resource use parameters ✓ CapabilityBoundingSet=~CAP_NET_ADMIN Service has no network configuration privileges ✓ CapabilityBoundingSet=~CAP_NET_(BIND_SERVICE|BROADCAST|RAW) Service has no elevated networking privileges ✗ DeviceAllow= Service has no device ACL 0.2 ✓ CapabilityBoundingSet=~CAP_AUDIT_* Service has no audit subsystem access ✓ CapabilityBoundingSet=~CAP_SYS_ADMIN Service has no administrator privileges ✓ PrivateTmp= Service has no access to other software's temporary files ✓ CapabilityBoundingSet=~CAP_SYSLOG Service has no access to kernel logging ✓ ProtectHome= Service has no access to home directories ✗ ProcSubset= Service has full access to non-process /proc files (/proc subset=) 0.1 ✗ PrivateNetwork= Service has access to the host's network 0.5 ✓ KeyringMode= Service doesn't share key material with other services ✓ Delegate= Service does not maintain its own delegated control group subtree ✓ PrivateUsers= Service does not have access to other users ✗ IPAddressDeny= Service does not define an IP address allow list 0.2 ✓ NotifyAccess= Service child processes cannot alter service state ✓ ProtectClock= Service cannot write to the hardware clock or system clock ✓ CapabilityBoundingSet=~CAP_SYS_PACCT Service cannot use acct() ✓ CapabilityBoundingSet=~CAP_KILL Service cannot send UNIX signals to arbitrary processes ✓ ProtectKernelLogs= Service cannot read from or write to the kernel log ring buffer ✓ CapabilityBoundingSet=~CAP_WAKE_ALARM Service cannot program timers that wake up the system ✓ CapabilityBoundingSet=~CAP_(DAC_*|FOWNER|IPC_OWNER) Service cannot override UNIX file/IPC permission checks ✓ ProtectControlGroups= Service cannot modify the control group file system ✓ CapabilityBoundingSet=~CAP_LINUX_IMMUTABLE Service cannot mark files immutable ✓ CapabilityBoundingSet=~CAP_IPC_LOCK Service cannot lock memory into RAM ✓ ProtectKernelModules= Service cannot load or read kernel modules ✓ CapabilityBoundingSet=~CAP_SYS_MODULE Service cannot load kernel modules ✓ CapabilityBoundingSet=~CAP_SYS_TTY_CONFIG Service cannot issue vhangup() ✓ CapabilityBoundingSet=~CAP_SYS_BOOT Service cannot issue reboot() ✓ CapabilityBoundingSet=~CAP_SYS_CHROOT Service cannot issue chroot() ✓ PrivateMounts= Service cannot install system mounts ✓ CapabilityBoundingSet=~CAP_BLOCK_SUSPEND Service cannot establish wake locks ✓ RestrictNamespaces=~user Service cannot create user namespaces ✓ RestrictNamespaces=~pid Service cannot create process namespaces ✓ RestrictNamespaces=~net Service cannot create network namespaces ✓ RestrictNamespaces=~uts Service cannot create hostname namespaces ✓ RestrictNamespaces=~mnt Service cannot create file system namespaces ✓ CapabilityBoundingSet=~CAP_LEASE Service cannot create file leases ✓ CapabilityBoundingSet=~CAP_MKNOD Service cannot create device nodes ✓ RestrictNamespaces=~cgroup Service cannot create cgroup namespaces ✓ RestrictNamespaces=~ipc Service cannot create IPC namespaces ✓ ProtectHostname= Service cannot change system host/domainname ✓ CapabilityBoundingSet=~CAP_(CHOWN|FSETID|SETFCAP) Service cannot change file ownership/access mode/capabilities ✓ CapabilityBoundingSet=~CAP_SET(UID|GID|PCAP) Service cannot change UID/GID identities/capabilities ✓ ProtectKernelTunables= Service cannot alter kernel tunables (/proc/sys, …) ✓ RestrictAddressFamilies=~AF_PACKET Service cannot allocate packet sockets ✓ RestrictAddressFamilies=~… Service cannot allocate exotic sockets ✓ CapabilityBoundingSet=~CAP_MAC_* Service cannot adjust SMACK MAC ✓ RestrictSUIDSGID= SUID/SGID file creation by service is restricted ✓ UMask= Files created by service are accessible only by service's own user by default → Overall exposure level for github-runner-numtide-github-runner-1.service: 2.2 OK 🙂
jfroche commented 1 year ago

See also https://www.ctrl.blog/entry/systemd-application-firewall.html

Right we should have options to filter out internal/local networks

jfroche commented 1 year ago

Helsinki systems also had some useful apparmor presets that can be added on top.

They archived their bbb4nix repository. @Mic92 do you have more precise link in mind ?

Mic92 commented 1 year ago

Helsinki systems also had some useful apparmor presets that can be added on top.

They archived their bbb4nix repository. @Mic92 do you have more precise link in mind ?

Better ask them directly. I think they had several profile levels with increase restrictions in their internal configuration.