Skip to contentSkip to conversation

add more security features for systemd units

PATCH Superseded Christian Hesse 6 participants 12 messages Dec 9, 2016 – Jan 25, 2017

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 add more security features for systemd units

From: Christian Hesse <[email protected]...>

ProtectSystem=strict mounts the entire file system hierarchy read-only, except for the API file system subtrees /dev, /proc and /sys (which can be protected using PrivateDevices=, ProtectKernelTunables=, ProtectControlGroups=).

ProtectHome=true makes the directories /home, /root and /run/user inaccessible and empty for the process.

See systemd.exec(5) [0] for details.

[0] https://www.freedesktop.org/software/systemd/man/systemd.exec.html

---
 distro/systemd/[email protected]... | 2 ++
 distro/systemd/[email protected]... | 2 ++
 2 files changed, 4 insertions(+)
distro/systemd/[email protected]... +2 -0
index 5618af3..3a9b7e2 100644
@@ -17,6 +17,8 @@ CapabilityBoundingSet=CAP_IPC_LOCK CAP_NET_ADMIN CAP_NET_RAW CAP_SETGID CAP_SETU
 LimitNPROC=10
 DeviceAllow=/dev/null rw
 DeviceAllow=/dev/net/tun rw
+ProtectSystem=strict
+ProtectHome=true
 
 [Install]
 WantedBy=multi-user.target
distro/systemd/[email protected]... +2 -0
index b9b4dba..a9e57b2 100644
@@ -17,6 +17,8 @@ CapabilityBoundingSet=CAP_IPC_LOCK CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RA
 LimitNPROC=10
 DeviceAllow=/dev/null rw
 DeviceAllow=/dev/net/tun rw
+ProtectSystem=strict
+ProtectHome=true
 
 [Install]
 WantedBy=multi-user.target
Signature · 1 line
2.10.2
#1 lore raw
Quoted 9 lines · Christian Hesse

From: Christian Hesse <[email protected]...>

ProtectSystem=strict mounts the entire file system hierarchy read-only, except for the API file system subtrees /dev, /proc and /sys (which can be protected using PrivateDevices=, ProtectKernelTunables=, ProtectControlGroups=).

ProtectHome=true makes the directories /home, /root and /run/user inaccessible and empty for the process.

Currently I don't think we can use ProtectedHome= .... as it is fully possible to save certificates and keys under $HOME/.cert on Fedora/RHEL (and clones). There is even a specific SELinux label for files in that path, home_cert_t.

For the others, I think they are more reasonable ... But I need to dig into the more murky details to be 100% they are safe for us. This is anyhow something we need to postpone until after 2.4.0 ... I don't dare adding more things which may backfire in rc2, as we're on a strict schedule to manage the next Debian release.

Once rc2 settles, I will start playing with this patch.

Signature · 4 lines
kind regards,

David Sommerseth
OpenVPN Technologies, Inc
#2 lore raw

David Sommerseth <[email protected]...> on Fri, 2016/12/09 20:42:

Quoted 8 lines · Christian Hesse
Quoted 7 lines

From: Christian Hesse <[email protected]...>

ProtectSystem=strict mounts the entire file system hierarchy read-only, except for the API file system subtrees /dev, /proc and /sys (which can be protected using PrivateDevices=, ProtectKernelTunables=, ProtectControlGroups=).

Quoted 7 lines
Quoted 2 lines

ProtectHome=true makes the directories /home, /root and /run/user inaccessible and empty for the process.

Currently I don't think we can use ProtectedHome= .... as it is fully possible to save certificates and keys under $HOME/.cert on Fedora/RHEL (and clones). There is even a specific SELinux label for files in that path, home_cert_t.

I know that NetworkManager and its openvpn plugin use $HOME/.cert/... But openvpn is not started from systemd then. Do we have setups where openvpn starts from systemd and reads certificates from $HOME?

ProtectHome=read-only could help here... But I would still prefer ProtectHome=true.

BTW, setting can be overwritten with something like:

mkdir /etc/systemd/system/[email protected]...
cat > /etc/systemd/system/[email protected].../protecthome.conf <<EOF
[Service]
ProtectHome=read-only
EOF

Quoted 7 lines

For the others, I think they are more reasonable ... But I need to dig into the more murky details to be 100% they are safe for us. This is anyhow something we need to postpone until after 2.4.0 ... I don't dare adding more things which may backfire in rc2, as we're on a strict schedule to manage the next Debian release.

Once rc2 settles, I will start playing with this patch.

