Sicurezza e DBMS: cosa ricordare quando si scelgono i mezzi di protezione

Sicurezza e DBMS: cosa ricordare quando si scelgono i mezzi di protezione

Mi chiamo Denis Rozhkov, sono il responsabile dello sviluppo software presso l'azienda «Gazinformservis», nel team di prodotto Jatoba. La legislazione e le normative aziendali pongono determinate esigenze in materia di sicurezza del trattamento dei dati. Nessuno vuole che terzi abbiano accesso a informazioni riservate, quindi per ogni progetto sono importanti le seguenti questioni: identificazione e autenticazione, gestione degli accessi ai dati, garantire l'integrità delle informazioni nel sistema, registrazione degli eventi di sicurezza. Pertanto, voglio parlare di alcuni aspetti interessanti riguardanti la sicurezza dei DBMS.

L'articolo è stato preparato sulla base di un intervento a @Databases Meetup, organizzato Mail.ru Cloud Solutions. Se non vuoi leggere, puoi guardare:

Guarda il video

Nell'articolo ci saranno tre parti:
  • Come proteggere le connessioni.
  • Cos'è l'audit delle attività e come registrare ciò che accade dal lato del database e della connessione ad esso.
  • Come proteggere i dati all'interno del database e quali tecnologie esistono per farlo.

Sicurezza e DBMS: cosa ricordare quando si scelgono i mezzi di protezione
Tre componenti della sicurezza dei DBMS: protezione delle connessioni, audit delle attività e protezione dei dati

Protezione delle connessioni

È possibile collegarsi al database sia direttamente che indirettamente tramite applicazioni web. Di solito, l'utente lato business, cioè la persona che lavora con il DBMS, interagisce con esso non direttamente.

Prima di parlare della protezione delle connessioni, è necessario rispondere a domande importanti, da cui dipende come saranno strutturate le misure di sicurezza:

  • un utente business è equivalente a un utente del DBMS;
  • l'accesso ai dati del DBMS è fornito solo tramite API che controlli, oppure c'è accesso diretto alle tabelle;
  • il DBMS è stato isolato in un segmento protetto, chi e come interagisce con esso;
  • viene utilizzato pooling/proxy e strati intermedi che possono modificare le informazioni su come è strutturata la connessione e chi utilizza il database.

Ora vediamo quali strumenti possono essere utilizzati per proteggere le connessioni:

  1. Utilizza soluzioni di tipo firewall per database. Uno strato di protezione aggiuntivo aumenterà almeno la trasparenza di ciò che accade nel DBMS, al massimo — potrai garantire una protezione aggiuntiva dei dati.
  2. Utilizza politiche di password. La loro applicazione dipende da come è strutturata la tua architettura. In ogni caso, una sola password nel file di configurazione di un'applicazione web collegata a un DBMS non è sufficiente per garantire protezione. Esistono diversi strumenti DBMS che consentono di controllare quali utenti e password necessitano di aggiornamento.

    Puoi leggere di più sulle funzioni di valutazione degli utenti qui, così come è possibile informarsi su MS SQL Vulnerability Assessment qui

  3. Arricchisci il contesto della sessione con le informazioni necessarie. Se la sessione è opaca e non capisci chi stia lavorando nel DBMS, puoi arricchire le informazioni riguardanti chi, cosa e perché sta eseguendo operazioni. Queste informazioni possono essere visualizzate nell'audit.
  4. Configura SSL se non hai una separazione di rete tra il DBMS e gli utenti finali, e non è in un VLAN separato. In tali casi, è obbligatorio proteggere il canale tra il consumatore e il DBMS stesso. Esistono strumenti di protezione anche tra le soluzioni open source.

Come influenzerà le prestazioni del DBMS?

Osserviamo con PostgreSQL come SSL influisca sull'uso della CPU, sull'aumento dei tempi di risposta e sulla diminuzione del TPS, se non verranno consumate troppe risorse attivandolo.

Carichiamo PostgreSQL utilizzando pgbench: è un programma semplice per eseguire test sulle prestazioni. Esegue ripetutamente una sequenza di comandi, eventualmente in sessioni parallele del database, e calcola la velocità media delle transazioni.

Test 1 senza SSL e utilizzando SSL — la connessione è stabilita ad ogni transazione:

pgbench.exe --connect -c 10 -t 5000 "host=192.168.220.129 dbname=taskdb user=postgres sslmode=require
sslrootcert=rootCA.crt sslcert=client.crt sslkey=client.key"

vs

pgbench.exe --connect -c 10 -t 5000 "host=192.168.220.129 dbname=taskdb user=postgres"

