Re: postgres_fdw, dblink, and CREATE SUBSCRIPTION security

2023-04-12 Thread Jacob Champion
On 3/30/23 11:13, Stephen Frost wrote:
>> Okay, but this is walking back from the network example you just
>> described upthread. Do you still consider that in scope, or...?
> 
> The concern around the network certainly needs to be in-scope overall.

Sounds good!

> Who are we trusting with what?  In particular, I'd argue that the user
> who is able to install the postgres_fdw extension and the user who is
> able to issue the CREATE SERVER are largely trusted; at least in so far
> as the user doing CREATE SERVER is allowed to create the server and
> through that allowed to make outbound connections from the Proxy.
> 
> Therefore, the Proxy is configured with postgres_fdw and with a trusted
> user performing the CREATE SERVER.
> 
> What doesn't this handle today?  Connection side-effects are one
> problem- once the CREATE SERVER is done, any user with USAGE rights on
> the server can create a USER MAPPING for themselves, either with a
> password or without one (if they're able to proxy GSS credentials to the
> system).  They aren't able to set password_required though, which
> defaults to true.  However, without having require_auth set, they're
> able to cause the Proxy to reach an authentication stage with the Target
> that might not match what credentials they're supposed to be providing.
> 
> We attempt to address this by checking post-auth to Target that we used
> the credentials to connect that we expected to- if GSS credentials were
> proxied, then we expect to use those.  If a password was provided then
> we expect to use a password to auth (only checked after we see if GSS
> credentials were proxied and used).  The issue here is 'post-auth' bit,
> we'd prefer to fail the connection pre-auth if it isn't what we're
> expecting.

Right. Keep in mind that require_auth is post-auth, though; it can't fix
that issue, so it doesn't fix any connection side-effect problems at all.

> Should we then explicit set require_auth=gss when GSS
> credentials are proxied?  Also, if a password is provided, then
> explicitly set require_auth=scram-sha-256?  Or default to these, at
> least, and allow the CREATE SERVER user to override our choices?  Or
> should it be a USER MAPPING option that's restricted?  Or not?
IMO, yes -- whatever credentials the proxy is forwarding from the user,
the proxy should be checking that the server has actually used them. The
person with the ability to create a USER MAPPING should probably not
have the ability to override that check.

>>> I think that what you're proposing is that B and C can just be allowed
>>> to proxy to A and A can say "hey, by the way, I'm just gonna let you
>>> in without asking for anything else" and B and C can, when proxying,
>>> react to that by disconnecting before the connection actually goes
>>> through. That's simpler, in a sense. It doesn't require us to set up
>>> the proxy configuration on B and C in a way that matches what
>>> pg_hba.conf allows on A. Instead, B and C can automatically deduce
>>> what connections they should refuse to proxy.
>>
>> Right. It's meant to take the "localhost/wraparound connection" out of a
>> class of special things we have to worry about, and make it completely
>> boring.
> 
> Again, trying to get at a more concrete example- the concern here is a
> user with CREATE SERVER ability could leverage that access to become a
> superuser if the system is configured with 'peer' access, right?

Or 'trust localhost', or 'ident [postgres user]', yes.

> A
> non-superuser is already prevented from being able to set
> "password_required=false", perhaps we shouldn't allow them to set
> "require_auth=none" (or have that effect) either?

I think that sounds reasonable.

> Perhaps the system
> should simply forcibly set require_auth based on the credentials
> provided in the USER MAPPING or on the connection and have require_auth
> otherwise restricted to superuser (who could override it if they'd
> really like to)?  Perhaps if password_required=false we implicitly
> un-set require_auth, to avoid having to make superusers change their
> existing configurations where they've clearly already accepted that
> credential-less connections are allowed.

Mm, I think I like the first idea better. If you've set a password,
wouldn't you like to know if the server ignored it? If password_required
is false, *and* you don't have a password, then we can drop require_auth
without issue.

> Automatically setting require_auth and restricting the ability of it to
> be set on user mappings to superusers doesn't strike me as terribly
> difficult to do and seems like it'd prevent this concern.
> 
> Just to make sure I'm following- Robert's up-thread suggestion of an
> 'outbound pg_hba' would be an additional restriction when it comes to
> what a user who can use CREATE SERVER is allowed to do?

Yes. That can provide additional safety in the case where you really
need to take the require_auth checks away for whatever reason. I think
it's just a good in-depth 

Re: postgres_fdw, dblink, and CREATE SUBSCRIPTION security

2023-04-12 Thread Jacob Champion
On 3/30/23 05:58, Robert Haas wrote:
> On Fri, Mar 24, 2023 at 5:47 PM Jacob Champion  
> wrote:
>> Okay, but this is walking back from the network example you just
>> described upthread. Do you still consider that in scope, or...?
> 
> Sorry, I don't know which example you mean.

The symmetrical proxy situation you described, where all the proxies are
mutually trusting. While it's easier to secure that setup than the
asymmetrical ones, it's also not a localhost-only situation anymore, and
the moment you open up to other machines is where I think your
characterization runs into trouble.

> I guess I wouldn't have a problem blaming the DBA here, but you seem
> to be telling me that the security literature has settled on another
> kind of approach, and I'm not in a position to dispute that. It still
> feels weird to me, though.

If it helps, [1] is a paper that helped me wrap my head around some of
it. It's focused on capability systems and an academic audience, but the
"Avoiding Confused Deputy Problems" section starting on page 11 is a
good place to jump to for the purposes of this discussion.

--Jacob

[1] https://srl.cs.jhu.edu/pubs/SRL2003-02.pdf




Re: postgres_fdw, dblink, and CREATE SUBSCRIPTION security

2023-03-30 Thread Stephen Frost
Greetings,

* Jacob Champion (jchamp...@timescale.com) wrote:
> On 3/20/23 09:32, Robert Haas wrote:
> > I think this is the root of our disagreement.
> 
> Agreed.

I've read all the way back to the $SUBJECT change to try and get an
understanding of the questions here and it's not been easy, in part, I
think, due to the verbiage but also the perhaps lack of concrete
examples and instead references to other systems and protocols.

> > My understanding of the
> > previous discussion is that people think that the major problem here
> > is the wraparound-to-superuser attack. That is, in general, we expect
> > that when we connect to a database over the network, we expect it to
> > do some kind of active authentication, like asking us for a password,
> > or asking us for an SSL certificate that isn't just lying around for
> > anyone to use. However, in the specific case of a local connection, we
> > have a reliable way of knowing who the remote user is without any kind
> > of active authentication, namely 'peer' authentication or perhaps even
> > 'trust' if we trust all the local users, and so we don't judge it
> > unreasonable to allow local connections without any form of active
> > authentication. There can be some scenarios where even over a network
> > we can know the identity of the person connecting with complete
> > certainty, e.g. if endpoints are locked down such that the source IP
> > address is a reliable indicator of who is initiating the connection,
> > but in general when there's a network involved you don't know who the
> > person making the connection is and need to do something extra to
> > figure it out.
> 
> Okay, but this is walking back from the network example you just
> described upthread. Do you still consider that in scope, or...?

The concern around the network certainly needs to be in-scope overall.

