[PHP] Ottimizzare login

Forum dedicato alla programmazione.

Moderatore: Staff

Regole del forum
1) Citare in modo preciso il linguaggio di programmazione usato.
2) Se possibile portare un esempio del risultato atteso.
3) Leggere attentamente le risposte ricevute.
4) Scrivere i messaggi con il colore di default, evitare altri colori.
5) Scrivere in Italiano o in Inglese, se possibile grammaticalmente corretto, evitate stili di scrittura poco chiari, quindi nessuna abbreviazione tipo telegramma o scrittura stile SMS o CHAT.
6) Appena registrati è consigliato presentarsi nel forum dedicato.

La non osservanza delle regole porta a provvedimenti di vari tipo da parte dello staff, in particolare la non osservanza della regola 5 porta alla cancellazione del post e alla segnalazione dell'utente. In caso di recidività l'utente rischia il ban temporaneo.
kanzy
Linux 2.x
Linux 2.x
Messaggi: 210
Iscritto il: sab 10 mag 2008, 15:02
Slackware: 14.2

[PHP] Ottimizzare login

Messaggio da kanzy »

Ciao a tutti! (soprattutto ad aschenaz :-D)

Questo è il login del sito di una piccola comunità di 120 persone.
Funziona senza problemi, anche perchè, credo, non sia mai stato "stressato" da
nessuno. :-)
Desidero una... manina per aggiornare il codice (scritto nel 2007, no CMS)
alle mutate esigenze della rete in materia di sicurezza e funzionalità.
Il server usa le ultime versioni di Slackware, PHP e MySQL.
Il sito, aggiornato il 1 luglio, supporta HTML5, CSS3 e jQuery.
Login x 3 gruppi (3 aree diverse) con 1 password x gruppo (non si desidera
registrare nessun utente).

Codice: Seleziona tutto

<?php 
...
if($azione == "login") {
	$utente = mysql_escape_string($_POST['utente']);
	$passwd = mysql_escape_string(sha1($_POST['password']));
	$query = mysql_query("SELECT * FROM utenti");
	if($utente == mysql_result($query,1,1) && $passwd ==
mysql_result($query,1,2)) {
		$_SESSION['segreteria'] = mysql_result($query,1,1);
		header("location: ../index.php?page=amministrazione");
	} elseif($utente == mysql_result($query,2,1) && $passwd ==
mysql_result($query,2,2)) {
		$_SESSION['professori'] = mysql_result($query,2,1);
		header("location: ../index.php?page=professori");
	} elseif($utente == mysql_result($query,3,1) && $passwd ==
mysql_result($query,3,2)) { 
		$_SESSION['studenti'] = mysql_result($query,3,1);
		header("location: ../index.php?page=studenti");
	} else {
		header("location: ../index.php?page=login&mssgg=Controllare le
credenziali");
	}
}
...
?>
l'uomo ha bisogno di cibo rifugio e storie

Avatar utente
masalapianta
Iper Master
Iper Master
Messaggi: 2775
Iscritto il: lun 25 lug 2005, 0:00
Nome Cognome: famoso porco
Kernel: uname -r
Desktop: awesome
Distribuzione: Debian
Località: Roma
Contatta:

Re: [PHP] Ottimizzare login

Messaggio da masalapianta »

1) evita come la peste l'uso di mysql_escape_string e mysql_real_escape_string (insicure), utilizza invece le prepared statement (che tornano utili anche a prescindere dal discorso sicurezza): http://stackoverflow.com/questions/9070 ... statements
2) le query buttate in mezzo al codice di login non se ponno vedè (magari se il codice è poco non serve MVC, ma infilare il codice che fa query sul db in funzioni apposite è meglio (migliora la manutenibilità)
3) non ho capito perchè fai una select su tutta la tabella facendo la ricerca con codice php, anzichè far cercare direttamente al database il record che ti interessa (SELECT * FROM utenti WHERE password = '$passwd' AND username = '$utente')
4) non ha senso usare N volte la funzione mysql_result(), meglio usarla una volta e poi usare il risultato in tutte le if/elseif

