SEC.AUTH.HBA_MD5 — md5 authentication, whose verifier is the password
- Category: security
- Severity: high
- Level: 0
- Confidence: deterministic
- Downtime class: none — the finding is about how the server authenticates, not about a statement
- Stability: stable
- Suites: audit
- Applies to: PostgreSQL 18
The role name is the only salt
PostgreSQL's md5 verifier is md5(password || rolname). The role name is public, so the digest is
effectively unsalted: a captured verifier can be attacked offline at enormous speed. Worse, the
protocol accepts a client that knows only the digest — so the verifier IS a password equivalent, and
recovering the original is optional.
scram-sha-256 fixes both, and PostgreSQL has shipped it since version 10.
The order matters, or nobody can log in
Changing the line first leaves every role holding an MD5 verifier the server will no longer accept.
-- 1. new passwords will be stored as SCRAM verifiers
ALTER SYSTEM SET password_encryption = 'scram-sha-256';
SELECT pg_reload_conf();
-- 2. every role sets its password AGAIN, which is what actually rewrites the verifier
ALTER ROLE app PASSWORD 'a new one';
-- 3. confirm before touching pg_hba.conf
SELECT rolname FROM pg_authid WHERE rolpassword LIKE 'md5%';
Only then change the line.
Bad
host all all 10.0.0.0/8 md5
Good
hostssl all app 10.0.4.0/24 scram-sha-256
Related
SEC.AUTH.HBA_CLEARTEXT— the method that sends the password itself.- What each role currently has stored is a separate question from what a line negotiates, and
the two do not have to agree: a role can hold a SCRAM verifier while a line still offers
md5.