Răspuns scurt
- Securizezi baza de date PostgreSQL sau MySQL în producție făcând-o să asculte doar pe localhost sau pe rețeaua privată, niciodată pe o adresă publică.
- Aplicația se conectează cu un rol propriu, cu drepturi doar pe schema ei, iar contul de superuser rămâne pentru administrare, folosit local.
- În PostgreSQL impui scram-sha-256 în pg_hba.conf și TLS cu hostssl; în MySQL pui bind-address, ștergi root@% și rulezi mysql_secure_installation.
- Parolele vin dintr-un manager de secrete, ai backup logic zilnic plus PITR și loghezi conexiunile eșuate.
- Metoda de autentificare PostgreSQL
- scram-sha-256, nu md5 sau trust
- Adresa de ascultare
- 127.0.0.1 sau IP-ul din rețeaua privată
- Contul aplicației
- rol propriu, fără SUPERUSER, fără DROP
- Backup
- pg_dump / mysqldump zilnic + PITR din WAL sau binlog
Rețea și autentificare: primele două straturi
Un server de baze de date nu are nevoie să fie accesibil de pe internet, nici cu parolă bună. Îl legi de adresa privată, iar administrarea de la distanță o faci prin tunel SSH sau VPN. Al doilea strat e autentificarea: pg_hba.conf spune cine se poate conecta, de unde, la ce bază și cum. Metodele trust și md5 pe rețea trebuie să dispară; scram-sha-256 e implicit din PostgreSQL 14, iar hostssl refuză conexiunile necriptate. În MySQL, echivalentul e bind-address, conturi pe host precis, nu pe %, și require_secure_transport = ON.
Privilegii minime: aplicația nu e administrator
Cea mai frecventă greșeală e aplicația conectată ca postgres sau root, „ca să meargă migrările”. Când aplicația are un SQL injection, atacatorul are tot ce are contul: toate bazele, extensii, citire de fișiere de pe disc. Corect, creezi un rol pentru aplicație cu SELECT, INSERT, UPDATE, DELETE pe tabelele ei și un rol separat pentru migrări, folosit doar la deploy. Rolurile de raportare primesc doar SELECT. Fiecare rol are parola lui, rotită când cineva pleacă, ținută în managerul de secrete, nu în cod.
- Un rol per aplicație și per mediu; staging nu folosește parola din producție
- ALTER DEFAULT PRIVILEGES ca tabelele noi să moștenească drepturile corecte
- log_connections activ, cu logurile trimise la sistemul central
Ce spune legislația din România
Baza de date e, aproape întotdeauna, locul unde stau datele personale, deci art. 32 GDPR se aplică direct: criptare, control al accesului, capacitate de restaurare. La o scurgere, ANSPDCP trebuie notificată în 72 de ore, iar prima întrebare e cine avea acces la date și cum. Pentru entitățile de sub OUG 155/2024, gestionarea accesului și backup-ul sunt măsuri minime explicite. Facturile emise prin e-Factura au termene legale de păstrare, deci backup-ul testat al bazei e obligație, nu opțiune.
Setări echivalente de securitate în PostgreSQL și MySQL / MariaDB| Control | PostgreSQL | MySQL / MariaDB |
|---|
| Adresa de ascultare | listen_addresses în postgresql.conf | bind-address în my.cnf |
|---|
| Cine se conectează, de unde | pg_hba.conf, o linie per rol și rețea | utilizator@host, fără % |
|---|
| Autentificare | scram-sha-256 | caching_sha2_password (implicit din 8.0) |
|---|
| Criptare în tranzit | ssl = on, hostssl în pg_hba.conf | require_secure_transport = ON |
|---|
| Backup logic + punct în timp | pg_dump + arhivare WAL (PITR) | mysqldump / mariabackup + binlog |
|---|
Comenzi și configurări
postgresql.conf și pg_hba.conf: doar rețeaua privată, doar scram-sha-256, doar TLS# postgresql.conf (fragment)
listen_addresses = '10.0.0.10'
password_encryption = scram-sha-256
ssl = on
log_connections = on
# pg_hba.conf
# TYPE DATABASE USER ADDRESS METHOD
local all postgres peer
hostssl app_db app_user 10.0.0.5/32 scram-sha-256
host all all 0.0.0.0/0 reject
PostgreSQL: rol de aplicație cu privilegii minimeCREATE ROLE app_user LOGIN PASSWORD 'parola-din-managerul-de-secrete';
GRANT CONNECT ON DATABASE app_db TO app_user;
GRANT USAGE ON SCHEMA public TO app_user;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO app_user;
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO app_user;
MySQL: bind pe rețeaua privată, TLS obligatoriu, fără root@%# /etc/mysql/mysql.conf.d/mysqld.cnf (fragment)
[mysqld]
bind-address = 10.0.0.10
require_secure_transport = ON
local_infile = 0
-- în clientul mysql
DROP USER IF EXISTS 'root'@'%';
CREATE USER 'app'@'10.0.0.5' IDENTIFIED BY 'parola-din-managerul-de-secrete';
GRANT SELECT, INSERT, UPDATE, DELETE ON app_db.* TO 'app'@'10.0.0.5';
FLUSH PRIVILEGES;
Exemple practice
SaaS din Iași cu PostgreSQL pe același VPS cu aplicația
Aplicația rula ca postgres, iar un formular vulnerabil a permis un SQL injection care a citit toate schemele, inclusiv ale altor clienți. Fiecare tenant a primit apoi un rol propriu, aplicația a pierdut superuser, iar pg_hba.conf a trecut pe scram-sha-256 și hostssl.
Magazin online din Oradea cu MySQL administrat de la distanță
Pentru un client desktop, cineva crease root@% și deschisese 3306 în firewall. Un scaner l-a găsit în câteva ore și a început brute force-ul. Contul a fost șters, bind-address setat pe adresa privată, iar accesul de la distanță s-a mutat pe tunel SSH.
Greșeli frecvente
- Lași listen_addresses = '*' sau bind-address = 0.0.0.0 și te bazezi pe parolă.
- Aplicația se conectează ca postgres sau root pentru că „așa au mers migrările”.
- Ai backup, dar nu l-ai restaurat niciodată și nu ai PITR pentru o ștergere accidentală.
- Parola bazei de date stă în repo, identică pe staging și producție.
Cum te ajută 4hosting
- Serviciul PostgreSQL & ClickHouse acoperă replicarea, backup-ul PITR și tuning-ul; MongoDB & Redis include hardening-ul acestor motoare.
- Orele incluse lunar, 1–8 la VPS și 10 la dedicate și GPU, se cer din panoul de client, secțiunea „Servicii DevOps”; un audit al pg_hba.conf și al rolurilor intră de obicei în cotă; orele se consumă în luna calendaristică și nu se reportează.
- Serviciul Firewall & Network Isolation separă serverul de baze de date de cel de aplicație într-o rețea privată.
Întrebări conexe
Trebuie TLS între aplicație și baza de date dacă rulează pe același server?
Pe același server, prin socket Unix sau 127.0.0.1, traficul nu părăsește mașina, deci TLS e opțional. Când baza de date e pe alt server, chiar în aceeași rețea privată, TLS devine obligatoriu: rețeaua furnizorului e partajată și o greșeală de configurare o expune.
Ce înseamnă PITR și de ce nu ajunge pg_dump?
pg_dump îți dă starea de la ora la care a rulat; tot ce s-a întâmplat după se pierde. PITR, recuperarea la un punct în timp, folosește arhiva WAL, sau binlog-ul în MySQL, ca să reconstruiești baza la minutul dinaintea unui DELETE greșit. Le folosești împreună.
Criptez discul sau baza de date?
Criptarea discului te protejează de furtul fizic sau de un disc scos din rotație, nu de un atacator conectat la baza care rulează. Pentru coloane sensibile, CNP sau date de plată, criptarea la nivel de aplicație, cu chei în afara bazei, e stratul care contează.