Agreed this is post-2.4.0 stuff. ;)

You can break this with something like:

status /etc/openvpn/client/status.log

in your configuration. Writing a status file
to /run/openvpn-{client,server}/status.log works, though. So the default setups should be fine. Do we have any more cases where openvpn wants write access for whatever?

Signature · 3 lines
main(a){char*c=/*    Schoene Gruesse                         */"B?IJj;MEH"
"CX:;",b;for(a/*    Best regards             my address:    */=0;b=c[a++];)
putchar(b-1/(/*    Chris            cc -ox -xc - && ./x    */b/42*2-3)*42);}
#3 lore raw
Quoted 8 lines

You can break this with something like:

status /etc/openvpn/client/status.log

in your configuration. Writing a status file
to /run/openvpn-{client,server}/status.log works, though. So the default setups should be fine. Do we have any more cases where openvpn wants write access for whatever?

From my configuration:
1) status
2) ifconfig-pool-persist
3) tmp-dir (for storing openvpn_pf_*.tmp files)
4) client-connect script may want to write something
5) a plugin may want to write something

For me even the read-only option will break nearly *everything*. And for user it will be completely not obvious why his scripts doesn't work, why his status file is not updated, and what's wrong with ifconfig-pool-persist.

#4 lore raw

SviMik <[email protected]...> on Sat, 2016/12/10 06:06:

Quoted 11 lines
Quoted 8 lines

You can break this with something like:

status /etc/openvpn/client/status.log

in your configuration. Writing a status file
to /run/openvpn-{client,server}/status.log works, though. So the default setups should be fine. Do we have any more cases where openvpn wants write access for whatever?

From my configuration:
1) status

That is fine if it is written to /run/openvpn-{client,server}/. It breaks with the status file in /etc/openvpn/{client,server}/ or example.

Quoted 1 line

2) ifconfig-pool-persist

That is a problem... As the name suggests this should be persistent. :-/

Quoted 1 line

3) tmp-dir (for storing openvpn_pf_*.tmp files)

Never used this. What is it for?
Anyway, I think this is not persistent stuff? Writing to /tmp/ or /run/openvpn-{client,server}/ should be fine.

Quoted 1 line

4) client-connect script may want to write something

My scripts do some configuration and dbus-stuff, but do not write anything... Writing to read-only path would fail, of course.

Quoted 1 line

5) a plugin may want to write something

Same here... /run/ and /tmp/ is fine, other paths fail.

Quoted 3 lines

For me even the read-only option will break nearly *everything*. And for user it will be completely not obvious why his scripts doesn't work, why his status file is not updated, and what's wrong with ifconfig-pool-persist.

Well, the error message should include something like: "cannot open file 'file': Read-only file system".

But this is more problematic than I thought initially.

Signature · 3 lines
main(a){char*c=/*    Schoene Gruesse                         */"B?IJj;MEH"
"CX:;",b;for(a/*    Best regards             my address:    */=0;b=c[a++];)
putchar(b-1/(/*    Chris            cc -ox -xc - && ./x    */b/42*2-3)*42);}
#5 lore raw
Quoted 10 lines · Christian Hesse

SviMik <[email protected]...> on Sat, 2016/12/10 06:06:

Quoted 9 lines
Quoted 8 lines

You can break this with something like:

status /etc/openvpn/client/status.log

in your configuration. Writing a status file
to /run/openvpn-{client,server}/status.log works, though. So the default setups should be fine. Do we have any more cases where openvpn wants write access for whatever?

Quoted 5 lines
Quoted 2 lines

From my configuration:
1) status

That is fine if it is written to /run/openvpn-{client,server}/. It breaks with the status file in /etc/openvpn/{client,server}/ or example.

FWIW, the default SELinux policies actually denies any openvpn_exec_t process to write to /etc ... I believe that is independent of Linux distros, as long as SELinux have been enabled and the system is Enforced mode.

Quoted 3 lines
Quoted 1 line

2) ifconfig-pool-persist

That is a problem... As the name suggests this should be persistent. :-/

Same SELinux issue here too. IIRC, these files needs to be located under /var/lib/openvpn or /var/run/openvpn. But I do see there is one exception ... /etc/openvpn/ipp\.txt will be labelled openvpn_etc_rw_t, which is OpenVPN is allowed to write to.

Quoted 5 lines
Quoted 1 line

3) tmp-dir (for storing openvpn_pf_*.tmp files)

Never used this. What is it for?
Anyway, I think this is not persistent stuff? Writing to /tmp/ or /run/openvpn-{client,server}/ should be fine.