Test 2 senza SSL e utilizzando SSL — tutte le transazioni vengono eseguite in una sola connessione:

pgbench.exe -c 10 -t 5000 "host=192.168.220.129 dbname=taskdb user=postgres sslmode=require
sslrootcert=rootCA.crt sslcert=client.crt sslkey=client.key"

vs

pgbench.exe -c 10 -t 5000 "host=192.168.220.129 dbname=taskdb user=postgres"

Altre impostazioni:

fattore di scaling: 1
modalità query: semplice
numero di clienti: 10
numero di thread: 1
numero di transazioni per cliente: 5000
numero di transazioni effettivamente elaborate: 50000/50000

Risultati dei test:

 
NO SSL
SSL

La connessione viene stabilita ad ogni transazione

latenza media
171.915 ms
187.695 ms

tps inclusi i collegamenti stabiliti
58.168112
53.278062

tps esclusi i collegamenti stabiliti
64.084546
58.725846

CPU
24%
28%

Tutte le transazioni vengono eseguite in una sola connessione

latenza media
6.722 ms
6.342 ms

tps includendo i collegamenti stabiliti
1587.657278
1576.792883

tps esclusi i collegamenti stabiliti
1588.380574
1577.694766

CPU
17%
21%

Con carichi leggeri, l'influenza di SSL è comparabile all'errore di misurazione. Se la quantità di dati trasmessi è molto grande, la situazione potrebbe essere diversa. Se stabiliremo una connessione per ogni transazione (cosa rara, di solito le connessioni vengono condivise tra gli utenti), avremo un gran numero di connessioni/disconnessioni, l'influenza potrebbe essere leggermente maggiore. Cioè, i rischi di riduzione delle prestazioni possono esistere, tuttavia, la differenza non è così grande da non utilizzare la protezione.

Fate attenzione: c'è una forte differenza se confrontiamo le modalità di lavoro: all'interno di una sessione lavorate o in modalità diverse. Questo è chiaro: per creare ogni connessione vengono spesi delle risorse.

Abbiamo avuto un caso in cui abbiamo collegato Zabbix in modalità trust, quindi non abbiamo controllato md5, non era necessaria l'autenticazione. Poi il cliente ha chiesto di attivare la modalità di autenticazione md5. Questo ha comportato un carico maggiore sulla CPU e le prestazioni sono diminuite. Abbiamo iniziato a cercare modi per ottimizzare. Una delle possibili soluzioni al problema è realizzare una limitazione di rete, creare VLAN separate per il DBMS, aggiungere impostazioni per far capire chi e da dove si sta connettendo e rimuovere l'autenticazione. Inoltre, è possibile ottimizzare le impostazioni di autenticazione per ridurre i costi durante l'attivazione dell'autenticazione, ma in generale l'applicazione di diversi metodi di autenticazione influisce sulle prestazioni e richiede di tenere in considerazione questi fattori durante la progettazione delle capacità di calcolo dei server (hardware) per il DBMS.

Conclusione: in alcune soluzioni anche piccole sfumature nell'autenticazione possono avere un grande impatto sul progetto e diventa problematico quando si capisce solo durante l'implementazione in produzione.

Audit delle azioni

L'audit può riguardare non solo il DBMS. L'audit è la raccolta di informazioni su ciò che accade in diversi segmenti. Può riguardare sia il database firewall sia il sistema operativo su cui è costruito il DBMS.

Nei DBMS commerciali a livello Enterprise, l'audit è ben implementato, mentre nell'open source non sempre. Ecco cosa è disponibile in PostgreSQL:

  • default log — logging integrato;
  • extensions: pgaudit — se il logging predefinito non è sufficiente, è possibile utilizzare impostazioni separate che risolvono alcune sfide.

Integrazione alla relazione nel video:

La registrazione di base degli operatori può essere garantita mediante uno strumento standard di registrazione con log_statement = all.

Questo è accettabile per il monitoraggio e altri tipi di utilizzo, ma non fornisce il livello di dettaglio normalmente necessario per un audit.

Non è sufficiente avere un elenco di tutte le operazioni eseguite sul database.

Deve anche essere possibile trovare affermazioni specifiche che siano di interesse per l'auditor.

Lo strumento di registrazione standard mostra ciò che l'utente ha richiesto, mentre pgAudit si concentra sui dettagli di ciò che è accaduto quando il database ha eseguito la richiesta.

Ad esempio, un auditor potrebbe voler verificare che una tabella specifica sia stata creata in una finestra di manutenzione documentata.

