Thread: [HACKERS] Possible SSL improvements for a newcomer to tackle
I previously made one minuscule contribution to the project two years ago. I'm interested in doing some more, and I'm trying to figure out what to focus on. Two SSL-related projects caught my attention:
1) Allow automatic selection of SSL client certificates from a certificate store (https://www.postgresql.org/message-id/8766.1241799013@sss.pgh.pa.us). It seems relatively straightforward to support an additional file format for key-value pairs in postgresql.crt/.key, and I think this is something I could take on if it's still desired.
2) I was surprised to learn the following from the docs:
> By default, PostgreSQL will not perform any verification of the server certificate. This means that it is possible to spoof the server identity (for example by modifying a DNS record or by taking over the server IP address) without the client knowing. In order to prevent spoofing, SSL certificate verification must be used.
Is there a technical reason to perform no verification by default? Wouldn't a safer default be desirable?
1) Allow automatic selection of SSL client certificates from a certificate store (https://www.postgresql.org/message-id/8766.1241799013@sss.pgh.pa.us). It seems relatively straightforward to support an additional file format for key-value pairs in postgresql.crt/.key, and I think this is something I could take on if it's still desired.
2) I was surprised to learn the following from the docs:
> By default, PostgreSQL will not perform any verification of the server certificate. This means that it is possible to spoof the server identity (for example by modifying a DNS record or by taking over the server IP address) without the client knowing. In order to prevent spoofing, SSL certificate verification must be used.
Is there a technical reason to perform no verification by default? Wouldn't a safer default be desirable?
Zeus Kronion <zkronion@gmail.com> writes: > 2) I was surprised to learn the following from the docs: >> By default, PostgreSQL will not perform any verification of the server >> certificate. > Is there a technical reason to perform no verification by default? Wouldn't > a safer default be desirable? I'm not an SSL expert, so insert appropriate grain of salt, but AIUI the question is what are you going to verify against? You need some local notion of which are your trusted root certificates before you can verify anything. So to default to verification would be to default to failing to connect at all until user has created a ~/.postgresql/root.crt file with valid, relevant entries. That seems like a nonstarter. It's possible that we could adopt some policy like "if the root.crt file exists then default to verify" ... but that seems messy and unreliable, so I'm not sure it would really add any security. regards, tom lane -- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers
On Tue, Oct 3, 2017 at 1:15 PM, Zeus Kronion <zkronion@gmail.com> wrote: > I previously made one minuscule contribution to the project two years ago. > I'm interested in doing some more, and I'm trying to figure out what to > focus on. Two SSL-related projects caught my attention: > 1) Allow automatic selection of SSL client certificates from a certificate > store (https://www.postgresql.org/message-id/8766.1241799013@sss.pgh.pa.us). > It seems relatively straightforward to support an additional file format for > key-value pairs in postgresql.crt/.key, and I think this is something I > could take on if it's still desired. > 2) I was surprised to learn the following from the docs: One other thing that could be improved, and that has been already asked for is improvement for passphrase handling, particularly since SSL parameters can be reloaded, by adding for example a new GUC parameter that calls a shell command which outputs what is wanted to stdout. It could be tricky to implement as the postmaster should be able to handle requests when launching the command. But I think you get the idea. >> By default, PostgreSQL will not perform any verification of the server >> certificate. This means that it is possible to spoof the server identity >> (for example by modifying a DNS record or by taking over the server IP >> address) without the client knowing. In order to prevent spoofing, SSL >> certificate verification must be used. > > Is there a technical reason to perform no verification by default? Wouldn't > a safer default be desirable? It would be nice to get into a stronger default with "require" at least, the recommendation is to use at least "verify-ca" for any serious deployment. Note that not long ago there were arguments about how the default value of sslmode called 'prefer' is good at giving a false sense of security, but this led nowhere (can't put my hands on this thread now..). -- Michael -- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers
On Tue, Oct 3, 2017 at 6:33 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
Zeus Kronion <zkronion@gmail.com> writes:
> 2) I was surprised to learn the following from the docs:
>> By default, PostgreSQL will not perform any verification of the server
>> certificate.
> Is there a technical reason to perform no verification by default? Wouldn't
> a safer default be desirable?
I'm not an SSL expert, so insert appropriate grain of salt, but AIUI the
question is what are you going to verify against? You need some local
notion of which are your trusted root certificates before you can verify
anything. So to default to verification would be to default to failing to
connect at all until user has created a ~/.postgresql/root.crt file with
valid, relevant entries. That seems like a nonstarter.
Yes, you need something to verify against.
One way to do it would be to default to the "system global certificate store", which is what most other SSL apps do. For example on a typical debian/ubuntu, that'd be the store in /etc/ssl/certs/ca-certificates.crt. Exactly where to find them would be distribution-specific though, and we would need to actually add support for a second certificate store. But that would probably be a useful feature in itself.
It's possible that we could adopt some policy like "if the root.crt file
exists then default to verify" ... but that seems messy and unreliable,
so I'm not sure it would really add any security.
No that's horrible. If it's unreliable, it doesn't provide any actual benefit. We have a history of that in our default being prefer instead of allow, but we definitely shouldn't make that situation even worse.
Hi, On 10/03/2017 06:15 AM, Zeus Kronion wrote: > 2) I was surprised to learn the following from the docs: > >> By default, PostgreSQL will not perform any verification of the server > certificate. This means that it is possible to spoof the server identity (for > example by modifying a DNS record or by taking over the server IP address) > without the client knowing. In order to prevent spoofing, SSL certificate > verification must be used. > > Is there a technical reason to perform no verification by default? Wouldn't a > safer default be desirable? If you want to verify server's certificate you should use DANE [1] + DNSSEC [2] ? (I am not an SSL expert too) If I understand correctly, you can store your certificate in a DNS record (TLSA). Then the client can check the certificate. You must trust your DNS server (protection against spoofing), that's why you have to use DNSSEC. 1: https://en.wikipedia.org/wiki/DNS-based_Authentication_of_Named_Entities 2: https://en.wikipedia.org/wiki/Domain_Name_System_Security_Extensions -- Adrien NAYRAT
Magnus Hagander <magnus@hagander.net> writes: > On Tue, Oct 3, 2017 at 6:33 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote: >> I'm not an SSL expert, so insert appropriate grain of salt, but AIUI the >> question is what are you going to verify against? > One way to do it would be to default to the "system global certificate > store", which is what most other SSL apps do. For example on a typical > debian/ubuntu, that'd be the store in /etc/ssl/certs/ca-certificates.crt. > Exactly where to find them would be distribution-specific though, and we > would need to actually add support for a second certificate store. But that > would probably be a useful feature in itself. Maybe. The impression I have is that it's very common for installations to use a locally-run CA to generate server and client certs. I would not expect them to put such certs into /etc/ssl/certs. But I suppose there might be cases where you would actually pay for a universally-valid cert for a DB server ... regards, tom lane -- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers
Tom, * Tom Lane (tgl@sss.pgh.pa.us) wrote: > Magnus Hagander <magnus@hagander.net> writes: > > On Tue, Oct 3, 2017 at 6:33 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote: > >> I'm not an SSL expert, so insert appropriate grain of salt, but AIUI the > >> question is what are you going to verify against? > > > One way to do it would be to default to the "system global certificate > > store", which is what most other SSL apps do. For example on a typical > > debian/ubuntu, that'd be the store in /etc/ssl/certs/ca-certificates.crt. > > Exactly where to find them would be distribution-specific though, and we > > would need to actually add support for a second certificate store. But that > > would probably be a useful feature in itself. > > Maybe. The impression I have is that it's very common for installations > to use a locally-run CA to generate server and client certs. I would not > expect them to put such certs into /etc/ssl/certs. But I suppose there > might be cases where you would actually pay for a universally-valid cert > for a DB server ... In many larger enterprises, they actually deploy systems with their own CA installed into the system global certificate store (possibly removing certain other CAs from that set too, and distributing their own version of the relevant package that maintains the CA set). I agree with Magnus that most other SSL apps do default to the system global cert store and it's generally what's expected. Thanks! Stephen
On Tue, Oct 3, 2017 at 3:51 PM, Stephen Frost <sfrost@snowman.net> wrote:
Tom,
* Tom Lane (tgl@sss.pgh.pa.us) wrote:
> Magnus Hagander <magnus@hagander.net> writes:
> > On Tue, Oct 3, 2017 at 6:33 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
> >> I'm not an SSL expert, so insert appropriate grain of salt, but AIUI the
> >> question is what are you going to verify against?
>
> > One way to do it would be to default to the "system global certificate
> > store", which is what most other SSL apps do. For example on a typical
> > debian/ubuntu, that'd be the store in /etc/ssl/certs/ca-certificates.crt.
> > Exactly where to find them would be distribution-specific though, and we
> > would need to actually add support for a second certificate store. But that
> > would probably be a useful feature in itself.
>
> Maybe. The impression I have is that it's very common for installations
> to use a locally-run CA to generate server and client certs. I would not
> expect them to put such certs into /etc/ssl/certs. But I suppose there
> might be cases where you would actually pay for a universally-valid cert
> for a DB server ...
In many larger enterprises, they actually deploy systems with their own
CA installed into the system global certificate store (possibly removing
certain other CAs from that set too, and distributing their own version
of the relevant package that maintains the CA set).
I think this is also something that's seen more now than it used to be. Back when we initially did the SSL support, few people actually did this. That's not just for this scenario of course -- larger enterprises are much more likely to *have* proper PKI management today, and if they do then it will include the Linux boxes.
Bottom line: things in this area has change greatly in the past 10-15 years.
On Tue, Oct 03, 2017 at 12:33:00AM -0400, Tom Lane wrote: > Zeus Kronion <zkronion@gmail.com> writes: > > 2) I was surprised to learn the following from the docs: > > >> By default, PostgreSQL will not perform any verification of the server > >> certificate. > > > Is there a technical reason to perform no verification by default? Wouldn't > > a safer default be desirable? > > I'm not an SSL expert, so insert appropriate grain of salt, but AIUI the > question is what are you going to verify against? You need some local > notion of which are your trusted root certificates before you can verify > anything. So to default to verification would be to default to failing to > connect at all until user has created a ~/.postgresql/root.crt file with > valid, relevant entries. That seems like a nonstarter. > > It's possible that we could adopt some policy like "if the root.crt file > exists then default to verify" ... but that seems messy and unreliable, > so I'm not sure it would really add any security. You do always need trust anchors in order to verify a peer's certificate. Usually there will be a system-wide trust anchor set, though it may not be appropriate for use with PG... Still, it would be safer to refuse to connect until the lack of trust anchors is rectified than to connect without warning about the inability to verify a server. By forcing the user (admins) to take action to remediate the problem, the problem then gets fixed, whereas plowing on creates an invisible (for many users) security problem. Now, the use of channel binding from authentication methods like GSS-API helps a fair bit, though mostly it helps by leveraging some other authentication infrastructure that the users (admins) have set up -- they could easily have setup PKI too then. With SCRAM there is much less infrastructure (but also SCRAM requires very good passwords; a PAKE would be much better). Nico -- -- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers
On Tue, Oct 03, 2017 at 09:44:01AM -0400, Tom Lane wrote: > Magnus Hagander <magnus@hagander.net> writes: > > On Tue, Oct 3, 2017 at 6:33 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote: > >> I'm not an SSL expert, so insert appropriate grain of salt, but AIUI the > >> question is what are you going to verify against? > > > One way to do it would be to default to the "system global certificate > > store", which is what most other SSL apps do. For example on a typical > > debian/ubuntu, that'd be the store in /etc/ssl/certs/ca-certificates.crt. > > Exactly where to find them would be distribution-specific though, and we > > would need to actually add support for a second certificate store. But that > > would probably be a useful feature in itself. > > Maybe. The impression I have is that it's very common for installations > to use a locally-run CA to generate server and client certs. I would not > expect them to put such certs into /etc/ssl/certs. But I suppose there > might be cases where you would actually pay for a universally-valid cert > for a DB server ... No, that is very common. However, in non-enterprise uses it's also very common for those to be Web PKI certificates, which would be very inappropriate for use in PG, so I agree that PG should not use the system trust anchor set by default. PG should just require that a trust anchor set be configured. Nico -- -- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers
On Tue, Oct 03, 2017 at 11:45:24AM +0200, Adrien Nayrat wrote: > On 10/03/2017 06:15 AM, Zeus Kronion wrote: > > 2) I was surprised to learn the following from the docs: > > > >> By default, PostgreSQL will not perform any verification of the server > > certificate. This means that it is possible to spoof the server identity (for > > example by modifying a DNS record or by taking over the server IP address) > > without the client knowing. In order to prevent spoofing, SSL certificate > > verification must be used. > > > > Is there a technical reason to perform no verification by default? Wouldn't a > > safer default be desirable? > > If you want to verify server's certificate you should use DANE [1] + DNSSEC [2] > ? (I am not an SSL expert too) > > If I understand correctly, you can store your certificate in a DNS record > (TLSA). Then the client can check the certificate. You must trust your DNS > server (protection against spoofing), that's why you have to use DNSSEC. +1, but it's trickier than you might think. I can connect you with Viktor Dukhovni, who has implemented DANE for OpenSSL, and done yeoman's work getting DANE for SMTP working. Nico -- -- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers
On 10/03/2017 05:47 PM, Nico Williams wrote: > +1, but it's trickier than you might think. I can connect you with > Viktor Dukhovni, who has implemented DANE for OpenSSL, and done yeoman's > work getting DANE for SMTP working. I really appreciate, but I know it is very tricky :). I do not pretend to work on this feature, I really do not have sufficient knowledge :/. -- Adrien NAYRAT
On Tue, Oct 3, 2017 at 11:39 AM, Nico Williams <nico@cryptonector.com> wrote:
I agree with Nico. If the server certificate can't be validated, the client should fail to connect unless specifically opting out of MITM protection. Why not change DefaultSSLMode from "prefer," even if it isn't backwards compatible? Is there a policy for deprecating default settings?
On Tue, Oct 03, 2017 at 12:33:00AM -0400, Tom Lane wrote:
> So to default to verification would be to default to failing to
> connect at all until user has created a ~/.postgresql/root.crt file with
> valid, relevant entries. That seems like a nonstarter.
>
> It's possible that we could adopt some policy like "if the root.crt file
> exists then default to verify" ... but that seems messy and unreliable,
> so I'm not sure it would really add any security.
Still, it would be safer to refuse to connect until the lack of trust
anchors is rectified than to connect without warning about the inability
to verify a server. By forcing the user (admins) to take action to
remediate the problem, the problem then gets fixed, whereas plowing on
creates an invisible (for many users) security problem.
I agree with Nico. If the server certificate can't be validated, the client should fail to connect unless specifically opting out of MITM protection. Why not change DefaultSSLMode from "prefer," even if it isn't backwards compatible? Is there a policy for deprecating default settings?
On Mon, Oct 2, 2017 at 9:33 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
It's possible that we could adopt some policy like "if the root.crt file
exists then default to verify" ... but that seems messy and unreliable,
so I'm not sure it would really add any security.
That is what we do. If root.crt exists, we default to verify-ca.
And yes, it is messy and unreliable. I don't know if it adds any security or not.
Or do you mean we could default to verify-full instead of verify-ca?
Cheers,
Jeff
On Wed, Oct 04, 2017 at 11:47:45AM -0700, Jeff Janes wrote: > On Mon, Oct 2, 2017 at 9:33 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote: > > It's possible that we could adopt some policy like "if the root.crt file > > exists then default to verify" ... but that seems messy and unreliable, > > so I'm not sure it would really add any security. > > That is what we do. If root.crt exists, we default to verify-ca. > > And yes, it is messy and unreliable. I don't know if it adds any security > or not. > > Or do you mean we could default to verify-full instead of verify-ca? I would rather psql defaulted to verify-full and let users deal with errors by either a) configuring appropriate trust anchors and provisioning appropriate certificates, or b) disabling verify-full. Users should know that they are using psql(1) insecurely -- it has to be obvious. Yes, this would be a backwards-incompatible change, but security tends to justify this sort of change. Another possibility would be to make this default change only applicable when using postgresql-scheme URIs (which I do, almost religiously -- they are much easier to use than all alternative connection data specifications). Nico -- -- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers
On Tue, Oct 3, 2017 at 6:44 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
Magnus Hagander <magnus@hagander.net> writes:
> On Tue, Oct 3, 2017 at 6:33 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
>> I'm not an SSL expert, so insert appropriate grain of salt, but AIUI the
>> question is what are you going to verify against?
> One way to do it would be to default to the "system global certificate
> store", which is what most other SSL apps do. For example on a typical
> debian/ubuntu, that'd be the store in /etc/ssl/certs/ca-certificates.crt.
> Exactly where to find them would be distribution-specific though, and we
> would need to actually add support for a second certificate store. But that
> would probably be a useful feature in itself.
Maybe. The impression I have is that it's very common for installations
to use a locally-run CA to generate server and client certs. I would not
expect them to put such certs into /etc/ssl/certs.
Well, I would do it that way if it worked. Not directly /etc/ssl/certs, but /etc/pki/ca-trust/source/anchors/
I would like the locally-run CA to able to sign not just postgresql server certs, but also apache server certs. And then install the CA cert file in one place per client and have it work for psql, curl, wget, etc.
Cheers,
Jeff