Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Login sicuro su PostgreSQL

Login a sfida su PostgreSQL: aumentare la sicurezza di un sistema di login basato su un'applicazione in PHP e un database PostgreSQL
Login a sfida su PostgreSQL: aumentare la sicurezza di un sistema di login basato su un'applicazione in PHP e un database PostgreSQL
Link copiato negli appunti

PostgreSQL è un famoso DBMS relazionale, basato sul ben noto paradigma client-server, completamente gratuito ed open source, che annovera molte caratteristiche avanzate, quali viste, triggers, supporto pieno per la transazionalità, e via discorrendo.

Il presente articolo descrive il porting verso PostgreSQL della pseudo-applicazione di login sicuro creata su database MySQL e presentata in un precedente articolo. Il deploy è su un server Linux Debian.

Per i dettagli sulla logica di funzionamento del programma rimando all'articolo su Html.it, che descrive la pseudo-applicazione nel dettaglio. Essa viene di fatto qui usata quale esempio di un primo utilizzo di PostgreSQL al fine di presentare la filosofia del DBMS inerente la logica di utilizzo e le politiche di sicurezza.

Descriveremo dapprima l'installazione del DBMS su Linux Debian, quindi procederemo con la creazione di un database, descrivendo le caratteristiche più importanti per quanto riguarda autenticazione, connessione e scambio dati tra client e server. Solo al termine dell'articolo torneremo a parlare del login a sfida.

Installazione di PostgreSQL, PHP ed Apache

Installeremo prima di tutto PostgreSQL, PHP ed Apache. Otterremo un ambiente di lavoro che potremmo chiamare LAPP (Linux, Apache, PostgreSQL, PHP), in opposizione al più noto LAMP. Tutte le operazioni dette di qui in poi verranno svolte da shell in qualità di utente root.

Per conoscere la versione corrente del server database, che al momento in cui scrivo è rappresentata dalla 8.3, utilizziamo i seguenti comandi (i comandi digitati, per differenziarli dalle risposte del sistema, sono scritti qui e in seguito in rosso; i nostri commenti sono scritti in ciano):

apt-get update; apt-cache search postgres | grep postgres

Al fine di installare e configurare PostgreSQL quale servizio, una volta ottenute le informazioni sul nome del pacchetto Debian da scaricare, usiamo:

apt-get install postgresql-8.3

Lettura della lista dei pacchetti in corso... Fatto
Generazione dell'albero delle dipendenze in corso      
Reading state information... Fatto              

I seguenti pacchetti verranno inoltre installati:
  postgresql-client-8.3 postgresql-client-common postgresql-common ssl-cert

Pacchetti suggeriti:
  postgresql-doc-8.3

I seguenti pacchetti NUOVI (NEW) saranno installati:
postgresql-8.3 postgresql-client-8.3 postgresql-client-common
postgresql-common ssl-cert

0 aggiornati, 5 installati, 0 da rimuovere e 0 non aggiornati.  

[...]                                                                                                                  

Configuro postgresql-8.3 (8.3.1-1) ...
Creating new cluster (configuration: /etc/postgresql/8.3/main, data: /var/lib/postgresql/8.3/main)...
Moving configuration file /var/lib/postgresql/8.3/main/postgresql.conf to /etc/postgresql/8.3/main...
Moving configuration file /var/lib/postgresql/8.3/main/pg_hba.conf to /etc/postgresql/8.3/main...
Moving configuration file /var/lib/postgresql/8.3/main/pg_ident.conf to /etc/postgresql/8.3/main...
Configuring postgresql.conf to use port 5432...
Starting PostgreSQL 8.3 database server: main.

Notiamo che i file di configurazione ed i file dati sono, come da consuetudine Debian, rispettivamente memorizzati nella cartella /etc (/etc/postgresql) e /var/lib (/var/lib/postgresql).

I file delle configurazioni inerenti l'autenticazione degli end-point sono leggibili (e modificabili) solamente dall'utente con cui gira PostgreSQL (e, sottinteso, da root):

-rw-r----- postgres postgres  pg_hba.conf
-rw-r----- postgres postgres  pg_ident.conf

I file dei dati seguono la medesima logica, ovvero solo PostgreSQL potrà accedere a queste cartelle, implicando la segretezza, l'integrità e l'autenticità dei dati, per lo meno a livello "sistemistico" (protezione interna).

PHP ed Apache

Per quanto concerne PHP ed Apache, procediamo come appena descritto per PostgreSQL; individuiamo il nome dei pacchetti da scaricare e li installiamo:

apt-cache search php5 | grep -i postgres
php5-pgsql - PostgreSQL module for php5 (modulo PHP per PostgreSQL)
apt-cache search php5 | grep -i apache2
libapache2-mod-php5 - server-side, HTML-embedded scripting language (Apache 2 module) (modulo PHP per Apache)

Quindi:

apt-get install apache2 php5 php5-pgsql libapache2-mod-php5

che si occuperà di installare, configurare ed avviare i programmi necessari:

I seguenti pacchetti NUOVI (NEW) saranno installati:
apache2 apache2-mpm-prefork apache2-utils apache2.2-common libapache2-mod-php5 libapr1 libaprutil1 php5 php5-common php5-pgsql

Al termine puliamo la cache dei pacchetti e, se necessario, riavviamo Apache:

apt-get clean
/etc/init.d/apache2 restart

Installazione di un client Web PHP per PostgreSQL

Similmente a quanto fatto con MySQL nel già citato articolo sul login sicuro, anche per PostgreSQL useremo un programma Web PHP per la sua amministrazione e la creazione di database.

Scarichiamo quindi il programma phpPgAdmin dal sito http://phppgadmin.sourceforge.net; una volta scompattato, esso andrà posto nella www di Apache (posta la configurazione di default di Apache stesso). Volendo, Debian mette a disposizione anche una versione pacchettizza del software.

A questo punto spostiamo la cartella contenente phpPgAdmin nella www (la cartella in cui Apache conserva i siti), definendo per essa i corretti permessi, di modo che Apache (il quale gira come utente www-data) possa accedervi.

Ad esempio (per il file compresso .tar.gz), posto che la directory di lavoro sia /home/marco:

cd /tmp
tar -xf /home/marco/phpPgAdmin-4.2.tar.gz
mv phpPgAdmin-4.2/ /var/www/phppgadmin
rm /home/marco/phpPgAdmin-4.2.tar.gz 
chmod -R 700 /var/www/phppgadmin/
chown -R www-data:www-data /var/www/phppgadmin/

Verifichiamo:

ls -l /var/www/
drwx------ www-data  www-data  phppgadmin

Creazione ruoli

PostgreSQL, come visto, gira sul sistema come utente postgres; ciò vuol dire che qualsiasi operazione esso esegua sul sistema è limitata dai permessi che quell'utente "virtuale" possiede;

ps aux

(qui filtrata) mostra l'asserto:

USER      PID   STAT   COMMAND
postgres  2346  S      /usr/lib/postgresql/8.3/bin/postgres -D /var/lib/postgresql/8.3/main -c config_file=/etc/postgresql/8.3/main/postgresql.conf
postgres  2348  Ss     postgres: writer process
postgres  2349  Ss     postgres: wal writer process
postgres  2350  Ss     postgres: autovacuum launcher process
postgres  2351  Ss     postgres: stats collector process

Al fine di creare gli account utente utilizzati dalle nostre applicazioni su PostgreSQL, è necessario impersonare l'utente con cui esso gira. Sempre da root digitiamo:

su - postgres

Per semplicità di utilizzo, useremo i comandi shell createuser e dropuser, che fungono da wrapper per gli omologhi SQL.

createuser my-app -S -P
Enter password for new role: myapp
Conferma password:  myapp
Shall the new role be allowed to create databases? (s/n) n
Shall the new role be allowed to create more new roles? (s/n) n

In questo modo abbiamo creato un utente non amministrativo, myapp, con password di esempio myapp (usare password forti in deploy! La presente è solo un esempio-giocattolo), che useremo quale utente della pseudo-applicazione di login verso il database.

Creiamo anche un utente amministrativo:

createuser my-admin -s -P
Enter password for new role: myadmin
Conferma password: myadmin

Senza entrare ora nel dettaglio, con estrema evidenza i due account si differenziano per i rispettivi permessi all'interno del database (ciò che attua la cosiddetta protezione esterna; per i dettagli si veda la Guida sulla sicurezza LAMP).

Come per MySQL, le informazioni relative agli account vengono memorizzate in tabelle dello stesso DBMS.

Prima di poter creare database e tabelle, al fine di utilizzare il pseudo-programma di login, è necessario approfondire alcune informazioni aggiuntive riguardanti la logica dell'autenticazione e sulle connessioni al server, come si diceva nell'introduzione. Le vedremo nella prossima parte dell'articolo.

Comunicazione client-server

Connessione client-server

I veicoli con i quali si attua la comunicazione interprocesso tra client e server sono due: tramite rete (socket Internet) oppure tramite socket di dominio UNIX (Unix Domain Socket, UDS).