ilmich
Master
Master
Messaggi: 1645
Iscritto il: lun 16 lug 2007, 17:39
Slackware: 15.0 64bit
Kernel: 5.15.27
Desktop: kde
Località: Roma

Re: [PHP] Ottimizzare login

Messaggio da ilmich »

masalapianta ha scritto:3) non ho capito perchè fai una select su tutta la tabella facendo la ricerca con codice php, anzichè far cercare direttamente al database il record che ti interessa (SELECT * FROM utenti WHERE password = '$passwd' AND username = '$utente')
dal codice mi sembra di intuire che ci siano 3 soli utenti senza possibilità di registrarne di nuovi quindi sostanzialmente controlla la password scorrendo le 3 possibilità
comunque aldila delle giustissime osservazioni che hai già dato tu questa è la parte che fa il login, per chiudere il cerchio e dare consigli per rifarlo (perchè a mio parere cosi' fatto nn va bene) occorrerebbe conoscere anche la parte che in ciascuna pagina protetta controlla la sessione per verificare che l'utente eventualmente loggato sia autorizzato ad accedervi.
#LiveSimple and #ProgramThings
https://github.com/ilmich
http://ilmich6502.it/

ilmich
Master
Master
Messaggi: 1645
Iscritto il: lun 16 lug 2007, 17:39
Slackware: 15.0 64bit
Kernel: 5.15.27
Desktop: kde
Località: Roma

Re: [PHP] Ottimizzare login

Messaggio da ilmich »

colgo inoltre l'occasione, perchè magari si puo' intavolare un discorso a piu' menti, su come ultimamente sviluppo i login per le mie applicazioni web.
fermo restando che niente è sicuro quanto un canale cifrato uno dei problemi piu' rilevanti del login in una applicazione web è lo scambio di username e password tra il browser e il server che se il canale non è sicuro avviene in chiaro.

percio' uso questo sistema che per ora nn da' evidenti problemi dal punto di vista funzionale (o almeno io nn li ho trovati).
praticamente in fase di registrazione al posto del campo password nel database creo un token di sicurezza che è composto dal risultato di una funzione di hashing/cifratura simmetrica della concatenazione di username+password.
in fase di login poi, nel caso di browser con javascript abilitato ,al posto di mandare separatamente username e password in chiaro, viene creato un token con lo stesso metodo usato in fase di registrazione (e sempre concatenando username + password) che viene poi usato in fase di query (select count(1) from utenti where token = 'input_del_browser')

in caso di browser senza javascript si attiva la modalità 'legacy' che manda le due informazioni in chiaro + l'informazione che la modalità è classica, ed è poi il server che in questo caso crea il token e fa la query sul db

in questo modo anche nel caso in cui per necessita/pigrizia/costi nn si possono usare certificati ssl per proteggere il canale comunque si alza di un po' la sicurezza.
che ne pensate!?
#LiveSimple and #ProgramThings
https://github.com/ilmich
http://ilmich6502.it/

Avatar utente
masalapianta
Iper Master
Iper Master
Messaggi: 2775
Iscritto il: lun 25 lug 2005, 0:00
Nome Cognome: famoso porco
Kernel: uname -r
Desktop: awesome
Distribuzione: Debian
Località: Roma
Contatta:

Re: [PHP] Ottimizzare login

Messaggio da masalapianta »

miklos ha scritto:colgo inoltre l'occasione, perchè magari si puo' intavolare un discorso a piu' menti, su come ultimamente sviluppo i login per le mie applicazioni web.
fermo restando che niente è sicuro quanto un canale cifrato uno dei problemi piu' rilevanti del login in una applicazione web è lo scambio di username e password tra il browser e il server che se il canale non è sicuro avviene in chiaro.

percio' uso questo sistema che per ora nn da' evidenti problemi dal punto di vista funzionale (o almeno io nn li ho trovati).
praticamente in fase di registrazione al posto del campo password nel database creo un token di sicurezza che è composto dal risultato di una funzione di hashing/cifratura simmetrica della concatenazione di username+password.
in fase di login poi, nel caso di browser con javascript abilitato ,al posto di mandare separatamente username e password in chiaro, viene creato un token con lo stesso metodo usato in fase di registrazione (e sempre concatenando username + password) che viene poi usato in fase di query (select count(1) from utenti where token = 'input_del_browser')

in caso di browser senza javascript si attiva la modalità 'legacy' che manda le due informazioni in chiaro + l'informazione che la modalità è classica, ed è poi il server che in questo caso crea il token e fa la query sul db

in questo modo anche nel caso in cui per necessita/pigrizia/costi nn si possono usare certificati ssl per proteggere il canale comunque si alza di un po' la sicurezza.
che ne pensate!?
che non è sicuro per niente, per esserlo, la stringa di cui fai l'hash deve contenere una sottostringa che cambia ogni volta (UUID ad esempio), che è poi la stessa cosa che fa APOP (http://tools.ietf.org/html/rfc1460).
Perchè l'hash deve contenere una stringa che cambia ogni volta? perchè se tu crei l'hash semplicemente applicando la funzione di hashing ad una stringa che contenga solo username e password, un eventuale attaccante che sta in mezzo e riesce a leggere l'hash in questione, lo può riutilizzare per loggarsi con l'utente in questione, mentre se la stringa da cui generi l'hash contiene una sottostringa che cambia sempre, anche se l'attaccante riesce a leggere l'hash comunque non lo può riutilizzare; quindi l'algoritmo è il seguente:
1) il client si connette al server chiedendo di iniziare una sessione di autenticazione per un dato utente
2) il server risponde con un token univoco (UUID o altro)
3) il client crea un hash con username+password+token_univoco
4) il server fa una query sul db cercando l'utente che il client ha comunicato al punto 1), si piglia anche la password, crea un hash con username+password+token_univoco (lo stesso token univoco che ha comunicato al client al punto 2) ), infine controlla i due hash, se uguali autentica l'utente, altrimenti lo sfancula