> > If you accept this characterization of the problem,
> 
> I'm not going to say yes or no just yet, because I don't understand your
> rationale for where to draw the lines.
> 
> If you just want the bare minimum thing that will solve the localhost
> case, require_auth landed this week. Login triggers are not yet a thing,
> so `require_auth=password,md5,scram-sha-256` ensures active
> authentication. You don't even have to disallow localhost connections,
> as far as I can tell; they'll work as intended.

I do think require_auth helps us move in a positive direction.  As I
mentioned elsewhere, I don't think we highlight it nearly enough in the
postgres_fdw documentation.  Let's look at that in a bit more depth with
concrete examples and perhaps everyone will be able to get a bit more
understanding of the issues.

Client is psql
Proxy is some PG server that's got postgres_fdw
Target is another PG server, that is being connected to from Proxy
Authentication is via GSS/Kerberos with proxied credentials

What do we want to require the user to configure to make this secure?

Proxy's pg_hba configured to require GSS auth from Client.
Target's pg_hba configured to require GSS auth from Proxy.

Who are we trusting with what?  In particular, I'd argue that the user
who is able to install the postgres_fdw extension and the user who is
able to issue the CREATE SERVER are largely trusted; at least in so far
as the user doing CREATE SERVER is allowed to create the server and
through that allowed to make outbound connections from the Proxy.

Therefore, the Proxy is configured with postgres_fdw and with a trusted
user performing the CREATE SERVER.

What doesn't this handle today?  Connection side-effects are one
problem- once the CREATE SERVER is done, any user with USAGE rights on
the server can create a USER MAPPING for themselves, either with a
password or without one (if they're able to proxy GSS credentials to the
system).  They aren't able to set password_required though, which
defaults to true.  However, without having require_auth set, they're
able to cause the Proxy to reach an authentication stage with the Target
that might not match what credentials they're supposed to be providing.

We attempt to address this by checking post-auth to Target that we used
the credentials to connect that we expected to- if GSS credentials were
proxied, then we expect to use those.  If a password was provided then
we expect to use a password to auth (only checked after we see if GSS
credentials were proxied and used).  The issue here is 'post-auth' bit,
we'd prefer to fail the connection pre-auth if it isn't what we're
expecting.  Should we then explicit set require_auth=gss when GSS
credentials are proxied?  Also, if a password is provided, then
explicitly set require_auth=scram-sha-256?  Or default to these, at
least, and allow the CREATE SERVER user to override our choices?  Or
should it be a USER MAPPING option that's restricted?  Or not?

> > I think that what you're proposing is that B and C can just be allowed
> > to proxy to A and A can say "hey, by the way, I'm just gonna let you
> > in without asking 

Re: postgres_fdw, dblink, and CREATE SUBSCRIPTION security

2023-03-30 Thread Robert Haas
On Fri, Mar 24, 2023 at 5:47 PM Jacob Champion  wrote:
> Okay, but this is walking back from the network example you just
> described upthread. Do you still consider that in scope, or...?

Sorry, I don't know which example you mean.

> > If machines B and C aren't under our control such that we can
> > configure them that way, then the configuration is fundamentally
> > insecure in a way that we can't really fix.
>
> Here's probably our biggest point of contention. You're unlikely to
> convince me that this is the DBA's fault.
>
> If machines B and C aren't under our control, then our *protocol* is
> fundamentally insecure in a way that we have the ability to fix, in a
> way that's already been characterized in security literature.

I guess I wouldn't have a problem blaming the DBA here, but you seem
to be telling me that the security literature has settled on another
kind of approach, and I'm not in a position to dispute that. It still
feels weird to me, though.

-- 
Robert Haas
EDB: http://www.enterprisedb.com




Re: postgres_fdw, dblink, and CREATE SUBSCRIPTION security

2023-03-24 Thread Jacob Champion
On 3/20/23 09:32, Robert Haas wrote:
> I think this is the root of our disagreement.

Agreed.

> My understanding of the
> previous discussion is that people think that the major problem here
> is the wraparound-to-superuser attack. That is, in general, we expect
> that when we connect to a database over the network, we expect it to
> do some kind of active authentication, like asking us for a password,
> or asking us for an SSL certificate that isn't just lying around for
> anyone to use. However, in the specific case of a local connection, we
> have a reliable way of knowing who the remote user is without any kind
> of active authentication, namely 'peer' authentication or perhaps even
> 'trust' if we trust all the local users, and so we don't judge it
> unreasonable to allow local connections without any form of active
> authentication. There can be some scenarios where even over a network
> we can know the identity of the person connecting with complete
> certainty, e.g. if endpoints are locked down such that the source IP
> address is a reliable indicator of who is initiating the connection,
> but in general when there's a network involved you don't know who the
> person making the connection is and need to do something extra to
> figure it out.

Okay, but this is walking back from the network example you just
described upthread. Do you still consider that in scope, or...?

> If you accept this characterization of the problem,

I'm not going to say yes or no just yet, because I don't understand your
rationale for where to draw the lines.

If you just want the bare minimum thing that will solve the localhost
case, require_auth landed this week. Login triggers are not yet a thing,
so `require_auth=password,md5,scram-sha-256` ensures active
authentication. You don't even have to disallow localhost connections,
as far as I can tell; they'll work as intended.

If you think login triggers will get in for PG16, my bigger proposal
can't help in time. But if you're drawing the line at "environmental
HBAs are fundamentally unsafe and you shouldn't use them if you have a
proxy," why can't I instead draw the line at "login triggers are
fundamentally unsafe and you shouldn't use them if you have a proxy"?

And if you want to handle the across-the-network case, too, then I don't
accept the characterization of the problem.

> then I don't think
> the oracle is that hard to design. We simply set it up not to allow
> wraparound connections, or maybe even more narrowly to not allow
> wraparound connections to superuser. If the DBA has some weird network
> topology where that's not the correct rule, either because they want
> to allow wraparound connections or they want to disallow other things,
> then yeah they have to tell us what to allow, but I don't really see
> why that's an unreasonable expectation.

This seems like a security model that has been carefully gerrymandered
around the existing implementation. My argument is that the "weird
network topology" isn't weird at all, and it's only dangerous because of
decisions we made (and can unmake).

I feel pretty strongly that the design arrow needs to be pointed in the
opposite direction. The model needs to be chosen first, to prevent us
from saying, "We defend against whatever the implementation lets us
defend against today. Good luck, DBAs."

> If machines B and C aren't under our control such that we can
> configure them that way, then the configuration is fundamentally
> insecure in a way that we can't really fix.

Here's probably our biggest point of contention. You're unlikely to
convince me that this is the DBA's fault.

If machines B and C aren't under our control, then our *protocol* is
fundamentally insecure in a way that we have the ability to fix, in a
way that's already been characterized in security literature.

> I think that what you're proposing is that B and C can just be allowed
> to proxy to A and A can say "hey, by the way, I'm just gonna let you
> in without asking for anything else" and B and C can, when proxying,
> react to that by disconnecting before the connection actually goes
> through. That's simpler, in a sense. It doesn't require us to set up
> the proxy configuration on B and C in a way that matches what
> pg_hba.conf allows on A. Instead, B and C can automatically deduce
> what connections they should refuse to proxy.