Questo potrebbe sembrare un compito semplice per un audit di base e grep, ma cosa succede se incontri qualcosa di simile a questo (intenzionalmente confuso) esempio:

DO $$
BEGIN
EXECUTE ‘CREATE TABLE import’ || ‘ant_table (id INT)’;
END $$;

La registrazione standard ti darà questo:

LOG: statement: DO $$
BEGIN
EXECUTE ‘CREATE TABLE import’ || ‘ant_table (id INT)’;
END $$;

Sembra che per trovare la tabella di interesse potrebbe essere necessaria una certa conoscenza del codice nei casi in cui le tabelle vengono create dinamicamente.

Questo non è ideale, poiché sarebbe preferibile cercare semplicemente per nome della tabella.

È qui che pgAudit può essere utile.

Per lo stesso input, fornirà questo output nel registro:

AUDIT: SESSION,33,1,FUNCTION,DO,,,«DO $$
BEGIN
EXECUTE ‘CREATE TABLE import’ || ‘ant_table (id INT)’;
END $$;"
AUDIT: SESSION,33,2,DDL,CREATE TABLE,TABLE,public.important_table,CREATE TABLE important_table (id INT)

Viene registrato non solo il blocco DO, ma anche l'intero testo di CREATE TABLE con il tipo di operazione, il tipo di oggetto e il nome completo, il che facilita la ricerca.

Nella registrazione degli operatori SELECT e DML, pgAudit può essere configurato per registrare un'azione separata per ciascuna relazione a cui si fa riferimento nell'operazione.

Non è necessaria l'analisi sintattica per trovare tutte le operazioni che riguardano una tabella specifica (*)».

Come influenzerà le prestazioni del DBMS?

Facciamo dei test attivando l'audit completo e vediamo cosa succede alle prestazioni di PostgreSQL. Attiviamo la registrazione massima del DB su tutti i parametri.

Nel file di configurazione non cambiamo quasi nulla, importante — attiviamo la modalità debug5 per ottenere il massimo delle informazioni.

, affinché il tuo database di test non voglia effettuare un backup silenziosamente.

log_destination = ‘stderr’
logging_collector = on
log_truncate_on_rotation = on
log_rotation_age = 1d
log_rotation_size = 10MB
log_min_messages = debug5
log_min_error_statement = debug5
log_min_duration_statement = 0
debug_print_parse = on
debug_print_rewritten = on
debug_print_plan = on
debug_pretty_print = attivo
log_checkpoints = attivo
log_connections = attivo
log_disconnections = attivo
log_duration = attivo
log_hostname = attivo
log_lock_waits = attivo
log_replication_commands = attivo
log_temp_files = 0
log_timezone = 'Europa/Mosca'

Sulla base dati PostgreSQL con parametri 1 CPU, 2,8 GHz, 2 GB di RAM, 40 GB di HDD eseguiamo tre test di carico, usando i comandi:

$ pgbench -p 3389 -U postgres -i -s 150 benchmark
$ pgbench -p 3389 -U postgres -c 50 -j 2 -P 60 -T 600 benchmark
$ pgbench -p 3389 -U postgres -c 150 -j 2 -P 60 -T 600 benchmark

Risultati del test:

Senza registrazione
Con registrazione

Tempo totale di riempimento del DB
43,74 sec
53,23 sec

RAM
24%
40%

CPU
72%
91%

Test 1 (50 connessioni)

Numero di transazioni in 10 minuti
74169
32445

Transazioni/sec
123
54

Ritardo medio
405 ms
925 ms

Test 2 (150 connessioni su 100 possibili)

Numero di transazioni in 10 minuti
81727
31429

Transazioni/sec
136
52

Ritardo medio
550 ms
1432 ms

Sulle dimensioni

Dimensione del DB
2251 MB
2262 MB

Dimensione dei registri del DB
0 MB
4587 MB

In definitiva: un audit completo non è molto vantaggioso. La quantità di dati derivanti dall'audit sarà pari, se non superiore, a quella dei dati stessi nel database. Tale volume di registrazione che si genera durante l'uso della DBMS è un problema comune in produzione.

Esaminiamo altri parametri:

  • La velocità non cambia molto: senza registrazione — 43,74 sec, con registrazione — 53,23 sec.
  • Le prestazioni in termini di RAM e CPU subiranno un calo, poiché è necessario generare un file con l'audit. Questo è evidente anche in produzione.

Con l'aumento del numero di connessioni, ovviamente, i risultati peggioreranno leggermente.