La prima tecnologia, ben nota a tutti, utilizza la rete (lo stack TCP-IP) per inviare stream di dati; la seconda utilizza file speciali all'interno dello stesso filesystem, i quali file vengono indirizzati dai programmi client e server attraverso interfacce socket e non tramite funzioni di manipolazione file.

Utilizzando gli UDS è possibile controllare chi deve connettersi a cosa anche attraverso i permessi dei file Unix, mentre con i socket IP ciò non è possibile ed ogni tipo di restrizione può esser controllata solamente dal programma server (a livello quindi applicativo). Infine, i primi privilegiano la portabilità delle applicazioni, i secondi, che possono esser usati solamente per servizi local-to-local, le performance.

Il comando

netstat -ap

(relativamente a PostgreSQL) mostra come esso ascolti per connessioni in arrivo:

Active Internet connections (servers and established)
Proto  Local Address         Foreign Address   State        PID/Program name
tcp    localhost:postgresql  *:*               LISTEN       2346/postgres  
udp    localhost:56232       localhost:56232   ESTABLISHED  2346/postgres

Active UNIX domain sockets (servers and established)
Proto  Type    State     I-Node  PID/Program name   Path
unix   STREAM  LISTENING 5792    2346/postgres      /var/run/postgresql/.s.PGSQL.5432

Autenticazione

Per autenticazione s'intende qui il processo tramite il quale il server database accerta l'identità delle applicazioni client.

Le impostazioni inerenti l'autenticazione dei client sono definiti dalle direttive contenute nel file pg_hba.conf (in /etc/postgresql/8.3/main/), il quale controlla gli host abilitati alla connessione, il metodo col quale sono autenticati, quale/i utente PostgreSQL e quale/i database possono rispettivamente impersonificare ed utilizzare. "local" si riferisce alle connessioni veicolate tramite UDS ed "host" quelle veicolate da socket TCP/IP (cifrate o meno).

# Allow any user on the local system to connect to (any) database
# if the user's password is correctly supplied.

# TYPE  DATABASE    USER        CIDR-ADDRESS          METHOD 

# Unix domain socket connections:
local   all         all                               password 

# TCP/IP connections (Ipv4/IPv6):
host    all         all         127.0.0.1/32          md5
host    all         all         ::1/128               md5

Il file di cui sopra permette a PostgreSQL di accettare connessioni locali, sia tramite UDS che socket di rete, senza restrizioni, definendo che il client si identificherà tramite login a username/password.

Scambio dati

Affiancando l'invio di dati in chiaro, è possibile utilizzare connessioni SSL cifrate (OpenSSL) tra gli end-point, a seconda di quanto definito in postgresql.conf. Questo, come più volte rimarcato, evita attacchi di tipo sniffing e man in the middle, riferendosi in particolare all'utilizzo in reti LAN.

Sull'applicazione

Il nostro pseudo-programma di login (che funge da client verso il DBMS per ciò che concerne le chiamate a database - il client è più precisamente rappresentato da PHP tramite il modulo che prima abbiamo installato) userà gli UDS per la comunicazione, ciò che garantisce un'adeguata sicurezza se server database e server Web si trovano sulla stessa macchina; diversamente, qualora dovessero comunicare in rete tra macchine diverse (non in localhost), il metodo "MD5" per l'invio delle credenziali (firmate assieme ad un "seme" casuale) o, meglio, un tunneling SSL per l'invio dei dati dovrebbero esser usati.

Creazione database tramite phpPgAdmin

Abbiamo appreso tutte le conoscenze di base che ci permettono di creare, tramite programma grafico Web, il database su cui la pseudo-applicazione di login sicuro si appoggerà.

Dopo aver impostato il file pg_hba.conf come poc'anzi definito, tramite ad esempio l'editor mc (mc -e /etc/postgresql/8.3/main/pg_hba.conf) ed aver riavviato il DBMS (/etc/init.d/postgresql-8.3 restart) siamo finalmente in grado di utilizzare phpPgAdmin per l'amministrazione.

Da browser richiamiamo quindi il programma, digitando nella barra degli indirizzi: http://localhost/phppgadmin e facciamo il login con l'utente my-admin.

Creiamo a questo punto, dall'interfaccia grafica che ci viene presentata, il database login_db (UTF8).

Il proprietario di tale database diviene automaticamente chi l'ha creato (my-admin): affinché my-app possa operare su di esso, è necessario concedergli i necessari privilegi, sempre da interfaccia Web.