Right. It's meant to take the "localhost/wraparound connection" out of a
class of special things we have to worry about, and make it completely
boring.

> I guess that's nice, but
> it feels pretty magical to me. It encourages the DBA not to think
> about what B and C should actually be allowed to proxy, and instead
> just trust that the automatics are going to prevent any security
> disasters.

I agree magical behavior is dangerous, if what you think it can do
doesn't match up with what it can actually do. Bugs are always possible,
and maybe I'm just not seeing a corner case yet, because I'm talking too
much and not 

Re: postgres_fdw, dblink, and CREATE SUBSCRIPTION security

2023-03-20 Thread Robert Haas
On Fri, Mar 10, 2023 at 7:00 PM Jacob Champion  wrote:
> On Thu, Mar 9, 2023 at 6:17 AM Robert Haas  wrote:
> > That seems like a circular argument. If you call the problem the
> > confused deputy problem then the issue must indeed be that the deputy
> > is confused, and needs to talk to someone else to get un-confused. But
> > why is the deputy necessarily confused in the first place? Our deputy
> > is confused because our code to decide whether to proxy a connection
> > or not is super-dumb,
>
> No, I think our proxy is confused because it doesn't know what power
> it has, and it can't tell the server what power it wants to use. That
> problem is independent of the decision to proxy. You're suggesting
> strengthening the code that makes that decision -- adding an oracle
> (in the form of a DBA) that knows about the confusion and actively
> mitigates it. That's guaranteed to work if the oracle is perfect,
> because "perfect" is somewhat tautologically defined as "whatever
> ensures secure operation". But the oracle doesn't reduce the
> confusion, and DBAs aren't perfect.

I think this is the root of our disagreement. My understanding of the
previous discussion is that people think that the major problem here
is the wraparound-to-superuser attack. That is, in general, we expect
that when we connect to a database over the network, we expect it to
do some kind of active authentication, like asking us for a password,
or asking us for an SSL certificate that isn't just lying around for
anyone to use. However, in the specific case of a local connection, we
have a reliable way of knowing who the remote user is without any kind
of active authentication, namely 'peer' authentication or perhaps even
'trust' if we trust all the local users, and so we don't judge it
unreasonable to allow local connections without any form of active
authentication. There can be some scenarios where even over a network
we can know the identity of the person connecting with complete
certainty, e.g. if endpoints are locked down such that the source IP
address is a reliable indicator of who is initiating the connection,
but in general when there's a network involved you don't know who the
person making the connection is and need to do something extra to
figure it out.

If you accept this characterization of the problem, then I don't think
the oracle is that hard to design. We simply set it up not to allow
wraparound connections, or maybe even more narrowly to not allow
wraparound connections to superuser. If the DBA has some weird network
topology where that's not the correct rule, either because they want
to allow wraparound connections or they want to disallow other things,
then yeah they have to tell us what to allow, but I don't really see
why that's an unreasonable expectation. I'd expect the correct
configuration of the proxy facility to fall naturally out of what's
allowed in pg_hba.conf. If machine A is configured to accept
connections from machines B and C based on environmental factors, then
machines B and C should be configured not to proxy connections to A.
If machines B and C aren't under our control such that we can
configure them that way, then the configuration is fundamentally
insecure in a way that we can't really fix.

I think that what you're proposing is that B and C can just be allowed
to proxy to A and A can say "hey, by the way, I'm just gonna let you
in without asking for anything else" and B and C can, when proxying,
react to that by disconnecting before the connection actually goes
through. That's simpler, in a sense. It doesn't require us to set up
the proxy configuration on B and C in a way that matches what
pg_hba.conf allows on A. Instead, B and C can automatically deduce
what connections they should refuse to proxy. I guess that's nice, but
it feels pretty magical to me. It encourages the DBA not to think
about what B and C should actually be allowed to proxy, and instead
just trust that the automatics are going to prevent any security
disasters. I'm not sure that they always will, and I fear cultivating
too much reliance on them. I think that if you're setting up a network
topology where the correct rule is something more complex than "don't
allow wraparound connections to superuser," maybe you ought to be
forced to spell that rule out instead of letting the system deduce one
that you hope will be right.

-- 
Robert Haas
EDB: http://www.enterprisedb.com




Re: postgres_fdw, dblink, and CREATE SUBSCRIPTION security

2023-03-10 Thread Jacob Champion
On Thu, Mar 9, 2023 at 6:17 AM Robert Haas  wrote:
> That seems like a circular argument. If you call the problem the
> confused deputy problem then the issue must indeed be that the deputy
> is confused, and needs to talk to someone else to get un-confused. But
> why is the deputy necessarily confused in the first place? Our deputy
> is confused because our code to decide whether to proxy a connection
> or not is super-dumb,

No, I think our proxy is confused because it doesn't know what power
it has, and it can't tell the server what power it wants to use. That
problem is independent of the decision to proxy. You're suggesting
strengthening the code that makes that decision -- adding an oracle
(in the form of a DBA) that knows about the confusion and actively
mitigates it. That's guaranteed to work if the oracle is perfect,
because "perfect" is somewhat tautologically defined as "whatever
ensures secure operation". But the oracle doesn't reduce the
confusion, and DBAs aren't perfect.

If you want to add a Sheriff Andy to hold Barney Fife's hand [1], that
will absolutely make Barney less of a problem, and I'd like to have
Andy around regardless. But Barney still doesn't know what's going on,
and when Andy makes a mistake, there will still be trouble. I'd like
to teach Barney some useful stuff.

> but if there's an intrinsic reason it can't be
> smarter, I don't understand what it is.

Well... I'm not well-versed enough in this to prove non-existence of a
solution. Can you find a solution, using the current protocol, that
doesn't make use of perfect out-of-band knowledge? We have a client
that will authenticate using any method the server asks it to, even if
its user intended to use something else. And we have a server that can
eagerly skip client authentication, and then eagerly run code on its
behalf, without first asking the client what it's even trying to do.
That would be an inherently hostile environment for *any* proxy, not
just ours.

Thanks,
--Jacob

[1] https://en.wikipedia.org/wiki/The_Andy_Griffith_Show#Premise_and_characters




Re: postgres_fdw, dblink, and CREATE SUBSCRIPTION security

2023-03-09 Thread Robert Haas
On Wed, Mar 8, 2023 at 5:44 PM Jacob Champion  wrote:
> Sure. I don't see a way for the proxy to figure that out by itself,
> though, going back to my asymmetry argument from before. Only the
> server truly knows, at time of HBA processing, whether the proxy
> itself has authority. If the proxy knew, it wouldn't be confused.

That seems like a circular argument. If you call the problem the
confused deputy problem then the issue must indeed be that the deputy
is confused, and needs to talk to someone else to get un-confused. But
why is the deputy necessarily confused in the first place? Our deputy
is confused because our code to decide whether to proxy a connection
or not is super-dumb, but if there's an intrinsic reason it can't be
smarter, I don't understand what it is.

-- 
Robert Haas
EDB: http://www.enterprisedb.com




Re: postgres_fdw, dblink, and CREATE SUBSCRIPTION security