Nelle aziende con audit è ancora più complicato:

  • i dati sono molti;
  • l'audit è necessario non solo tramite syslog in SIEM, ma anche in file: nel caso in cui accada qualcosa con syslog, deve esserci vicino al database un file in cui vengono salvati i dati;
  • per l'audit è necessario uno scaffale separato, per non influenzare le operazioni I/O sui dischi, poiché occupa molto spazio;
  • a volte, i dipendenti della sicurezza informatica richiedono standard GOST in ogni luogo, cercano l'identificazione secondo GOST.

Limitazione dell'accesso ai dati

Esaminiamo le tecnologie utilizzate per proteggere i dati e per regolamentare l'accesso ad essi nei DB commerciali e open source.

Cosa si può utilizzare in generale:

  1. Crittografia e offuscazione di procedure e funzioni (Wrapping) — ovvero strumenti e utilità separate che trasformano il codice leggibile in incomprensibile. Tuttavia, poi non può essere né modificato né rifattorizzato indietro. Questo approccio è talvolta necessario almeno sul lato del DBMS — la logica delle limitazioni di licenza o la logica di autorizzazione viene crittografata proprio a livello di procedura e funzione.
  2. La restrizione della visibilità dei dati per riga (RLS) è quando utenti diversi vedono la stessa tabella, ma con un insieme differente di righe al suo interno, ovvero per qualcuno certe informazioni non possono essere mostrate a livello di riga.
  3. La modifica dei dati visualizzati (Masking) è quando gli utenti in una colonna della tabella vedono o i dati completi o solo asterischi, ovvero per alcuni utenti le informazioni saranno nascoste. La tecnologia definisce quali dati mostrare a ciascun utente in base al livello di accesso.
  4. La separazione degli accessi Security DBA/Application DBA/DBA riguarda più che altro la limitazione dell'accesso stesso al DBMS, cioè si può separare il personale della sicurezza dai database administrator e application administrator. In open source ci sono poche tecnologie in questo ambito, mentre nei DBMS commerciali ce ne sono molte. Sono necessarie quando ci sono molti utenti con accesso ai server.
  5. Limitazione dell'accesso ai file a livello di filesystem. È possibile assegnare diritti e privilegi di accesso a directory, in modo che ogni amministratore possa accedere solo ai dati necessari.
  6. L'accesso mandatorio e la pulizia della memoria sono tecnologie raramente utilizzate.
  7. La crittografia end-to-end nella DBMS è una crittografia end-side con gestione delle chiavi lato server.
  8. Crittografia dei dati. Ad esempio, la crittografia a livello di colonna: quando utilizzi un meccanismo che crittografa una singola colonna del database.

Come influisce sulle performance del DBMS?

Vediamo l'esempio della crittografia a livello di colonna in PostgreSQL. C'è il modulo pgcrypto, che consente di memorizzare in modo crittografato campi selezionati. Questo è utile quando solo alcuni dati hanno valore. Per leggere i campi crittografati, il client trasmette la chiave di decrittazione, il server decrittografa i dati e li restituisce al client. Senza la chiave, nessuno potrà fare nulla con i tuoi dati.

Eseguiamo un test con pgcrypto. Creiamo una tabella con dati crittografati e dati normali. Di seguito i comandi per creare le tabelle, nella prima riga c'è un comando utile: la creazione dell'estensione con la registrazione del DBMS:

CREATE EXTENSION pgcrypto;
CREATE TABLE t1 (id integer, text1 text, text2 text);
CREATE TABLE t2 (id integer, text1 bytea, text2 bytea);
INSERT INTO t1 (id, text1, text2)
VALUES (generate_series(1,10000000), generate_series(1,10000000)::text, generate_series(1,10000000)::text);
INSERT INTO t2 (id, text1, text2) VALUES (
generate_series(1,10000000),
encrypt(cast(generate_series(1,10000000) AS text)::bytea, 'key'::bytea, 'bf'),
encrypt(cast(generate_series(1,10000000) AS text)::bytea, 'key'::bytea, 'bf'));

Successivamente proveremo a fare una selezione di dati da ciascuna tabella e daremo un'occhiata ai tempi di esecuzione.

Selezione dalla tabella senza funzione di crittografia:

psql -c "timing" -c "select * from t1 limit 1000;" "host=192.168.220.129 dbname=taskdb
user=postgres sslmode=disable" > 1.txt

Cronometro attivato.

  id | text1 | text2
——+——-+——-
1 | 1     | 1
2 | 2     | 2
3 | 3     | 3

997 | 997   | 997
998 | 998   | 998
999 | 999   | 999
1000 | 1000  | 1000
(1000 righe)

