BUG #4340: SECURITY: Is SSL Doing Anything?
The following bug has been logged online:
Bug reference: 4340
Logged by: Dan Kaminsky
Email address: dan@doxpara.com
PostgreSQL version: 7.3
Operating system: Any
Description: SECURITY: Is SSL Doing Anything?
Details:
http://www.google.com/codesearch?hl=en&q=verify_cb+package:http://ring.atr.j
p/archives/misc/db/postgresql-jp/7.3beta/postgresql-7.3b1.tar.gz+show:T2MIh9
GrfhE:LRGuIfOPoEk:-Eemn4ZpAKY&sa=N&cd=1&ct=rc&cs_p=http://ring.atr.jp/archiv
es/misc/db/postgresql-jp/7.3beta/postgresql-7.3b1.tar.gz&cs_f=postgresql-7.3
b1/src/interfaces/libpq/fe-secure.c#l355
/*
* Certificate verification callback
*
* This callback allows us to log intermediate problems during
* verification, but there doesn't seem to be a clean way to get
* our PGconn * structure. So we can't log anything!
*
* This callback also allows us to override the default acceptance
* criteria (e.g., accepting self-signed or expired certs), but
* for now we accept the default checks.
*/
static int
verify_cb(int ok, X509_STORE_CTX *ctx)
{
return ok;
}
---
Clearly, this is handling self-signed certs. Great. But what I really want
to know is, is verify_peer accepting a self-signed identity assertion?
Because that'd be remote EoP.
"Dan Kaminsky" <dan@doxpara.com> writes:
Clearly, this is handling self-signed certs. Great. But what I really want
to know is, is verify_peer accepting a self-signed identity assertion?
Because that'd be remote EoP.
I'm just guessing what you're driving at (unexplained acronyms aren't
a good way to communicate), but I think it's not a big problem. PG
doesn't rely on SSL for authentication, only for communications
security, so whether the remote cert is self-signed doesn't seem
like much of an issue. Anyway, you can adjust your list of trusted
CAs to determine whether you'll accept it or not.
regards, tom lane
Tom Lane wrote:
"Dan Kaminsky" <dan@doxpara.com> writes:
Clearly, this is handling self-signed certs. Great. But what I really want
to know is, is verify_peer accepting a self-signed identity assertion?
Because that'd be remote EoP.I'm just guessing what you're driving at (unexplained acronyms aren't
a good way to communicate), but I think it's not a big problem. PG
doesn't rely on SSL for authentication, only for communications
security, so whether the remote cert is self-signed doesn't seem
like much of an issue. Anyway, you can adjust your list of trusted
CAs to determine whether you'll accept it or not.regards, tom lane
Heh Tom,
Thanks for replying so quickly. It's definitely appreciated.
Apologies, EoP = Escalation of Privilege. I've been up all night.
Lets talk about the verify_cb callback first: Suppose there's a
man-in-the-middle between the PG client and the PG server. Is some
secondary force going to apply some Trusted CA list?
Second, are you saying verify_peer doesn't do anything for
authentication? Are you sure about that? There's really little reason
otherwise for the call to exist.
--Dan
Dan Kaminsky <dan@doxpara.com> writes:
Lets talk about the verify_cb callback first: Suppose there's a
man-in-the-middle between the PG client and the PG server. Is some
secondary force going to apply some Trusted CA list?
I'm not sure why we have verify_cb at all -- so far as I can see,
it just specifies the same behavior as OpenSSL's default. Are
you saying that OpenSSL's default verification behavior is broken?
Second, are you saying verify_peer doesn't do anything for
authentication? Are you sure about that? There's really little reason
otherwise for the call to exist.
Er, we don't *have* a verify_peer callback.
regards, tom lane
Tom Lane wrote:
Dan Kaminsky <dan@doxpara.com> writes:
Lets talk about the verify_cb callback first: Suppose there's a
man-in-the-middle between the PG client and the PG server. Is some
secondary force going to apply some Trusted CA list?I'm not sure why we have verify_cb at all -- so far as I can see,
it just specifies the same behavior as OpenSSL's default. Are
you saying that OpenSSL's default verification behavior is broken?
verify_cb() is just a throwaway true parameter for the function, I
assume.
Second, are you saying verify_peer doesn't do anything for
authentication? Are you sure about that? There's really little reason
otherwise for the call to exist.Er, we don't *have* a verify_peer callback.
Uh, the user reported running Postgres 7.3 and we have improved SSL
quite a bit since then so perhaps an upgrade and reading the current
docs would help the user.
--
Bruce Momjian <bruce@momjian.us> http://momjian.us
EnterpriseDB http://enterprisedb.com
+ If your life is a hard drive, Christ can be your backup. +
Bruce Momjian wrote:
Tom Lane wrote:
Dan Kaminsky <dan@doxpara.com> writes:
Second, are you saying verify_peer doesn't do anything for
authentication? Are you sure about that? There's really little reason
otherwise for the call to exist.Er, we don't *have* a verify_peer callback.
Uh, the user reported running Postgres 7.3 and we have improved SSL
quite a bit since then so perhaps an upgrade and reading the current
docs would help the user.
The code is identical in HEAD, according to a quick read I did last
week.
--
Alvaro Herrera http://www.CommandPrompt.com/
The PostgreSQL Company - Command Prompt, Inc.
Alvaro Herrera <alvherre@commandprompt.com> writes:
Tom Lane wrote:
Er, we don't *have* a verify_peer callback.
Uh, the user reported running Postgres 7.3 and we have improved SSL
quite a bit since then so perhaps an upgrade and reading the current
docs would help the user.
The code is identical in HEAD, according to a quick read I did last
week.
Actually, I had missed that the OP was looking at 7.3 rather than 8.3.
There was a "verify_peer()" in 7.3 but it was #ifdef'd out. The
question remains whether there's a reason to have it. It would be good
if the discussion were based on a non-obsolete PG version ...
regards, tom lane
"Tom Lane" <tgl@sss.pgh.pa.us> writes:
Actually, I had missed that the OP was looking at 7.3 rather than 8.3.
There was a "verify_peer()" in 7.3 but it was #ifdef'd out. The
question remains whether there's a reason to have it. It would be good
if the discussion were based on a non-obsolete PG version ...
Well in theory SSL without at least one-way authentication is actually
worthless. It's susceptible to man-in-the-middle attacks meaning someone can
sniff all the contents or even inject into or take over connections. It is
proof against passive attacks but active attacks are known in the field so
that's cold comfort these days.
--
Gregory Stark
EnterpriseDB http://www.enterprisedb.com
Get trained by Bruce Momjian - ask me about EnterpriseDB's PostgreSQL training!
Gregory Stark wrote:
"Tom Lane" <tgl@sss.pgh.pa.us> writes:
Actually, I had missed that the OP was looking at 7.3 rather than 8.3.
There was a "verify_peer()" in 7.3 but it was #ifdef'd out. The
question remains whether there's a reason to have it. It would be good
if the discussion were based on a non-obsolete PG version ...Well in theory SSL without at least one-way authentication is actually
worthless. It's susceptible to man-in-the-middle attacks meaning someone can
sniff all the contents or even inject into or take over connections. It is
proof against passive attacks but active attacks are known in the field so
that's cold comfort these days.
As the finder of recent DNS issues, I'm pretty aware of real world
active attacks.
My question has been: When you attempt to create an SSL connection to
database.backend.com, do you actually validate that:
1) The subject name of the certificate you're connecting to is
database.backend.com, and
2) At least the basic checks (expiration, chaining back to a valid root)
occur?
I've gotten some reasonable hints that #2 happen, but I don't know if #1
happens, and these comments make me worry.
--Dan
Dan Kaminsky <dan@doxpara.com> writes:
My question has been: When you attempt to create an SSL connection to
database.backend.com, do you actually validate that:
1) The subject name of the certificate you're connecting to is
database.backend.com, and
2) At least the basic checks (expiration, chaining back to a valid root)
occur?
[ shrug... ] We do whatever OpenSSL's default validation behavior is.
If that's inadequate you probably ought to be taking it up with them,
instead of trying to get downstream projects to fix it one at a time.
regards, tom lane
Tom Lane wrote:
Dan Kaminsky <dan@doxpara.com> writes:
My question has been: When you attempt to create an SSL connection to
database.backend.com, do you actually validate that:1) The subject name of the certificate you're connecting to is
database.backend.com, and
2) At least the basic checks (expiration, chaining back to a valid root)
occur?[ shrug... ] We do whatever OpenSSL's default validation behavior is.
If that's inadequate you probably ought to be taking it up with them,
instead of trying to get downstream projects to fix it one at a time.regards, tom lane
Heh, you're the one making guarantees to your users. I'm just asking
the exact nature of those guarantees. I agree that #2 is entirely under
the control of OpenSSL -- but I'd like to know if #1 is being satisfied,
i.e. OpenSSL knows you're looking to validate database.backend.com as
opposed to "some cert that chains back", which is a worthless security
assertion.
--Dan
Dan Kaminsky wrote:
Tom Lane wrote:
Dan Kaminsky <dan@doxpara.com> writes:
My question has been: When you attempt to create an SSL connection
to database.backend.com, do you actually validate that:1) The subject name of the certificate you're connecting to is
database.backend.com, and
2) At least the basic checks (expiration, chaining back to a valid
root) occur?[ shrug... ] We do whatever OpenSSL's default validation behavior is.
If that's inadequate you probably ought to be taking it up with them,
instead of trying to get downstream projects to fix it one at a time.regards, tom lane
Heh, you're the one making guarantees to your users. I'm just asking
the exact nature of those guarantees. I agree that #2 is entirely under
the control of OpenSSL -- but I'd like to know if #1 is being satisfied,
i.e. OpenSSL knows you're looking to validate database.backend.com as
opposed to "some cert that chains back", which is a worthless security
assertion.
We do not validate the name. It is stated in a comment at the top of
f-secure.h that we do, but the code is all behind #ifdef NOT_USED. It
would probably not be a bad idea to have that check enabled by default,
but a way to turn it off.
(I don't believe OpenSSL does this verification either, because AFAICS
OpenSSL only ever sees the IP address of the server, and not the FQDN)
We do, however, return the peer certificate information to the libpq
client, that can verify this if it's considered necessary by the
*application*.
That said, claiming that the check of the chain up to a root certificate
is wortheless is very far from correct. Used the proper way, and the
way I most often see it deployed with PostgreSQL, makes it very worthy.
Because people normally either bundle the server certificate itself with
the application, in which case it will only ever connect to that server
(self-signed cert). Or they have a dedicated CA for this purpose. Is it
perfect? Far from. But it's certainly not worthless.
//Magnus
Magnus Hagander <magnus@hagander.net> writes:
(I don't believe OpenSSL does this verification either, because AFAICS
OpenSSL only ever sees the IP address of the server, and not the FQDN)
In common usages libpq doesn't have the FQDN of the server either.
To impose such a requirement, we'd have to forbid naming the server
by IP address or via a domain-search-path abbreviation.
regards, tom lane
Tom Lane wrote:
Magnus Hagander <magnus@hagander.net> writes:
(I don't believe OpenSSL does this verification either, because AFAICS
OpenSSL only ever sees the IP address of the server, and not the FQDN)In common usages libpq doesn't have the FQDN of the server either.
To impose such a requirement, we'd have to forbid naming the server
by IP address or via a domain-search-path abbreviation.
You could issue a certificate to an IP address, so you could match the
textual representation of the IP in that case.
Or you could require the FQDN for a SSL connection when this
verification is enabled. A similar restriction already exists for
Kerberos, for example.
//Magnus
Tom Lane wrote:
Magnus Hagander <magnus@hagander.net> writes:
(I don't believe OpenSSL does this verification either, because AFAICS
OpenSSL only ever sees the IP address of the server, and not the FQDN)In common usages libpq doesn't have the FQDN of the server either.
To impose such a requirement, we'd have to forbid naming the server
by IP address or via a domain-search-path abbreviation.regards, tom lane
Well, right now, SSL does nothing for you, so you have to do something.
It's OK, SSL isn't doing a lot for a lot of people, but this is the
beginning of us calling people out on that.
You can handle IP address and domain-search-path by having an option for
explicitly declaring the subject name to be expected at the other side
of the SSL connection. In other words, sever the DNS/FQDN link, and
just explicitly say "however I reach that host over there, I expect
database.backend.com".
--Dan
Dan Kaminsky wrote:
Tom Lane wrote:
Magnus Hagander <magnus@hagander.net> writes:
(I don't believe OpenSSL does this verification either, because AFAICS
OpenSSL only ever sees the IP address of the server, and not the FQDN)In common usages libpq doesn't have the FQDN of the server either.
To impose such a requirement, we'd have to forbid naming the server
by IP address or via a domain-search-path abbreviation.regards, tom lane
Well, right now, SSL does nothing for you, so you have to do something.
It's OK, SSL isn't doing a lot for a lot of people, but this is the
beginning of us calling people out on that.
Do feel free to explain how it "does nothing" for you with properly set
up certificates (see my previous email). (I'm still not saying it cannot
be significantly improved, of course)
You can handle IP address and domain-search-path by having an option for
explicitly declaring the subject name to be expected at the other side
of the SSL connection. In other words, sever the DNS/FQDN link, and
just explicitly say "however I reach that host over there, I expect
database.backend.com".
You can do this today. If you are willing to do it in the application,
just verify the certificate DN and you're done.
Yes, it would certainly be a lot better to do the validation earlier in
the chain (if you're sending plaintext password, you'll end up sending
the password before you do the validation. But I don't think you even
can do that in current versions), and if it was slightly easier to do,
but you can certainly validate the cert if you want to.
//Magnus
Well, right now, SSL does nothing for you, so you have to do something.
It's OK, SSL isn't doing a lot for a lot of people, but this is the
beginning of us calling people out on that.Do feel free to explain how it "does nothing" for you with properly set
up certificates (see my previous email). (I'm still not saying it cannot
be significantly improved, of course)
If the only roots set up are private roots, it works great.
If there are generic roots (Verisign etc), or if no roots are checked at
all, it's useless.
Pretty simple.
You can handle IP address and domain-search-path by having an option for
explicitly declaring the subject name to be expected at the other side
of the SSL connection. In other words, sever the DNS/FQDN link, and
just explicitly say "however I reach that host over there, I expect
database.backend.com".You can do this today. If you are willing to do it in the application,
just verify the certificate DN and you're done.Yes, it would certainly be a lot better to do the validation earlier in
the chain (if you're sending plaintext password, you'll end up sending
the password before you do the validation. But I don't think you even
can do that in current versions), and if it was slightly easier to do,
but you can certainly validate the cert if you want to.//Magnus
See, I don't care *why* things are broken -- whether they're broken at
the application, at libpq, or at openssl, I'm asking the direct question
-- is SSL doing anything in common deployment, and if not, what needs to
be done to fix that?
Background: After the DNS flaw was found, I started looking around to
see if SSL was a legitimate protection. Everywhere I looked, I found
issues. It's pretty embarrassing to find out that even SSL VPN's aren't
checking certs. So, yeah, I'm looking to see what level of protection
is out there.
So, not caring *why* things are broken -- is it fair to say that libpq's
use of SSL didn't defend against the DNS bug, in any scenario except
where custom roots were set up?
--Dan
--Dan
Dan Kaminsky wrote:
Well, right now, SSL does nothing for you, so you have to do
something. It's OK, SSL isn't doing a lot for a lot of people, but
this is the
beginning of us calling people out on that.Do feel free to explain how it "does nothing" for you with properly set
up certificates (see my previous email). (I'm still not saying it cannot
be significantly improved, of course)If the only roots set up are private roots, it works great.
If there are generic roots (Verisign etc), or if no roots are checked at
all, it's useless.Pretty simple
Good, then we're in agreement that far.
(FWIW, I don't think I've ever seen a PostgreSQL server with a
certificate off a global root. I've seen plenty off a corporate root
though, which could in theory have similar issues - but at least you're
in control of your own problem in that case)
You can handle IP address and domain-search-path by having an option for
explicitly declaring the subject name to be expected at the other side
of the SSL connection. In other words, sever the DNS/FQDN link, and
just explicitly say "however I reach that host over there, I expect
database.backend.com".You can do this today. If you are willing to do it in the application,
just verify the certificate DN and you're done.Yes, it would certainly be a lot better to do the validation earlier in
the chain (if you're sending plaintext password, you'll end up sending
the password before you do the validation. But I don't think you even
can do that in current versions), and if it was slightly easier to do,
but you can certainly validate the cert if you want to.//Magnus
See, I don't care *why* things are broken -- whether they're broken at
the application, at libpq, or at openssl, I'm asking the direct question
-- is SSL doing anything in common deployment, and if not, what needs to
be done to fix that?Background: After the DNS flaw was found, I started looking around to
see if SSL was a legitimate protection. Everywhere I looked, I found
issues. It's pretty embarrassing to find out that even SSL VPN's aren't
checking certs. So, yeah, I'm looking to see what level of protection
is out there.So, not caring *why* things are broken -- is it fair to say that libpq's
use of SSL didn't defend against the DNS bug, in any scenario except
where custom roots were set up?
Yes, I think that's fair. You *can* do the verification yourself, but
libpq will not do it for you.
Only I will claim that the common deployment, as you refer to above,
*is* with a custom root. PostgreSQL server are *very* seldom "published
to the internet", and therefor tend not to use the global CA roots.
//Magnus
On Tue, Aug 19, 2008 at 02:57:55PM -0400, Tom Lane wrote:
To impose such a requirement, we'd have to forbid naming the server
by IP address or via a domain-search-path abbreviation.
If you ask me, the second idea at least is a good one anyway. In an
SSL context, search paths are a terrible idea. (Frankly, they're a
terrible idea outside that context also, but that ship sailed some
time ago.)
A
--
Andrew Sullivan
ajs@commandprompt.com
+1 503 667 4564 x104
http://www.commandprompt.com/
Good, then we're in agreement that far.
Cool!
(FWIW, I don't think I've ever seen a PostgreSQL server with a
certificate off a global root. I've seen plenty off a corporate root
though, which could in theory have similar issues - but at least you're
in control of your own problem in that case)
OK, now describe client behavior for me. Is the average client
configured to accept:
1) No roots (but still works for some unknown reason)
2) Explicitly configured corporate roots
3) Explicitly configured corporate roots, AND global roots
4) Global roots (but still works for some unknown reason)
Keep in mind that at least Debian distributes a ca-certificates package,
and I can't imagine they're alone.
Yes, I think that's fair. You *can* do the verification yourself, but
libpq will not do it for you.Only I will claim that the common deployment, as you refer to above,
*is* with a custom root. PostgreSQL server are *very* seldom "published
to the internet", and therefor tend not to use the global CA roots.
So one of the nastier aspects of the DNS bug is that internal
communication may get routed out to the Internet, because it's DNS that
keeps things behind the firewall. If SSL is being used, the
*presumption* is that there's a MITM we want to defend against.