ovviamente si fa prima ad usare https, visto che oggi ci sono anche enti che rilasciano certificati gratuitamente (vedi il certificato che usa slacky)

ilmich
Master
Master
Messaggi: 1645
Iscritto il: lun 16 lug 2007, 17:39
Slackware: 15.0 64bit
Kernel: 5.15.27
Desktop: kde
Località: Roma

Re: [PHP] Ottimizzare login

Messaggio da ilmich »

sono d'accordo con te se stessimo parlando di un cookie di autorizzazione che viaggia ogni volta (infatti in quel caso uso un sistema simile all'hmac con 3 cookie).. quello che ho descritto io (e mi scuso perchè evidentemente nn si capiva) serve solo per il login inteso come "ti sto inviando le mie credenziali".. il processo di login dal punto in cui l'ho descritto varia ed è simile a quello che hai descritto tu.
#LiveSimple and #ProgramThings
https://github.com/ilmich
http://ilmich6502.it/

ilmich
Master
Master
Messaggi: 1645
Iscritto il: lun 16 lug 2007, 17:39
Slackware: 15.0 64bit
Kernel: 5.15.27
Desktop: kde
Località: Roma

Re: [PHP] Ottimizzare login

Messaggio da ilmich »

chiedo venia.. inizialmente nn avevo capito bene il tuo algoritmo.. effettivamente è molto piu' sicuro cosi'! :D sapevo che mi sarebbe stato utile parlarne :D
#LiveSimple and #ProgramThings
https://github.com/ilmich
http://ilmich6502.it/

kanzy
Linux 2.x
Linux 2.x
Messaggi: 210
Iscritto il: sab 10 mag 2008, 15:02
Slackware: 14.2

Re: [PHP] Ottimizzare login

Messaggio da kanzy »

Grazie per i suggerimenti, vedrò di documentarmi ai links postati.