2023-03-09 Thread Robert Haas
On Wed, Mar 8, 2023 at 5:44 PM Jacob Champion  wrote:
>
> On Wed, Mar 8, 2023 at 11:40 AM Robert Haas  wrote:
> > On Wed, Mar 8, 2023 at 2:30 PM Jacob Champion  
> > wrote:
> > > I don't think I necessarily like that option better than SASL-style,
> > > but hopefully that clarifies it somewhat?
> >
> > Hmm, yeah, I guess that's OK.
>
> Okay, cool.
>
> > I still don't love it, though. It feels
> > more solid to me if the proxy can actually block the connections
> > before they even happen, without having to rely on a server
> > interaction to figure out what is permissible.
>
> Sure. I don't see a way for the proxy to figure that out by itself,
> though, going back to my asymmetry argument from before. Only the
> server truly knows, at time of HBA processing, whether the proxy
> itself has authority. If the proxy knew, it wouldn't be confused.
>
> > I don't know what you mean by SASL-style, exactly.
>
> That's the one where the server explicitly names all forms of
> authentication, including the ambient ones (ANONYMOUS, EXTERNAL,
> etc.), and requires the client to choose one before running any
> actions on their behalf. That lets the require_auth machinery work for
> this case, too.
>
> --Jacob



-- 
Robert Haas
EDB: http://www.enterprisedb.com




Re: postgres_fdw, dblink, and CREATE SUBSCRIPTION security

2023-03-08 Thread Jacob Champion
On Wed, Mar 8, 2023 at 11:40 AM Robert Haas  wrote:
> On Wed, Mar 8, 2023 at 2:30 PM Jacob Champion  wrote:
> > I don't think I necessarily like that option better than SASL-style,
> > but hopefully that clarifies it somewhat?
>
> Hmm, yeah, I guess that's OK.

Okay, cool.

> I still don't love it, though. It feels
> more solid to me if the proxy can actually block the connections
> before they even happen, without having to rely on a server
> interaction to figure out what is permissible.

Sure. I don't see a way for the proxy to figure that out by itself,
though, going back to my asymmetry argument from before. Only the
server truly knows, at time of HBA processing, whether the proxy
itself has authority. If the proxy knew, it wouldn't be confused.

> I don't know what you mean by SASL-style, exactly.

That's the one where the server explicitly names all forms of
authentication, including the ambient ones (ANONYMOUS, EXTERNAL,
etc.), and requires the client to choose one before running any
actions on their behalf. That lets the require_auth machinery work for
this case, too.

--Jacob




Re: postgres_fdw, dblink, and CREATE SUBSCRIPTION security

2023-03-08 Thread Robert Haas
On Wed, Mar 8, 2023 at 2:30 PM Jacob Champion  wrote:
> > No, that's the opposite, and exactly the point I'm trying to make. In
> > that case, the SERVER says what it's willing to accept, and the CLIENT
> > decides whether or not to provide that. In your proposal, the client
> > tells the server which authentication methods to accept.
>
> Ah, that's a (the?) sticking point. In my example, the client doesn't
> tell the server which methods to accept. The client tells the server
> which method the *client* has the ability to use. (Or, implicitly,
> which methods it refuses to use.)
>
> That shouldn't lose any power, security-wise, because the server is
> looking for an intersection of the two sets. And the client already
> has the power to do that for almost every form of authentication,
> except the ambient methods.
>
> I don't think I necessarily like that option better than SASL-style,
> but hopefully that clarifies it somewhat?

Hmm, yeah, I guess that's OK. I still don't love it, though. It feels
more solid to me if the proxy can actually block the connections
before they even happen, without having to rely on a server
interaction to figure out what is permissible.

I don't know what you mean by SASL-style, exactly.

-- 
Robert Haas
EDB: http://www.enterprisedb.com




Re: postgres_fdw, dblink, and CREATE SUBSCRIPTION security

2023-03-08 Thread Jacob Champion
On Tue, Mar 7, 2023 at 11:04 AM Robert Haas  wrote:
>
> On Thu, Feb 9, 2023 at 4:46 PM Jacob Champion  wrote:
> > On 2/6/23 08:22, Robert Haas wrote:
> > > I don't think that's quite the right concept. It seems to me that the
> > > client is responsible for informing the server of what the situation
> > > is, and the server is responsible for deciding whether to allow the
> > > connection. In your scenario, the client is not only communicating
> > > information ("here's the password I have got") but also making demands
> > > on the server ("DO NOT authenticate using anything else"). I like the
> > > first part fine, but not the second part.
> >
> > For what it's worth, making a negative demand during authentication is
> > pretty standard: if you visit example.com and it tells you "I need your
> > OS login password and Social Security Number to authenticate you," you
> > have the option of saying "no thanks" and closing the tab.
>
> No, that's the opposite, and exactly the point I'm trying to make. In
> that case, the SERVER says what it's willing to accept, and the CLIENT
> decides whether or not to provide that. In your proposal, the client
> tells the server which authentication methods to accept.

Ah, that's a (the?) sticking point. In my example, the client doesn't
tell the server which methods to accept. The client tells the server
which method the *client* has the ability to use. (Or, implicitly,
which methods it refuses to use.)

That shouldn't lose any power, security-wise, because the server is
looking for an intersection of the two sets. And the client already
has the power to do that for almost every form of authentication,
except the ambient methods.

I don't think I necessarily like that option better than SASL-style,
but hopefully that clarifies it somewhat?

> I don't think we're really very far apart here, but for some reason
> the terminology seems to be giving us some trouble.

Agreed.

> Of course, there's
> also the small problem of actually finding the time to do some
> meaningful work on this stuff, rather than just talking

Agreed :)

--Jacob




Re: postgres_fdw, dblink, and CREATE SUBSCRIPTION security

2023-03-07 Thread Robert Haas
On Thu, Feb 9, 2023 at 4:46 PM Jacob Champion  wrote:
> On 2/6/23 08:22, Robert Haas wrote:
> > I don't think that's quite the right concept. It seems to me that the
> > client is responsible for informing the server of what the situation
> > is, and the server is responsible for deciding whether to allow the
> > connection. In your scenario, the client is not only communicating
> > information ("here's the password I have got") but also making demands
> > on the server ("DO NOT authenticate using anything else"). I like the
> > first part fine, but not the second part.
>
> For what it's worth, making a negative demand during authentication is
> pretty standard: if you visit example.com and it tells you "I need your
> OS login password and Social Security Number to authenticate you," you
> have the option of saying "no thanks" and closing the tab.

No, that's the opposite, and exactly the point I'm trying to make. In
that case, the SERVER says what it's willing to accept, and the CLIENT
decides whether or not to provide that. In your proposal, the client
tells the server which authentication methods to accept.

> In a hypothetical world where the server presented the client with a
> list of authentication options before allowing any access, this would
> maybe be a little less convoluted to solve. For example, a proxy seeing
> a SASL list of
>
> - ANONYMOUS
> - EXTERNAL
>
> could understand that both methods allow the client to assume the
> authority of the proxy itself. So if its client isn't allowed to do
> that, the proxy realizes something is wrong (either it, or its target
> server, has been misconfigured or is under attack), and it can close the
> connection *before* the server runs login triggers.

Yep, that totally makes sense to me, but I don't think it's what you proposed.