The openvpn_pf_*.tmp files are just one thing. If you use --auth-user-pass-verify script hooks or perhaps even --plugin for authentication, other temp files are generated in the default tmp-dir. See commit 4e1cc5f6dda22e9ff12 for more info.

Quoted 4 lines
Quoted 1 line

4) client-connect script may want to write something

My scripts do some configuration and dbus-stuff, but do not write anything... Writing to read-only path would fail, of course.

Again, SELinux can again block this already ... unless you write in the properly labelled directories for OpenVPN.

Quoted 3 lines
Quoted 1 line

5) a plugin may want to write something

Same here... /run/ and /tmp/ is fine, other paths fail.

The same as 4)

Quoted 8 lines
Quoted 3 lines

For me even the read-only option will break nearly *everything*. And for user it will be completely not obvious why his scripts doesn't work, why his status file is not updated, and what's wrong with ifconfig-pool-persist.

Well, the error message should include something like: "cannot open file 'file': Read-only file system".

But this is more problematic than I thought initially.

If we have some directories which complies with the SELinux policies in regards to read/write privileges, we should be fine. And restricting which directories OpenVPN can write to is quite sane. All those plenty of blogs putting runtime status files into /etc/openvpn have misunderstood quite some of the concept of the Unix file system layout.

Signature · 4 lines
kind regards,

David Sommerseth
OpenVPN Technologies, Inc
#6 lore raw
In reply to Christian Hesse

Hi,

Quoted 6 lines · Christian Hesse

From: Christian Hesse <[email protected]...>

ProtectSystem=strict mounts the entire file system hierarchy read-only, except for the API file system subtrees /dev, /proc and /sys (which can be protected using PrivateDevices=, ProtectKernelTunables=, ProtectControlGroups=).

Unless the temp directories are still writeable, this will break server configs with --client-connect scripts or plugins trying to hand back config settings via temp files.

(I do not think an openvpn *client* config will need a to create files, but this needs testing)

gert

Signature · 4 lines
USENET is *not* the non-clickable part of WWW!
                                                           //www.muc.de/~gert/
Gert Doering - Munich, Germany                             [email protected]...
fax: +49-89-35655025                        [email protected]...
#7 lore raw
Quoted 10 lines

Hi,

Quoted 6 lines · Christian Hesse

From: Christian Hesse <[email protected]...>

ProtectSystem=strict mounts the entire file system hierarchy read-only, except for the API file system subtrees /dev, /proc and /sys (which can be protected using PrivateDevices=, ProtectKernelTunables=, ProtectControlGroups=).

Quoted 7 lines

Unless the temp directories are still writeable, this will break server configs with --client-connect scripts or plugins trying to hand back config settings via temp files.

(I do not think an openvpn *client* config will need a to create files, but this needs testing)

Even if you find a way to store temporary files, I'm still not sure what can be done with ifconfig-pool-persist. It's not a temp file, it should be persistent.

#8 lore raw
Quoted 5 lines
Quoted 5 lines

(I do not think an openvpn *client* config will need a to create files, but this needs testing)

No, it does not. You compile with CLIENT_ONLY the tmp-dir option will throw an error.

Arne

#9 lore raw
In reply to Gert Doering
Quoted 5 lines · Gert Doering

Hi,

Quoted 2 lines · Christian Hesse

From: Christian Hesse <[email protected]...>

Quoted 8 lines
Quoted 4 lines

ProtectSystem=strict mounts the entire file system hierarchy read-only, except for the API file system subtrees /dev, /proc and /sys (which can be protected using PrivateDevices=, ProtectKernelTunables=, ProtectControlGroups=).

Unless the temp directories are still writeable, this will break server configs with --client-connect scripts or plugins trying to hand back config settings via temp files.

Agreed, we cannot have /tmp (or --tmp-dir) read-only.

However, I read up a bit on ProtectSystem= on RHEL7. And on RHEL7 (shipping systemd-219) ProtectSystem= can only be 'full' or 'true' (it is 'false'/off by default). We cannot use any other values, as RHEL defines the oldest distros we support, and RHEL7 is the oldest systemd distro we will support in the future.

We can definitely use ProtectSystem=true, as that ensure /usr and /boot are read-only. That is safe. If using 'full', /etc is also made read-only. I personally think this makes sense too, as if you have any state or log files, they should be placed under /var/log, {/var,}/run or /var/lib.

Signature · 4 lines
kind regards,

David Sommerseth
OpenVPN Technologies, Inc
#10 lore raw