I tipi di privilegi sono, in massima sintesi: SELECT, INSERT, UPDATE, DELETE, REFERENCES, TRIGGER, CREATE, CONNECT, TEMPORARY, EXECUTE ed USAGE. Non approfondiremo ulteriormente.

Facciamo ora il login come my-app e prepariamo quindi la tabella tabella_utente secondo la grafica di seguito riportata

Figura 1: La tabella "tabella_utente"
(clic per ingrandire)

La tabella tabella_utente

ed inseriamo come esempio-giocattolo l'entry:

guest1
15dac3875ad0f994a832043be841dc7e

(la stringa rappresenta l'hash MD5 della password guest1).

Figura 2: Il primo record della "tabella_utente"
(clic per ingrandire)

Il primo record della tabella_utente

Installazione della pseudo applicazione di login

Il pseudo-programma di login rappresenta la struttura base di un login a sfida, o challenge-response, da utilizzare all'interno del proprio programma PHP (compatibilità PHP5+).

Evitare l'invio della password in chiaro da browser a web server, durante l'autenticazione tipicamente utilizzata per un'area riservata, è sempre una cosa buona e giusta, in quanto evita il reply-attack a seguito dello sniffing delle stesse, che, come ben sappiamo, in una LAN è cosa più che banale.

A meno di utilizzare un tunneling SSL (con certificato firmato da una CA o con certificati personali noti al browser), questo tipo di login risulta davvero efficace, a patto che la password sia forte e le sfide generate dal server lunghe e davvero casuali, in modo da vanificare la pericolosità di un attacco a forza bruta.

Su questo ultimo punto ci si può ovviamente spingere oltre, migliorando quanto presente nel codice proposto, dipendentemente dalla vostra buona volontà.

Funzionamento del programma in breve

La logica di funzionamento prevede che il browser invii lo username ed il webserver crei conseguentemente una sfida o challenge (stringa casuale) da rinviare al client stesso.

Il browser codifica a questo punto la sfida con la password personale inserita dall'utente ed invia la stringa ottenuta di modo che il webserver possa controllarne la validità.

Si ha, così, che la password personale non viene inviata da client a server via rete, ma entrambi la conoscono.

Avendo utilizzato lo wrapper ADOdb per l'interazione col database (ADOdb "comunica" coi moduli per MySql e PostrgeSQL presentando al programmatore un'interfaccia omogenea), il porting dal primo al secondo DBMS risulta davvero banale; nella fattispecie è necessario:

  • modificare il file di configurazione db_conn.php;
  • modificare il modo in cui vengono effettuate le query SQL (si tratta di banali modifiche);
  • usare la funzione pg_escape_string anziché l'omologa per MySQL nel "purgare" i dati in ingresso al database.

Il file CLASSES/adodb/db_conn.php dell'applicazione login-pg verrà ad essere:

<?php

require_once ("adodb.inc.php"); 
$DATABASE = "postgres:login_db";
$DBTYPE   = preg_replace("/:.*$/", "", $DATABASE);
$DATABASE = preg_replace("/^.*?:/", "", $DATABASE);
$USERNAME = "my-app";
$PASSWORD = "myapp"; # Questo è solo un esempio, usare sempre password forti!
$LOCALE = "It"; 

ADOLoadCode ($DBTYPE);
$db_conn = &ADONewConnection($DBTYPE);
$db_conn->PConnect("", $USERNAME, $PASSWORD, $DATABASE, $LOCALE);

?>

Il codice esemplifica quanto detto nella pratica. Tutti i file del pseudo-programma sono scaricabili alla voce download.

L'installazione sul server Apache2 @ Linux Debain ricalca esattamente quanto fatto per phpPgAdmin: estrarre lo ZIP, copiare la cartella ottenuta nella www e definire per essa i corretti permessi.

Login-pg risponderà ad http://localhost/login-pg.

Una possibile ulteriore protezione: il salvataggio di dati cifrati

Nel caso di dati sensibili (pensiamo ai dati medici, ad esempio) la legislazione attuale prevede il salvataggio degli stessi cifrati.

Posto che non vi siano vulnerabilità a livello sistemistico o di rete, la cifratura dei dati a livello di filesystem li protegge dalla possibilità di esser letti nel caso in cui si abbia accesso fisico ai dispositivi di memoria di massa del server (server theft).

La cifratura può avvenire a vari livelli di granularità sugli oggetti del database.

Per la decifratura, il client fornisce la chiave al server, il quale decifra i dati e li ritorna al client stesso (molto probabilmente entro un tunnel cifrato SSL, trattandosi appunto di dati "importanti").

Ti consigliamo anche