> This sounds like a reasonable separation of responsibilities on the
> surface, but I think it's subtly off. The entire confused-deputy problem
> space revolves around the proxy being unable to correctly decide which
> connections to allow unless it also knows why the connections are being
> authorized.

I agree.

> You've constructed an example where that's not a concern: everything's
> symmetrical, all proxies operate with the same authority, and internal
> users are identical to external users. But the CVE that led to the
> password requirement, as far as I can tell, dealt with asymmetry. The
> proxy had the authority to connect locally to a user, and the clients
> had the authority to connect to other machines' users, but those users
> weren't the same and were not mutually trusting.

Yeah, agreed. So, I think the point here is that the proxy
configuration (and pg_hba.conf) need to be sufficiently powerful that
each user can permit the things that make sense in their environment
and block the things that don't.

I don't think we're really very far apart here, but for some reason
the terminology seems to be giving us some trouble. Of course, there's
also the small problem of actually finding the time to do some
meaningful work on this stuff, rather than just talking

-- 
Robert Haas
EDB: http://www.enterprisedb.com




Re: postgres_fdw, dblink, and CREATE SUBSCRIPTION security

2023-02-09 Thread Jacob Champion
On 2/6/23 08:22, Robert Haas wrote:
> I don't think that's quite the right concept. It seems to me that the
> client is responsible for informing the server of what the situation
> is, and the server is responsible for deciding whether to allow the
> connection. In your scenario, the client is not only communicating
> information ("here's the password I have got") but also making demands
> on the server ("DO NOT authenticate using anything else"). I like the
> first part fine, but not the second part.

For what it's worth, making a negative demand during authentication is
pretty standard: if you visit example.com and it tells you "I need your
OS login password and Social Security Number to authenticate you," you
have the option of saying "no thanks" and closing the tab.

It's not really about protecting the server at that point; the server
can protect itself. It's about protecting *you*. Allowing the proxy to
pin a specific set of authentication details to the connection is just a
way for it to close the tab on a server that would otherwise pull some
other piece of ambient authority out of it.

In a hypothetical world where the server presented the client with a
list of authentication options before allowing any access, this would
maybe be a little less convoluted to solve. For example, a proxy seeing
a SASL list of

- ANONYMOUS
- EXTERNAL

could understand that both methods allow the client to assume the
authority of the proxy itself. So if its client isn't allowed to do
that, the proxy realizes something is wrong (either it, or its target
server, has been misconfigured or is under attack), and it can close the
connection *before* the server runs login triggers.

> In this kind of scenario, the client has no business
> demanding that the server authenticate using the password rather than
> anything else. The server, not the client, is in charge of deciding
> which connections to accept; the client's job is only to decide which
> connections to proxy.

This sounds like a reasonable separation of responsibilities on the
surface, but I think it's subtly off. The entire confused-deputy problem
space revolves around the proxy being unable to correctly decide which
connections to allow unless it also knows why the connections are being
authorized.

You've constructed an example where that's not a concern: everything's
symmetrical, all proxies operate with the same authority, and internal
users are identical to external users. But the CVE that led to the
password requirement, as far as I can tell, dealt with asymmetry. The
proxy had the authority to connect locally to a user, and the clients
had the authority to connect to other machines' users, but those users
weren't the same and were not mutually trusting.

> And the human being is responsible for making
> sure that the combination of those two things implements the intended
> security policy.

Sure, but upthread it was illustrated how difficult it is for even the
people implementing the protocol to reason through what's safe and
what's not.

The primitives we're providing in the protocol are, IMO, difficult to
wield safely for more complex use cases. We can provide mitigations, and
demand that the DBA reason through every combination, and tell them
"don't do that" when they screw up or come across a situation that our
mitigations can't paper over. But I think we can solve the root problem
instead.

> We
> could do something that looks more like a series of if-then rules,
> e.g.
> 
> target-host 127.0.0.0/8 => reject
> authentication-method scram => accept
> reject

Yeah, I think something based on allow/deny is going to be the most
intuitive.

> But it's only a hop, skip and a jump from there to something that
> looks an awful lot like a full-blown programing language, and maybe
> that's even the right idea, but, oh, the bike-shedding!

Eh. Someone will demand Turing-completeness eventually, but you don't
have to listen. :D

--Jacob




Re: postgres_fdw, dblink, and CREATE SUBSCRIPTION security

2023-02-06 Thread Robert Haas
On Wed, Feb 1, 2023 at 3:37 PM Jacob Champion  wrote:
> > I'm not an expert on this stuff, but to me that feels like a weak and
> > fuzzy concept. If the client is going to tell the server something,
> > I'd much rather have it say something like "i'm proxying a request
> > from my local user rhaas, who authenticated using such and such a
> > method and connected from such and such an IP yadda yadda". That feels
> > to me like really clear communication that the server can then be
> > configured to something about via pg_hba.conf or similar. Saying "use
> > in-band authentication only", to me, feels much murkier. As the
> > recipient of that message, I don't know exactly what to do about it,
> > and it feels like whatever heuristic I adopt might end up being wrong
> > and something bad happens anyway.
>
> Is it maybe just a matter of terminology? If a proxy tells the server,
> "This user is logging in. Here's the password I have for them. DO NOT
> authenticate using anything else," and the HBA says to use ident auth
> for that user, then the server fails the connection. That's what I
> mean by in-band -- the proxy says, "here are the credentials for this
> connection." That's it.

I don't think that's quite the right concept. It seems to me that the
client is responsible for informing the server of what the situation
is, and the server is responsible for deciding whether to allow the
connection. In your scenario, the client is not only communicating
information ("here's the password I have got") but also making demands
on the server ("DO NOT authenticate using anything else"). I like the
first part fine, but not the second part.

Consider the scenario where somebody wants to allow a connection that
is proxied and does not require a password. For example, maybe I have
a group of three machines that all mutually trust each other and the
network is locked down so that we need not worry about IP spoofing or
whatever. Just be doubly sure, they all have SSL certificates so that
they can verify that an incoming connection is from one of the other
trusted machines. I, as the administrator, want to configure things so
that each machine will proxy connections to the others as long as
local user = remote user. When the remote machine receives the
connection, it can trust that the request is legitimate provided that
the SSL certificate is successfully verified.

The way I think this should work is, first, on each machine, in the
proxy configuration, there should be a rule that says "only proxy
connections where local user = remote user" (and any other rules I
want to enforce). Second, in the HBA configuration, there should be a
rule that says "if somebody is trying to proxy a connection, it has to
be for one of these IPs and they have to authenticate using an SSL
certificate". In this kind of scenario, the client has no business
demanding that the server authenticate using the password rather than
anything else. The server, not the client, is in charge of deciding
which connections to accept; the client's job is only to decide which
connections to proxy. And the human being is responsible for making
sure that the combination of those two things implements the intended
security policy.

> Agreed. The danger from my end is, I'm trained on configuration
> formats that have infinite bells and whistles. I don't really want to
> go too crazy with it.

Yeah. If I remember my math well enough, the time required to
implement infinite bells and whistles will also be infinite, and as a
wise man once said, real artists ship.

It does seem like a good idea, if we can, to make the configuration
file format flexible enough that we can easily extend it with more
bells and whistles later if we so choose. But realistically most
people are going to have very simple configurations.