@masalapianta
1) ..e usare filter_var($_POST['utente'], FILTER_SANITIZE_STRING); ?..
2) Se non ho capito male, devo scrivere la funzione della query?.. e poi la infilo nella pagina funzioni.php dove ci stanno tutte le altre?.. è così?..
3) perchè ho bisogno di tutti i dati, visto che chi fa login non so a quale gruppo appartiene. Se estraggo solo una row non risolvo nulla.
Ma se hai un metodo migliore sono qui per questo.
4) Please, spiegami come fare.. idem c.s. (il codice che vedi è copiato dal tutorial php di aschenaz del (credo..) 2006 :D .

@mikios
ecco qui il code di una delle aree protette

Codice: Seleziona tutto

<?php 
session_start(); 
if (!$_SESSION['studenti']) { 
	header("location: ../index.php?page=login&mssgg=Inserire le
credenziali"); 
}
?>
Pur preparando pagine web ad uso personale da 20 anni, la mia competenza è superficiale, o comunque poco approfondita, ed assolutamente non professionale, dunque ho bisogno di esempi chiari e, per imparare ciò che non so, possibilmente commentati. grazie 1000!!
l'uomo ha bisogno di cibo rifugio e storie

Avatar utente
masalapianta
Iper Master
Iper Master
Messaggi: 2775
Iscritto il: lun 25 lug 2005, 0:00
Nome Cognome: famoso porco
Kernel: uname -r
Desktop: awesome
Distribuzione: Debian
Località: Roma
Contatta:

Re: [PHP] Ottimizzare login

Messaggio da masalapianta »

kanzy ha scritto:Grazie per i suggerimenti, vedrò di documentarmi ai links postati.

@masalapianta
1) ..e usare filter_var($_POST['utente'], FILTER_SANITIZE_STRING); ?..
non è pensato per quello, il modo più sicuro (e standard) di proteggersi dagli sql injection bug è usando i prepared statement (che poi tornano utili anche sotto altri punti di vista)
2) Se non ho capito male, devo scrivere la funzione della query?.. e poi la infilo nella pagina funzioni.php dove ci stanno tutte le altre?.. è così?..
in sostanza infili il codice che fa query sul db in delle funzioni dedicate (che poi richiami laddove ora hai il codice che fa query sul db)
3) perchè ho bisogno di tutti i dati, visto che chi fa login non so a quale gruppo appartiene. Se estraggo solo una row non risolvo nulla.
eh??? a te serve il record dell'utente che prova a loggarsi, da quel record ricavi che utente è; non ha alcun senso fare N query per poi ricavarsi l'utenza usando un metodo posizionale del record nella tabella;
se hai 3 utenze e ti serve sapere chi si sta loggando, basta che fai la query come ti ho detto e poi ti estrai il campo contenente il nome utente dal record.
4) Please, spiegami come fare.. idem c.s. (il codice che vedi è copiato dal tutorial php di aschenaz del (credo..) 2006 :D .
te l'ho detto, prima usa la mysql_result() per assegnare ad una variabile il nome utente e poi controlli il contenuto di quella varabile con delle if/elseif o con un switch e in base a quello che trovi fai quel che devi fare

Avatar utente
conraid
Staff
Staff
Messaggi: 13630
Iscritto il: gio 14 lug 2005, 0:00
Nome Cognome: Corrado Franco
Slackware: current64
Desktop: kde
Località: Livorno
Contatta:

Re: [PHP] Ottimizzare login

Messaggio da conraid »

Tra l'altro l'estensione mysql è deprecata (in php 5.5 http://www.php.net/manual/en/intro.mysql.php), usa mysqli o pdo
Come ti dice masalapianta usa le procedure statement, consigliate anche dal manuale php
http://it1.php.net/manual/en/security.d ... ection.php
http://php.net/manual/en/mysqli.quickst ... ements.php

Avatar utente
aschenaz
Staff
Staff
Messaggi: 4623
Iscritto il: mer 28 lug 2004, 0:00
Nome Cognome: Nino
Slackware: current
Kernel: 5.4.x
Desktop: KDE
Località: Reggio Calabria
Contatta:

Re: [PHP] Ottimizzare login

Messaggio da aschenaz »

conraid ha scritto:... usa mysqli o pdo...
Mamma mia, riscrivere tonnellate di codice! #-o

Ma quale delle due estensioni è preferibile?

Avatar utente
conraid
Staff
Staff
Messaggi: 13630
Iscritto il: gio 14 lug 2005, 0:00
Nome Cognome: Corrado Franco
Slackware: current64
Desktop: kde
Località: Livorno
Contatta:

Re: [PHP] Ottimizzare login

Messaggio da conraid »

http://www.php.net/manual/en/mysqlinfo.api.choosing.php

mysqli ti permette qualcosa in più (compreso usare un modo procedurale), ma PDO è più portatile con altri DB

kanzy
Linux 2.x
Linux 2.x
Messaggi: 210
Iscritto il: sab 10 mag 2008, 15:02
Slackware: 14.2

Re: [PHP] Ottimizzare login

Messaggio da kanzy »

Grazie 1000 a tutti!.. mi sembra che dovrò impegnarmi per qualche mese.. sono tutte cose assolutamente nuove per me: vedrò di leggere il man di php.
Se qualcuno vorrà postarmi un esempio pratico di code, mi fa un grosso piacere :D
l'uomo ha bisogno di cibo rifugio e storie

Avatar utente
boh
Linux 4.x
Linux 4.x
Messaggi: 1027
Iscritto il: ven 16 set 2005, 0:00
Slackware: 14.2 (x64)
Kernel: 4.4.111
Desktop: KDE 4.14.32
Località: Milano
Contatta:

Re: [PHP] Ottimizzare login

Messaggio da boh »

masalapianta ha scritto:
miklos ha scritto:colgo inoltre l'occasione, perchè magari si puo' intavolare un discorso a piu' menti, su come ultimamente sviluppo i login per le mie applicazioni web.
fermo restando che niente è sicuro quanto un canale cifrato uno dei problemi piu' rilevanti del login in una applicazione web è lo scambio di username e password tra il browser e il server che se il canale non è sicuro avviene in chiaro.

percio' uso questo sistema che per ora nn da' evidenti problemi dal punto di vista funzionale (o almeno io nn li ho trovati).
praticamente in fase di registrazione al posto del campo password nel database creo un token di sicurezza che è composto dal risultato di una funzione di hashing/cifratura simmetrica della concatenazione di username+password.
in fase di login poi, nel caso di browser con javascript abilitato ,al posto di mandare separatamente username e password in chiaro, viene creato un token con lo stesso metodo usato in fase di registrazione (e sempre concatenando username + password) che viene poi usato in fase di query (select count(1) from utenti where token = 'input_del_browser')

in caso di browser senza javascript si attiva la modalità 'legacy' che manda le due informazioni in chiaro + l'informazione che la modalità è classica, ed è poi il server che in questo caso crea il token e fa la query sul db

in questo modo anche nel caso in cui per necessita/pigrizia/costi nn si possono usare certificati ssl per proteggere il canale comunque si alza di un po' la sicurezza.
che ne pensate!?
che non è sicuro per niente, per esserlo, la stringa di cui fai l'hash deve contenere una sottostringa che cambia ogni volta (UUID ad esempio), che è poi la stessa cosa che fa APOP (http://tools.ietf.org/html/rfc1460).
Perchè l'hash deve contenere una stringa che cambia ogni volta? perchè se tu crei l'hash semplicemente applicando la funzione di hashing ad una stringa che contenga solo username e password, un eventuale attaccante che sta in mezzo e riesce a leggere l'hash in questione, lo può riutilizzare per loggarsi con l'utente in questione, mentre se la stringa da cui generi l'hash contiene una sottostringa che cambia sempre, anche se l'attaccante riesce a leggere l'hash comunque non lo può riutilizzare; quindi l'algoritmo è il seguente:
1) il client si connette al server chiedendo di iniziare una sessione di autenticazione per un dato utente
2) il server risponde con un token univoco (UUID o altro)
3) il client crea un hash con username+password+token_univoco
4) il server fa una query sul db cercando l'utente che il client ha comunicato al punto 1), si piglia anche la password, crea un hash con username+password+token_univoco (lo stesso token univoco che ha comunicato al client al punto 2) ), infine controlla i due hash, se uguali autentica l'utente, altrimenti lo sfancula