PATCH v2 1/1 add more security feature for systemd units

In reply to Christian Hesse

From: Christian Hesse <[email protected]...>

ProtectSystem=true mounts the /usr and /boot directories read-only.

ProtectHome=true makes the directories /home, /root and /run/user inaccessible and empty for the process.

See systemd.exec(5) [0] for details.

v2: Replace ProtectSystem=strict with ProtectSystem=true. Some configurations
may want to write to /etc or the like.

[0] https://www.freedesktop.org/software/systemd/man/systemd.exec.html

---
 distro/systemd/[email protected]... | 2 ++
 distro/systemd/[email protected]... | 2 ++
 2 files changed, 4 insertions(+)
distro/systemd/[email protected]... +2 -0
index 5618af3..b92f2fa 100644
@@ -17,6 +17,8 @@ CapabilityBoundingSet=CAP_IPC_LOCK CAP_NET_ADMIN CAP_NET_RAW CAP_SETGID CAP_SETU
 LimitNPROC=10
 DeviceAllow=/dev/null rw
 DeviceAllow=/dev/net/tun rw
+ProtectSystem=true
+ProtectHome=true
 
 [Install]
 WantedBy=multi-user.target
distro/systemd/[email protected]... +2 -0
index b9b4dba..535a79d 100644
@@ -17,6 +17,8 @@ CapabilityBoundingSet=CAP_IPC_LOCK CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RA
 LimitNPROC=10
 DeviceAllow=/dev/null rw
 DeviceAllow=/dev/net/tun rw
+ProtectSystem=true
+ProtectHome=true
 
 [Install]
 WantedBy=multi-user.target
Signature · 1 line
2.11.0
#11 lore raw

Re: [Openvpn-devel] [PATCH applied] systemd: Add more security feature for systemd units

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

ACK. Tested this lightly with both server and client profiles, and this seems to work very well. Users having keys under /home will probably complain. But I do not think system wide configurations should depend on keys in users' home directories.

Your patch has been applied to the following branches

commit 76096c605fcac4815674b6ae76ac1f31f03a8186 (master) commit ba3ccaf92d379f8a2efad80cee7dc2806088f421 (release/2.4)

Author: Christian Hesse
Date:   Tue Dec 27 23:18:32 2016 +0100
     systemd: Add more security feature for systemd units

     Signed-off-by: Christian Hesse <[email protected]...>
     Acked-by: David Sommerseth <[email protected]...>
     Message-Id: <[email protected]...>
     URL: https://www.mail-archive.com/[email protected]/msg13743.html
     Signed-off-by: David Sommerseth <[email protected]...>

- --
kind regards,

David Sommerseth

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.22 (GNU/Linux)

iQIcBAEBAgAGBQJYiPPRAAoJEIbPlEyWcf3ymHAQAIuy8UXELqs4blJCs0IfHtOg nALf1ALs+fvhQp7he+Z+wxmDT+QFL3mli53RXKZZGG8y+boWgRFkJ11PX4YzsCO9 KSJAWqbDRW+n9pp8uZ7q6D+uLeiO6ziKhEm6Jl2zln4FtTxi3pW8jUcONEdNwBtP XSzJ7vdKAuiKGp8GvDm+uWpyjRJvpsClKynPvh2sN0bY6ERlkLDYKUMy37+1vDfc HV6k1Rdwq7L4fVxbx9P6YWF/iKX3yuqTK1Qs99ZaZ7N4UE+QAYtuOtzDbAb+ISrN fs7kOim2H5OZ8qfgYTosE6bRLP4mTEqgKX7zjYUMPWWZZgvrW3H9E4v/nGWupZxD NaLIE+WELGDVZRnHMZRkVYCbK6zcPYyvfrehc2O/cKKNAtsIQLDe8NdiirpWsbRB 7+e/UCgIyvtPTxaf1FoVD0ENdyfGXT3EYRIuCsPA6Uk9C5vu3JpAhBnxhleaynE6 Vkh29k3lxBi/CHKsIa2DYYLqumrkwlI9TJ6FHSt7xR4zYkA92BZb2UKZGDkuCss7 g5wNrnxuswIaAgllsa7YSKkVSS41DhlUZG+flFnFLbodME5HatUJWokAqJzOzC7L vH1SMR+AQGKRwV1YkEJYRsxYfKJFByViipoqHkStq70Bl7Qql2hGXS+qh8cC/bLK WX35Il88WHshyCmcqI+d
=2/Wt
-----END PGP SIGNATURE-----