> > and that maybe
> > has something in common with our existing configuration file syntaxes.
> > But if we have to invent something new, then we can do that.
>
> Okay. Personally I'd like
> - the ability to set options globally (so filters are optional)
> - the ability to maintain many options for a specific scope (host? IP
> range?) without making my config lines grow without bound
> - the ability to audit a configuration without trusting its comments
>
> But getting all of my wishlist into a sane configuration format that
> handles all the use cases is the tricky part. I'll think about it.

Nobody seemed too keen on my proposal of a bunch of tab-separated
fields; maybe we're all traumatized from pg_hba.conf and should look
for something more complex with a real parser. I thought that
tab-separated fields might be good enough and simple to implement, but
it doesn't matter how simple it is to implement if nobody likes it. We
could do something that looks more like a series of if-then rules,
e.g.

target-host 127.0.0.0/8 => reject
authentication-method scram => accept
reject

But it's only a hop, skip and a jump from there to something that
looks an awful 

Re: postgres_fdw, dblink, and CREATE SUBSCRIPTION security

2023-02-01 Thread Jacob Champion
On Mon, Jan 30, 2023 at 2:21 PM Robert Haas  wrote:
> On Mon, Jan 30, 2023 at 4:12 PM Jacob Champion  
> wrote:
> > For our case, assuming that connections have side effects, one
> > solution could be for the client to signal to the server that the
> > connection should use in-band authentication only; i.e. fail the
> > connection if the credentials provided aren't good enough by
> > themselves to authenticate the client. (This has some overlap with
> > SASL negotiation, maybe.)
>
> I'm not an expert on this stuff, but to me that feels like a weak and
> fuzzy concept. If the client is going to tell the server something,
> I'd much rather have it say something like "i'm proxying a request
> from my local user rhaas, who authenticated using such and such a
> method and connected from such and such an IP yadda yadda". That feels
> to me like really clear communication that the server can then be
> configured to something about via pg_hba.conf or similar. Saying "use
> in-band authentication only", to me, feels much murkier. As the
> recipient of that message, I don't know exactly what to do about it,
> and it feels like whatever heuristic I adopt might end up being wrong
> and something bad happens anyway.

Is it maybe just a matter of terminology? If a proxy tells the server,
"This user is logging in. Here's the password I have for them. DO NOT
authenticate using anything else," and the HBA says to use ident auth
for that user, then the server fails the connection. That's what I
mean by in-band -- the proxy says, "here are the credentials for this
connection." That's it.

Alternatively, if you really don't like making this server-side: any
future "connection side effects" we add, such as logon triggers, could
either be opted into by the client or explicitly invoked by the client
after it's happy with the authentication exchange. Or it could be
disabled at the server side for forms of ambient authn. (This is
getting closer to HTTP's method safety concept.)

> > I agree. (But for the record, I think that an outbound proxy filter is
> > also insufficient. Someone, somewhere, is going to want to safely
> > proxy through localhost _and_ have peer authentication set up.)
>
> Well then they're indeed going to need some way to distinguish a
> proxied connection from a non-proxied one. You can't send identical
> connection requests in different scenarios and get different
> results

Yeah. Most of these solutions require explicitly labelling things that
were implicit before.

> I think what we really need here is an example or three of a proposed
> configuration file syntax. I think it would be good if we could pick a
> syntax that doesn't require a super-complicated parser

Agreed. The danger from my end is, I'm trained on configuration
formats that have infinite bells and whistles. I don't really want to
go too crazy with it.

> and that maybe
> has something in common with our existing configuration file syntaxes.
> But if we have to invent something new, then we can do that.

Okay. Personally I'd like
- the ability to set options globally (so filters are optional)
- the ability to maintain many options for a specific scope (host? IP
range?) without making my config lines grow without bound
- the ability to audit a configuration without trusting its comments

But getting all of my wishlist into a sane configuration format that
handles all the use cases is the tricky part. I'll think about it.

--Jacob




Re: postgres_fdw, dblink, and CREATE SUBSCRIPTION security

2023-01-30 Thread Robert Haas
On Mon, Jan 30, 2023 at 4:12 PM Jacob Champion  wrote:
> For our case, assuming that connections have side effects, one
> solution could be for the client to signal to the server that the
> connection should use in-band authentication only; i.e. fail the
> connection if the credentials provided aren't good enough by
> themselves to authenticate the client. (This has some overlap with
> SASL negotiation, maybe.)

I'm not an expert on this stuff, but to me that feels like a weak and
fuzzy concept. If the client is going to tell the server something,
I'd much rather have it say something like "i'm proxying a request
from my local user rhaas, who authenticated using such and such a
method and connected from such and such an IP yadda yadda". That feels
to me like really clear communication that the server can then be
configured to something about via pg_hba.conf or similar. Saying "use
in-band authentication only", to me, feels much murkier. As the
recipient of that message, I don't know exactly what to do about it,
and it feels like whatever heuristic I adopt might end up being wrong
and something bad happens anyway.

> I agree. (But for the record, I think that an outbound proxy filter is
> also insufficient. Someone, somewhere, is going to want to safely
> proxy through localhost _and_ have peer authentication set up.)

Well then they're indeed going to need some way to distinguish a
proxied connection from a non-proxied one. You can't send identical
connection requests in different scenarios and get different
results

> I guess I didn't call it out explicitly, so it was fair to assume that
> it did not. I don't think we should ignore those cases.

OK, cool.

> But if we let the configuration focus on policies instead, and
> simultaneously improve the confused-deputy problem, then any IP/host
> filter functionality that we provide becomes an additional safety
> measure instead of your only viable line of defense. "I screwed up our
> IP filter, but we're still safe because the proxy refused to forward
> its client cert to the backend." Or, "this other local application
> requires peer authentication, but it's okay because the proxy
> disallows those connections by default."

Defense in depth is good.

> > Your idea
> > seems to rely on us being able to identify all of the policies that a
> > user is likely to want and give names to each one, and I don't feel
> > very confident that that's realistic. But maybe I'm misinterpreting
> > your idea?
>
> No, that's pretty accurate. But I'm used to systems that provide a
> ridiculous number of policies [1, 2] via what's basically a scoped
> property bag. "Turn off option 1 and 2 globally. For host A and IP
> address B, turn on option 1 as an exception." And I don't really
> expect us to need as many options as those systems do.
>
> I think that configuration style evolves well, it focuses on the right
> things, and it can still handle IP lists intuitively [3], if that's
> the way a DBA really wants to set up policies.

I think what we really need here is an example or three of a proposed
configuration file syntax. I think it would be good if we could pick a
syntax that doesn't require a super-complicated parser, and that maybe
has something in common with our existing configuration file syntaxes.
But if we have to invent something new, then we can do that.

-- 
Robert Haas
EDB: http://www.enterprisedb.com




Re: postgres_fdw, dblink, and CREATE SUBSCRIPTION security

2023-01-30 Thread Jacob Champion
On Fri, Jan 27, 2023 at 1:08 PM Robert Haas  wrote:
> > 1) Forwarding the original ambient context along with the request, so
> > the server can check it too.
>
> Right, so a protocol extension. Reasonable idea, but a big lift. Not
> only do you need everyone to be running a new enough version of
> PostgreSQL, but existing proxies like pgpool and pgbouncer need
> updates, too.