Tempo: 1,386 ms

Selezione dalla tabella con funzione di crittografia:

psql -c "timing" -c "select id, decrypt(text1, 'key'::bytea, 'bf'),
decrypt(text2, 'key'::bytea, 'bf') from t2 limit 1000;"
"host=192.168.220.129 dbname=taskdb user=postgres sslmode=disable" > 2.txt

Cronometro attivato.

  id | decrypt | decrypt
——+—————+————
1 | x31 | x31
2 | x32 | x32
3 | x33 | x33

999 | x393939 | x393939
1000 | x31303030 | x31303030
(1000 righe)

Tempo: 50,203 ms

Risultati dei test:

 
Senza crittografia
Pgcrypto (decrypt)

Selezione 1000 righe
1,386 ms
50,203 ms

CPU
15%
35%

RAM
 
+5%

La crittografia influisce notevolmente sulle prestazioni. È evidente che il tempo è aumentato, poiché le operazioni di decrittazione dei dati crittografati (e la decrittazione è generalmente ancora avvolta nella tua logica) richiedono risorse significative. Quindi, l'idea di crittografare tutte le colonne che contengono dati è rischiosa e può portare a una diminuzione delle prestazioni.

Detto ciò, la crittografia non è una soluzione universale per tutti i problemi. I dati decrittografati e la chiave di decrittazione durante il processo di decrittazione e trasferimento dei dati si trovano sul server. Pertanto, le chiavi possono essere intercettate da chi ha accesso completo al server del database, ad esempio da un amministratore di sistema.

Quando per un'intera colonna si utilizza una sola chiave per tutti gli utenti (anche se non per tutti, ma per clienti di un insieme limitato), non è sempre una scelta ottimale. È proprio per questo che si è iniziato a fare crittografia end-to-end, considerando nella gestione dei database varie opzioni di crittografia dei dati dal lato del client e del server, sono emerse le soluzioni key-vault — prodotti separati che forniscono gestione delle chiavi dal lato del database.

Sicurezza e DBMS: cosa ricordare quando si scelgono i mezzi di protezione
Esempio di tale crittografia in MongoDB

Strumenti di sicurezza in database commerciali e open source

Funzioni
Tipo
Password Policy
Audit
Protezione del codice sorgente di procedure e funzioni
RLS
Crittografia

Oracle
Commerciale
+
+
+
+
+

MsSql
Commerciale
+
+
+
+
+

Jatoba
Commerciale
+
+
+
+
estensioni

PostgreSQL
Free
estensioni
estensioni

+
estensioni

MongoDb
Free

+


Disponibile solo in MongoDB Enterprise

La tabella non è affatto completa, ma la situazione è questa: nei prodotti commerciali le questioni di sicurezza sono affrontate da tempo, negli open source, di norma, si utilizzano integrazioni per la sicurezza, molte funzionalità mancano e a volte è necessario scrivere qualcosa. Ad esempio, le politiche di password: in PostgreSQL ci sono molte estensioni diverse.1, 2, 3, 4, 5), che implementano le politiche delle password, ma tutte le esigenze del segmento corporate nazionale, a mio parere, nessuna le soddisfa.

Cosa fare se non si trova quello che serve? Например, хочется использовать определенную СУБД, в которой нет функций, которые требует заказчик.

In tal caso, è possibile utilizzare soluzioni di terze parti che lavorano con diversi DBMS, come «Crypto DB» o «Garda DB». Se si tratta di soluzioni dal segmento nazionale, lì conoscono meglio gli standard GOST rispetto all'open source.

Una seconda opzione è scrivere autonomamente ciò di cui hai bisogno, implementare a livello di procedure l'accesso ai dati e la crittografia nell'applicazione. Tuttavia, con il GOST sarà più complicato. Ma in generale, puoi nascondere i dati come necessario, archiviarli nel DBMS, per poi recuperarli e decifrarli come richiesto, direttamente a livello di applicazione. Tieni subito presente come proteggerai questi algoritmi nell'applicazione. A nostro avviso, è necessario farlo a livello di DBMS, perché lavorerà più velocemente.

Questa presentazione è stata pronunciata per la prima volta a @Databases Meetup by Mail.ru Cloud Solutions. Guarda video altre presentazioni e iscriviti agli annunci di eventi su Telegram Attorno a Kubernetes in Mail.ru Group.

Cosa leggere ancora sull'argomento:

  1. Più di Ceph: archiviazione su cloud MCS.
  2. Come scegliere un database per il progetto, in modo da non dover scegliere di nuovo.

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster