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 all system services by default #213

Open
monsieuremre opened this issue Mar 17, 2024 · 10 comments
Open

Harden all system services by default #213

monsieuremre opened this issue Mar 17, 2024 · 10 comments

Comments

@monsieuremre
Copy link
Contributor

Let's make use of systemd sandboxing mechanisms to harden all services by default, whitelisting any services where necessary.

  • Big time advantage: not bothering to sandbox single services one by one, we sandbox everything as much as we can by default and exempt services where applicable. We can do this only for very obvious privileges that are only required by a very limited number of known services. It will still bring a lot of value in hardening.

  • Step 1: Create a global hardened drop in for all services

Under /etc/systemd/system/service.d create 25_security-misc.conf, with the content:

[Service]
ProtectProc=invisible
ProcSubset=pid
NoNewPrivileges=true
SecureBits=noroot-locked
ProtectClock=true
ProtectHostname=true
RestrictNamespaces=true
LockPersonality=true
PrivateTmp=yes
ProtectHome=yes
ProtectKernelLogs=yes
ProtectKernelModules=yes
ProtectKernelTunables=yes
RestrictSUIDSGID=true
MemoryDenyWriteExecute=true
RemoveIPC=true
UMask=0077
# InaccessiblePaths=/sys
NoExecPaths=/
ExecPaths=/usr/sbin/ /usr/lib /usr/lib64 /usr/bin
PrivateDevices=true
  • Step 2: Whitelist vital system components so that we don't actually die

  • For common and used time synchronization daemons, such as systemd-timesyncd, create the following drop-in:

[Service]
ProtectClock=false
  • For the systemd-login daemon, the following drop-in:
[Service]
ProcSubset=all
ProtectProc=false
  • For systemd-modules-load and quite possibly other services, we need enable sticking modules to the kernel and stuff:
[Service]
ProtectKernelModules=yes
ProtectKernelTunables=yes
  • For systemd-journald and auditd and if applicable other known logging daemons, the following drop in:
[Service]
ProtectKernelLogs=no
  • This is an extensive list. RestrictNamespaces=true probably needs exemption for apt and possibly some other privileged things.
  • LockPersonality=true might break random virtual box things, so that might be left out if necessary.
  • MemoryDenyWriteExecute=true might need exemption for desktop environments especially when using xorg, and probably some other things, for now not clear without testing.
  • RemoveIPC=true will most certainly break xorg, so DE components that rely on xorg will need drop-ins.
  • ProtectHostname needs an exception for services that need that for sure, what those are yet to be cleared.
  • PrivateDevices need exemption for services that do mounting and unmounting, only a few of them are there. Mount units need no exception, only services do.
  • Other things should not break anything given the exception drop-ins. Not tested this except for ProtectProc, which works as I intended. One exception drop-in does the job. So they might break more, and more exception drop-ins might be required. Will create a pull when I find the time to write a test version and actually test it.
@adrelanos
Copy link
Member

adrelanos commented Mar 17, 2024

Let's hope this doesn't create a lot issues infeasible to fix.

Folder needs to be /lib/systemd/system/service.d. As per:
https://www.kicksecure.com/wiki/Dev/About_Debian_Packaging#use_/usr_instead_of_/etc

Some mechanism to test this would be good:

@monsieuremre
Copy link
Contributor Author

There is no need for conditions tho. I don't understand the appeal here.

@monsieuremre
Copy link
Contributor Author

Some mechanism to test this would be good:

Long overdue for a package such as security-misc. Trivial to implement too, but what will be tested exactly?

Also this package needs some real changes, it is really overloaded and hard to read. Things that are unabled should have their own branch for example. Anyway, I will try offering a solution to this soon.

@roddhjav
Copy link

roddhjav commented Mar 17, 2024

From my experience applying this everywhere generate a lot of breakage. Witch is fine provided the fact you:

  1. Have the resource/will to commit on maintaining/testing it
  2. Have debug/audit tool that allow to check when (and why) something is needed.

A few years ago, I made a project like this (similar in spirit to apparmor.d but for systemd services), I gave up because, unlike apparmor, there is not way to audit issues (so that would probably be you first challenge if you want to commit time on this).

Side note:

As these config settings change the way a service is executed, it has consequences on other tool in the OS. These tools much then be aware of this. Some example with apparmor & systemd:

Systemd tools are usually already well configured on this matter, if a setting is not enabled, there is a reason why.

Big time advantage: not bothering to sandbox single services one by one, we sandbox everything as much as we can by default and exempt services where applicable.

If it is the correct way to implement it (allow-list instead of deny-list), it is quite complex and time consuming: you need to test every possible service and check if they need less settings. In other words, you still need to sandbox single services...

@monsieuremre
Copy link
Contributor Author

That's why I chose the most limited options to apply globally. Anything that would break because of these settings are rare and known. You are right, it is a little far reaching with IPC and Memory restrictions, but not everything in the list is necessarily to be applied. If things break, we can leave it out. For kernel and proc stuff for example, everything that an break is already known to us. Similar for other things.

But even if we wanted to harden some select service on their own, it isn't as difficult as you suggest, since there are actually tools. I for one, used this thing in recently. You just run the service normally for a while, and voila you have your sandboxing config auto generated for you. Was easier than my experience with apparmor to be honest. But as I said, hardening of single services is not in the scope.

@roddhjav
Copy link

roddhjav commented Mar 17, 2024

Interesting, I wish I had this tool a few years ago. apparmor.d is more complex because:

  1. It is up to you to define the size of the profile (ie: the sandbox)
  2. There are much more interaction between profiles (dbus, gnome..) that's where MAC shine over sandboxing.

It end up being much more than a list of restriction more a security construction of you OS.

@adrelanos
Copy link
Member

Would apparmor.d accomplish the same (and more) than this ticket?

@monsieuremre
Copy link
Contributor Author

Would apparmor.d accomplish the same (and more) than this ticket?

Well yeah, but actually no. For some parts, yes. Technically sandboxing and Mandatory Access Control are different concepts. Apparmor.d is more for access, privilege and capability mediation. Systemd sandboxing is more for creating a fake sandbox envrionment for that service. At the end, we kind of achieve the same thing, sort of. When a service is sandboxed and protect proc is true, then it actually sees a proc and can access is, its just it sees it empty. Or like when we enable private devices, the service can access all the devices it sees and it thinks the system has, but those are just not the real devices, they are just what we want them to be, which is nothing. An apparmor profile on the other hand just denies the service access to those things. Different? Yeah... But sort of achieves a similar goal at the end.

On a side note apparmor.d accomplishes a lot more than just hardening systemd services obviously. Pujol's apparmor.d is on its own single handedly the one single thing you can do on a linux desktop to harden it, it is miles ahead and achieves much more than anything else in terms of security hardening, especially with the full system policy enabled. It is one single biggest step by far kicksecure can take towards hardening a system, hands down.

@monsieuremre
Copy link
Contributor Author

@adrelanos a very similar approach is about make its way to fedora. And by similar I mean literally the same.

https://fedoraproject.org/wiki/Changes/SystemdSecurityHardening

We can also just import the config files directly from fedora. Only a few debian specific services will need extra files, which can easily be prepared.

@adrelanos
Copy link
Member

Please send systemd unit files improvements (systemd hardening) patches upstream to individual Debian packages so this doesn't need to be (all) carried downstream by Kicksecure. As per:
https://www.kicksecure.com/wiki/Dev/Relationship_With_Upstream#Upstream_software

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