Right.

> > 2) Explicitly combining the request with the proof of authority needed
> > to make it, as in capability-based security [3].
>
> As far as I can see, that link doesn't address how you'd make this
> approach work across a network.

The CSRF-token example I gave is one. But that's HTTP-specific
(stateless, server-driven) and probably doesn't make a lot of sense
for our case.

For our case, assuming that connections have side effects, one
solution could be for the client to signal to the server that the
connection should use in-band authentication only; i.e. fail the
connection if the credentials provided aren't good enough by
themselves to authenticate the client. (This has some overlap with
SASL negotiation, maybe.)

But that still requires server support. I don't know if there's a
clever way to tie the authentication to the request on the client side
only, using existing server implementations. (If connections don't
have side effects, require_auth should be sufficient.)

> > 3) Dropping as many implicitly-held privileges as possible before making
> > a request. This doesn't solve the problem but may considerably reduce
> > the practical attack surface.
>
> Right. I definitely don't object to this kind of approach, but I don't
> think it can ever be sufficient by itself.

I agree. (But for the record, I think that an outbound proxy filter is
also insufficient. Someone, somewhere, is going to want to safely
proxy through localhost _and_ have peer authentication set up.)

> > I think this style focuses on absolute configuration flexibility at the
> > expense of usability. It obfuscates the common use cases. (I have the
> > exact same complaint about our HBA and ident configs, so I may be
> > fighting uphill.)
>
> That's probably somewhat true, but on the other hand, it also is more
> powerful than what you're describing. In your system, is there some
> way the DBA can say "hey, you can connect to any of the machines on
> this list of subnets, but nothing else"? Or equally, "hey, you may NOT
> connect to any machine on this list of subnets, but anything else is
> fine"? Or "you can connect to these subnets without SSL, but if you
> want to talk to anything else, you need to use SSL"?

I guess I didn't call it out explicitly, so it was fair to assume that
it did not. I don't think we should ignore those cases.

But if we let the configuration focus on policies instead, and
simultaneously improve the confused-deputy problem, then any IP/host
filter functionality that we provide becomes an additional safety
measure instead of your only viable line of defense. "I screwed up our
IP filter, but we're still safe because the proxy refused to forward
its client cert to the backend." Or, "this other local application
requires peer authentication, but it's okay because the proxy
disallows those connections by default."

> Your idea
> seems to rely on us being able to identify all of the policies that a
> user is likely to want and give names to each one, and I don't feel
> very confident that that's realistic. But maybe I'm misinterpreting
> your idea?

No, that's pretty accurate. But I'm used to systems that provide a
ridiculous number of policies [1, 2] via what's basically a scoped
property bag. "Turn off option 1 and 2 globally. For host A and IP
address B, turn on option 1 as an exception." And I don't really
expect us to need as many options as those systems do.

I think that configuration style evolves well, it focuses on the right
things, and it can still handle IP lists intuitively [3], if that's
the way a DBA really wants to set up policies.

--Jacob

[1] https://httpd.apache.org/docs/2.4/mod/mod_proxy.html
[2] https://www.haproxy.com/documentation/hapee/latest/onepage/#4
[3] 
https://docs.nginx.com/nginx/admin-guide/security-controls/controlling-access-proxied-tcp/




Re: postgres_fdw, dblink, and CREATE SUBSCRIPTION security

2023-01-27 Thread Robert Haas
On Wed, Jan 25, 2023 at 6:22 PM Jacob Champion  wrote:
> Sure: Ambient authority [1] means that something is granted access based
> on some aspect of its existence that it can't remove (or even
> necessarily enumerate). Up above, when you said "I cannot choose not to
> be myself," that's a clear marker that ambient authority is involved.
> Examples of ambient authn/z factors might include an originating IP
> address, the user ID of a connected peer process, the use of a loopback
> interface, a GPS location, and so on. So 'peer' and 'ident' are ambient
> authentication methods.

OK.

> 1) Forwarding the original ambient context along with the request, so
> the server can check it too.

Right, so a protocol extension. Reasonable idea, but a big lift. Not
only do you need everyone to be running a new enough version of
PostgreSQL, but existing proxies like pgpool and pgbouncer need
updates, too.

> 2) Explicitly combining the request with the proof of authority needed
> to make it, as in capability-based security [3].

As far as I can see, that link doesn't address how you'd make this
approach work across a network.

> 3) Dropping as many implicitly-held privileges as possible before making
> a request. This doesn't solve the problem but may considerably reduce
> the practical attack surface.

Right. I definitely don't object to this kind of approach, but I don't
think it can ever be sufficient by itself.

> > e.g.
> >
> > all all all local all all - deny # block access through UNIX sockets
> > all all all 127.0.0.0/8 all all - deny # block loopback interface via IPv4
> >
> > Or:
> >
> > postgres_fdw all all all all all authentication=cleartext,md5,sasl
> > allow # allow postgres_fdw with password-ish authentication
>
> I think this style focuses on absolute configuration flexibility at the
> expense of usability. It obfuscates the common use cases. (I have the
> exact same complaint about our HBA and ident configs, so I may be
> fighting uphill.)

That's probably somewhat true, but on the other hand, it also is more
powerful than what you're describing. In your system, is there some
way the DBA can say "hey, you can connect to any of the machines on
this list of subnets, but nothing else"? Or equally, "hey, you may NOT
connect to any machine on this list of subnets, but anything else is
fine"? Or "you can connect to these subnets without SSL, but if you
want to talk to anything else, you need to use SSL"? I would feel a
bit bad saying that those are just use cases we don't care about. Most
people likely wouldn't use that kind of flexibility, so maybe it
doesn't really matter, but it seems kind of nice to have. Your idea
seems to rely on us being able to identify all of the policies that a
user is likely to want and give names to each one, and I don't feel
very confident that that's realistic. But maybe I'm misinterpreting
your idea?

-- 
Robert Haas
EDB: http://www.enterprisedb.com




Re: postgres_fdw, dblink, and CREATE SUBSCRIPTION security

2023-01-25 Thread Jacob Champion
On 1/24/23 12:04, Robert Haas wrote:
> I find the concept of "ambient authentication" problematic. I don't
> know exactly what you mean by it. I hope you'll tell me,

Sure: Ambient authority [1] means that something is granted access based
on some aspect of its existence that it can't remove (or even
necessarily enumerate). Up above, when you said "I cannot choose not to
be myself," that's a clear marker that ambient authority is involved.
Examples of ambient authn/z factors might include an originating IP
address, the user ID of a connected peer process, the use of a loopback
interface, a GPS location, and so on. So 'peer' and 'ident' are ambient
authentication methods.

And, because I think it's useful, I'll extend the definition to include
privileges that _could_ be dropped by a proxy, but in practice are
included because there's no easy way not to. Examples for libpq include
the automatic use of the client certificate in ~/.postgresql, or any
Kerberos credentials available in the local user cache. (Or even a
PGPASSWORD set up and forgotten by a DBA.)

Ambient authority is closely related to the confused deputy problem [2],
and the proxy discussed here is a classic confused deputy. The proxy
doesn't know that a core piece of its identity has been used to
authenticate the request it's forwarding. It can't choose its IP
address, or its user ID.

