Subject: Re: RFC: Additional Directory for Extensions

From: Alvaro Herrera <[email-masked]>
Date: Tue, 25 Jun 2024 12:12:33 +0200

On 2024-Jun-24, Robert Haas wrote:

> Is "tighten up what the superuser can do" on our list of objectives?
> Personally, I think we should be focusing mostly, and maybe entirely,
> on letting non-superusers do more things, with appropriate security
> controls. The superuser can ultimately do anything, since they can
> cause shell commands to be run and load arbitrary code into the
> backend and write code in untrusted procedural languages and mutilate
> the system catalogs and lots of other terrible things.

I don't agree that we should focus _solely_ on allowing non-superusers
to do more things.  Sure, it's a good thing to do -- but we shouldn't
completely close the option of securing superuser itself.  I think it's
not completely impossible to have a future where superuser is just so
within the database, i.e. that it can't escape to the operating system.
I'm sure that would be useful in many environments.  On this list, many
people frequently make the argument that it is impossible to secure, but
I'm not convinced.

They can mutilate the system catalogs: yes, they can TRUNCATE pg_type.
So what?  They've just destroyed their own ability to do anything else.
The real issue here is that they can edit pg_proc to cause SQL function
calls to call arbitrary code.  But what if we limit functions so that
the C code that they can call is located in specific places that are
known to only contain secure code?  This is easy: make sure the
OS-installation only contains safe code in $libdir.

I hear you say: ah, but they can modify dynamic_library_path, which is a
GUC, to load code from anywhere -- especially /tmp, where the newest
bitcoin-mining library was just written.  This is true.  I suggest, to
solve this problem, that we should make dynamic_library_path no longer a
GUC.  It should be a setting that comes from a different origin, one
that even superuser cannot write to.  Only the OS-installation can
modify that file; that way, superuser cannot load arbitrary code that
way.

This is where the new GUC setting being proposed in this thread rubs me
the wrong way: it's adding yet another avenue for this to be exploited.
I would like this new directory not to be a GUC either, just like
dynamic_library_path.

I hear you argue: ah, but they can use COPY to write a new file to
$libdir.  Yes, they can, and I think that's foolish.  We could have
another non-GUC setting which takes a list of directories where COPY can
write files into.  Problem solved.  Do people really need the ability to
write files on arbitrary locations?

Untrusted extensions: well, just don't have those in the OS-installation
and you'll be fine.  I'm okay with saying that a superuser-restricted
system is incompatible with plpython.

archive_command and so on: we could disable these too.  Nathan did some
work to implement those using dynamic libraries, so it shouldn't be too
much of a loss; anything that is done with a shell script can also be
done with a small library.  Those libraries can be made safe.
If there are other ways to invoke shell commands from GUCs, let's add
the ability to use libraries for those too.

What other exploits do we know about?  How can we close them?

Now, I'm not saying that this is an easy journey.  But if we don't
start, we're not going to get there.

-- 
Álvaro Herrera        Breisgau, Deutschland  —  https://www.EnterpriseDB.com/
"Doing what he did amounts to sticking his fingers under the hood of the
implementation; if he gets his fingers burnt, it's his problem."  (Tom Lane)

---

From: Jelte Fennema-Nio <[email-masked]>
Date: Tue, 25 Jun 2024 13:45:06 +0200

> OS-installation only contains safe code in $libdir.

I wouldn't call it "easy" but I totally agree that changing pg_proc is
the main security issue that we have no easy way to tackle.

> modify that file; that way, superuser cannot load arbitrary code that

I don't think that needs a whole new file. Making this GUC be
PGC_SIGHUP/PGC_POSTMASTER + GUC_DISALLOW_IN_AUTO_FILE should be
enough. Just like was done for the new allow_alter_system GUC in PG17.

> I would like this new directory not to be a GUC either, just like

We can make it PGC_SIGHUP/PGC_POSTMASTER + GUC_DISALLOW_IN_AUTO_FILE
too, either now or in the future.

> start, we're not going to get there.

Sure, but it sounds like you're suggesting that you want to "start" by
not adding new features that have equivalent security holes as the
ones that we already have. I don't think that is a very helpful way to
get to a better place. It seems much more useful to tackle the current
problems that we have first, and almost certainly the same solutions
to those problems can be applied to any new features with security
issues.

It at least definitely seems the case for the proposal in this thread:
i.e. we already have a GUC that allows loading libraries from an
arbitrary location. This proposal adds another such GUC. If we solve
the security problem in that first GUC, either by
GUC_DISALLOW_IN_AUTO_FILE, or by creating a whole new mechanism for
the setting, then I see no reason why we cannot use that exact same
solution for the newly proposed GUC. So the required work to secure
postgres will not be meaningfully harder by adding this GUC.

---

From: Nathan Bossart <[email-masked]>
Date: Wed, 21 Aug 2024 16:03:31 -0500

> the ability to use libraries for those too.

Sorry, I just noticed this message.  I recently withdrew my patch set [0]
for using a library instead of shell commands for restore_command,
archive_cleanup_command, and recovery_end_command, as it had sat idle for a
very long time.  If/when there's interest, I'd be happy to pick it up
again.

[0] https://postgr.es/m/ZkwLqichtySV5kF3%40nathan-air.lan

-- 
nathan