On 2022/12/15 13:56:00 -0700, Ashlen <euryd...@riseup.net> wrote:
> Hi all, so I'm wondering how to securely deal with TLS certificates on a 
> server
> that's grown to host multiple services (website, XMPP, soon email as well).
> Specifically how to handle permissions and to what degree certificates should 
> be
> separated.
> 
> (I recognize this is a long email. I'm unsure how to break down my thoughts
> further)
> 
> I know that I could add a load of Subject Alternative Names to one big
> certificate, but I have a couple of concerns with this.
> 
> 1) If I understand it right, if there's a security issue with one program and 
> an
> attacker gains arbitrary read, and the effective user id can read the private
> key, the exposure is greater than it has to be (that is to say, domains that 
> are
> completely unrelated to the insecure program are exposed). Daemons outside of
> base unfortunately often lack privilege separation to the extent that it 
> exists
> in base, so there may not be a separate user to handle private keys, and then
> the whole thing has the potential to blow up later.
> 
> 2) A long list of Subject Alternative Names means that anyone connecting to 
> the
> web server can see all of the additional subdomains that are unrelated to the
> web server being hosted. This is really a nitpick compared to the first point,
> as even without this being the case there are other methods of enumeration and
> discovery (nmap and friends), and relying on DNS entries being hidden seems 
> like
> a bad idea.
> 
> The best way I can think of how to handle this so far, and "best" is used very
> loosely since I don't think it's a perfect solution, is to split the keys up,
> add a separate group, and modify `/etc/ssl/private`.
> 
> ```
> # groupadd tls
> # usermod -G tls _prosody
> # chown root:tls /etc/ssl/private
> # chmod 750 /etc/ssl/private
> ```
>
> Then the private keys within would all have 0400 permissions, user and group
> being the same (so _prosody:_prosody for XMPP-related TLS). I noted that the
> default is 700 permissions on `/etc/ssl/private` with root:wheel ownership. Is
> the approach I've just outlined with adding a group and modifying permissions 
> a
> bad idea?

Personally, I wouldn't deviate from the os defaults by changing the
permission on /etc/ssl/private.

it seems fragile, and you'd also need to make sure permissions are
kept when updating the certificates.

> Even if it makes sense to do it this way, I still have a separate issue in 
> that
> when two or more services need the certificate for the root domain, they'll 
> end
> up sharing it, and I'm unclear what the right way to fix that problem is. If
> it's only services in the base system, that's one thing. But Prosody also has
> this issue with the way I set it up. Currently it's configured so that 
> usernames
> can be in the form "u...@example.com" rather than "u...@xmpp.example.com"
> (similar to how email usernames use the root domain). This means it needs the
> certificate for the root domain so that authentication can take place over 
> TLS,
> and that breaks the separation.

you can just issue multiple certificates.  A compromised prosody would
still be able to leak the certificate for "example.com", but there's
no other way around it as it needs the certificate.

> For some services, it can make sense to use relayd(8) and let that handle TLS
> instead, which simplifies things since relayd has proper privilege separation
> and can even use SNI. But I'm unsure how this could be done with something 
> like
> Prosody since XMPP uses STARTTLS (outside of exceptions to that rule like
> XEP-0368).
> 
> What can I do to manage this better? Any ideas/suggestions are very welcome.
> Thank you for reading all of this if you made it here.

Can only speak for prosody as it's the only non-base daemon I'm
getting TLS certificates for; my strategy with it has been to generate
a different certificate and to deliver it in a place where only
prosody can read it.  Luckily, the prosody package installs
/etc/prosody/certs owned by _prosody alone.

        # /etc/acme-client.conf
        domain xmpp {
                domain name example.com
                alternative names { room.example.com upload.example.com }
                domain key "/etc/prosody/certs/example.com.key"
                domain full chain certificate 
"/etc/prosody/certs/example.net.crt"
                sign with letsencrypt
        }

note the `domain' name is "xmpp" because I have another `domain' block
for the same domain (but different alt names) for httpd:

        # only for httpd
        domain example.com {
                alternative names { www.example.com }
                ...
        }

all handled by cron as usual:

        ~ * * * * acme-client example.com && rcctl reload httpd
        ~ * * * * acme-client xmpp && rcctl restart prosody

in prosody.conf.lua i have

        certificates = "certs"

I also have some symlinks in /etc/prosody/certs in the form:

        {room,upload}.example.com.crt -> example.com.crt
        {room,upload}.example.com.key -> example.com.key

so that prosody can look up the certs by itself without extra
configuration.  Can probably do it without the symlinks, but I was
lazy and this worked for me.

HTH

Reply via email to