I'm most familiar with this in the context of HTTP, cookie-/IP-based
authn, and cross-site request forgeries. Whenever someone runs a local
web server with no authentication and says "it's okay! we only respond
to requests from the local host!" they're probably about to be broken
open by the first person to successfully reflect a request through the
victim's (very local) web browser.

Ways to mitigate or solve this problem (that I know of) include

1) Forwarding the original ambient context along with the request, so
the server can check it too. HTTP has the Origin header, so a browser
can say, "This request is not coming from my end user; it's coming from
a page controlled by example.org. You can't necessarily treat attached
cookies like they're authoritative." The PROXY protocol lets a proxy
forward several ambient factors, including the originating IP address
(or even the use of a UNIX socket) and information about the original
TLS context.

2) Explicitly combining the request with the proof of authority needed
to make it, as in capability-based security [3]. Some web frameworks
push secret "CSRF tokens" into URLs for this purpose, to tangle the
authorization into the request itself [4]. I'd argue that the "password
requirement" implemented by postgres_fdw and discussed upthread was an
attempt at doing this, to try to ensure that the authentication comes
from the user explicitly and not from the proxy. It's just not very strong.

(require_auth would strengthen it quite a bit; a major feature of that
patchset is to explicitly name the in-band authentication factors that a
server is allowed to pull out of a client. It's still not strong enough
to make a true capability, for one because it's client-side only. But as
long as servers don't perform actions on behalf of users upon
connection, that's pretty good in practice.)

3) Dropping as many implicitly-held privileges as possible before making
a request. This doesn't solve the problem but may considerably reduce
the practical attack surface. For example, if browsers didn't attach
their user's cookies to cross-origin requests, cross-site request
forgeries would probably be considerably less dangerous (and, in the
years since I left the space, it looks like browsers have finally
stopped doing this by default). Upthread, Andres suggested disabling the
default inclusion of client certs and GSS creds, and I would extend that
to include really *anything* pulled in from the environment. Make the
DBA explicitly allow those things.

> but I think
> that I won't like it even after I know, because as I said before, it's
> difficult to know why anyone else makes a decision, and asking an
> untrusted third-party why they're deciding something is sketchy at
> best.

I think that's a red herring. Setting aside that you can, in fact, prove
that the server has authenticated you (e.g. require_auth=scram-sha-256
in my proposed patchset), I don't think "untrusted servers, that we
don't control, doing something stupid" is a very useful thing to focus
on. We're trying to secure the case where a server *is* authenticating
us, using known useful factors, but those factors have been co-opted by
an attacker via a proxy.

> I think that the problems we have in this area can be solved by
> either (a) restricting the open proxy to be less open or (b)
> encouraging people to authenticate users in some way that won't admit
> connections from an open proxy.

(a) is an excellent mitigation, and we should do it. (b) starts getting
shaky because I think peer auth is actually a very reasonable choice for
many people. So I hope we can also start 

postgres_fdw, dblink, and CREATE SUBSCRIPTION security

2023-01-24 Thread Robert Haas
[ Changing subject line to something more appropriate: This is
branched from the "Non-superuser subscription owners" thread, but the
topic has become connection security more generally for outbound
connections from a PostgreSQL instance, the inadequacies of just
trying to require that such connections always use a password, and
related problems. I proposed some kind of "reverse pg_hba.conf file"
as a way of allowing configurable limits on such outbound connections.
]

On Tue, Jan 24, 2023 at 2:18 PM Jacob Champion  wrote:
> - It's completely reasonable to let a proxy operator restrict how that
> proxy is used. I doubt very much that a typical DBA wants to be
> operating an open proxy.

That's very well put. It's precisely what I was thinking, but
expressed much more clearly.

> - I think the devil will be in the details of the configuration
> design. Lists of allowed destination authorities (in the URI sense),
> options that must be present/absent/overridden, those sound great. But
> your initial examples of allow-loopback and require-passwords options
> are in the "make the DBA deal with it" line of thinking, IMO. I think
> it's difficult for someone to reason through those correctly the first
> time, even for experts. I'd like to instead see the core problem --
> that *any* ambient authentication used by a proxy is inherently risky
> -- exposed as a highly visible concept in the config, so that it's
> hard to make mistakes.

I find the concept of "ambient authentication" problematic. I don't
know exactly what you mean by it. I hope you'll tell me, but I think
that I won't like it even after I know, because as I said before, it's
difficult to know why anyone else makes a decision, and asking an
untrusted third-party why they're deciding something is sketchy at
best. I think that the problems we have in this area can be solved by
either (a) restricting the open proxy to be less open or (b)
encouraging people to authenticate users in some way that won't admit
connections from an open proxy. The former needs to be configurable by
the DBA, and the latter is also a configuration choice by the DBA. We
can provide tools here that make it less likely that people will shoot
themselves in the foot, and we can ship default configurations that
reduce the chance of inadvertent foot-shooting, and we can write
documentation that says "don't shoot yourself in the foot," but we
cannot actually prevent people from shooting themselves in the foot
except, perhaps, by massively nerfing the capabilities of the system.

What I was thinking about in terms of a "reverse pg_hba.conf" was
something in the vein of, e.g.:

SOURCE_COMPONENT SOURCE_DATABASE SOURCE_USER DESTINATION_SUBNET
DESTINATION_DATABASE DESTINATION_USER OPTIONS ACTION

e.g.

all all all local all all - deny # block access through UNIX sockets
all all all 127.0.0.0/8 all all - deny # block loopback interface via IPv4

Or:

postgres_fdw all all all all all authentication=cleartext,md5,sasl
allow # allow postgres_fdw with password-ish authentication

Disallowing loopback connections feels quite tricky. You could use
127.anything.anything.anything, but you could also loop back via IPv6,
or you could loop back via any interface. But you can't use
subnet-based ACLs to rule out loop backs through IP/IPv6 interfaces
unless you know what all your system's own IPs are. Maybe that's an
argument in favor of having a dedicated deny-loopback facility built
into the system instead of relying on IP ACLs. But I am not sure that
really works either: how sure are we that we can discover all of the
local IP addresses? Maybe it doesn't matter anyway, since the point is
just to disallow anything that would be likely to use "trust" or
"ident" authentication, and that's probably not going to include any
non-loopback network interfaces. But ... is that true in general? What
about on Windows?

> - I'm inherently skeptical of solutions that require all clients --
> proxies, in this case -- to be configured correctly in order for a
> server to be able to protect itself. (But I also have a larger
> appetite for security options that break compatibility when turned on.
> :D)

I (still) don't think that restricting the proxy is required, but you
can't both not restrict the proxy and also allow passwordless loopback
superuser connections. You have to pick one or the other. The reason I
keep harping on the role of the DBA is that I don't think we can make
that choice unilaterally on behalf of everyone. We've tried doing that
with the current rules and we've discussed the weaknesses of that
approach already.

> > I don't think the logon trigger thing is all *that* hypothetical. We
> > don't have it yet, but there have been patches proposed repeatedly for
> > many years.
>
> Okay. I think this thread has applicable lessons -- if connection
> establishment itself leads to side effects, all actors in the
> ecosystem (bouncers, proxies) have to be hardened against making those
> connections