ovviamente si fa prima ad usare https, visto che oggi ci sono anche enti che rilasciano certificati gratuitamente (vedi il certificato che usa slacky)
Chiedo scusa per l'intrusione, ma nel punto 1 il nome utente è trasmesso in chiaro al server?
Se è in chiaro, allora con questo sistema un eventuale man in the middle potrebbe vedere solo il nome utente al punto 1 e l'hash univoco al punto 3, giusto?
"Be yourself. Everyone else is already taken." ~ Oscar Wilde

Avatar utente
masalapianta
Iper Master
Iper Master
Messaggi: 2775
Iscritto il: lun 25 lug 2005, 0:00
Nome Cognome: famoso porco
Kernel: uname -r
Desktop: awesome
Distribuzione: Debian
Località: Roma
Contatta:

Re: [PHP] Ottimizzare login

Messaggio da masalapianta »

boh ha scritto:
masalapianta ha scritto:
miklos ha scritto:colgo inoltre l'occasione, perchè magari si puo' intavolare un discorso a piu' menti, su come ultimamente sviluppo i login per le mie applicazioni web.
fermo restando che niente è sicuro quanto un canale cifrato uno dei problemi piu' rilevanti del login in una applicazione web è lo scambio di username e password tra il browser e il server che se il canale non è sicuro avviene in chiaro.

percio' uso questo sistema che per ora nn da' evidenti problemi dal punto di vista funzionale (o almeno io nn li ho trovati).
praticamente in fase di registrazione al posto del campo password nel database creo un token di sicurezza che è composto dal risultato di una funzione di hashing/cifratura simmetrica della concatenazione di username+password.
in fase di login poi, nel caso di browser con javascript abilitato ,al posto di mandare separatamente username e password in chiaro, viene creato un token con lo stesso metodo usato in fase di registrazione (e sempre concatenando username + password) che viene poi usato in fase di query (select count(1) from utenti where token = 'input_del_browser')

in caso di browser senza javascript si attiva la modalità 'legacy' che manda le due informazioni in chiaro + l'informazione che la modalità è classica, ed è poi il server che in questo caso crea il token e fa la query sul db

in questo modo anche nel caso in cui per necessita/pigrizia/costi nn si possono usare certificati ssl per proteggere il canale comunque si alza di un po' la sicurezza.
che ne pensate!?
che non è sicuro per niente, per esserlo, la stringa di cui fai l'hash deve contenere una sottostringa che cambia ogni volta (UUID ad esempio), che è poi la stessa cosa che fa APOP (http://tools.ietf.org/html/rfc1460).
Perchè l'hash deve contenere una stringa che cambia ogni volta? perchè se tu crei l'hash semplicemente applicando la funzione di hashing ad una stringa che contenga solo username e password, un eventuale attaccante che sta in mezzo e riesce a leggere l'hash in questione, lo può riutilizzare per loggarsi con l'utente in questione, mentre se la stringa da cui generi l'hash contiene una sottostringa che cambia sempre, anche se l'attaccante riesce a leggere l'hash comunque non lo può riutilizzare; quindi l'algoritmo è il seguente:
1) il client si connette al server chiedendo di iniziare una sessione di autenticazione per un dato utente
2) il server risponde con un token univoco (UUID o altro)
3) il client crea un hash con username+password+token_univoco
4) il server fa una query sul db cercando l'utente che il client ha comunicato al punto 1), si piglia anche la password, crea un hash con username+password+token_univoco (lo stesso token univoco che ha comunicato al client al punto 2) ), infine controlla i due hash, se uguali autentica l'utente, altrimenti lo sfancula

ovviamente si fa prima ad usare https, visto che oggi ci sono anche enti che rilasciano certificati gratuitamente (vedi il certificato che usa slacky)
Chiedo scusa per l'intrusione, ma nel punto 1 il nome utente è trasmesso in chiaro al server?
Se è in chiaro, allora con questo sistema un eventuale man in the middle potrebbe vedere solo il nome utente al punto 1 e l'hash univoco al punto 3, giusto?
si, l'intento è mantenere segreta la password (e/o il suo hash presente nel db del server) non il nome utente; ma come ho detto la soluzione migliore è https.

Rispondi