Repository 32bit  Forum
Repository 64bit  Wiki

[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.

[PHP] Ottimizzare login

Messaggioda kanzy » mer lug 03, 2013 10:55

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
kanzy
Linux 2.4
Linux 2.4
 
Messaggi: 206
Iscritto il: sab mag 10, 2008 14:02
Località: Godiasco PV
Nome Cognome: Franz Fricker
Slackware: 14.0-x86_64
Kernel: 3.2.29
Desktop: kde

Re: [PHP] Ottimizzare login

Messaggioda masalapianta » mer lug 03, 2013 14:43

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
Avatar utente
masalapianta
Iper Master
Iper Master
 
Messaggi: 2775
Iscritto il: dom lug 24, 2005 23:00
Località: Roma
Nome Cognome: famoso porco
Kernel: uname -r
Desktop: awesome
Distribuzione: Debian

Re: [PHP] Ottimizzare login

Messaggioda miklos » mer lug 03, 2013 15:07

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.
ho visto cose che voi astemi non potete immaginare
miklos
Linux 3.x
Linux 3.x
 
Messaggi: 1200
Iscritto il: lun lug 16, 2007 16:39
Località: Roma
Slackware: 14.1 64bit
Kernel: 3.12.6
Desktop: openbox 3.5.2

Re: [PHP] Ottimizzare login

Messaggioda miklos » mer lug 03, 2013 15:26

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!?
ho visto cose che voi astemi non potete immaginare
miklos
Linux 3.x
Linux 3.x
 
Messaggi: 1200
Iscritto il: lun lug 16, 2007 16:39
Località: Roma
Slackware: 14.1 64bit
Kernel: 3.12.6
Desktop: openbox 3.5.2

Re: [PHP] Ottimizzare login

Messaggioda masalapianta » mer lug 03, 2013 16:02

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)
Avatar utente
masalapianta
Iper Master
Iper Master
 
Messaggi: 2775
Iscritto il: dom lug 24, 2005 23:00
Località: Roma
Nome Cognome: famoso porco
Kernel: uname -r
Desktop: awesome
Distribuzione: Debian

Re: [PHP] Ottimizzare login

Messaggioda miklos » mer lug 03, 2013 16:09

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.
ho visto cose che voi astemi non potete immaginare
miklos
Linux 3.x
Linux 3.x
 
Messaggi: 1200
Iscritto il: lun lug 16, 2007 16:39
Località: Roma
Slackware: 14.1 64bit
Kernel: 3.12.6
Desktop: openbox 3.5.2

Re: [PHP] Ottimizzare login

Messaggioda miklos » mer lug 03, 2013 16:18

chiedo venia.. inizialmente nn avevo capito bene il tuo algoritmo.. effettivamente è molto piu' sicuro cosi'! :D sapevo che mi sarebbe stato utile parlarne :D
ho visto cose che voi astemi non potete immaginare
miklos
Linux 3.x
Linux 3.x
 
Messaggi: 1200
Iscritto il: lun lug 16, 2007 16:39
Località: Roma
Slackware: 14.1 64bit
Kernel: 3.12.6
Desktop: openbox 3.5.2

Re: [PHP] Ottimizzare login

Messaggioda kanzy » mer lug 03, 2013 18:23

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
kanzy
Linux 2.4
Linux 2.4
 
Messaggi: 206
Iscritto il: sab mag 10, 2008 14:02
Località: Godiasco PV
Nome Cognome: Franz Fricker
Slackware: 14.0-x86_64
Kernel: 3.2.29
Desktop: kde

Re: [PHP] Ottimizzare login

Messaggioda masalapianta » mer lug 03, 2013 19:42

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
masalapianta
Iper Master
Iper Master
 
Messaggi: 2775
Iscritto il: dom lug 24, 2005 23:00
Località: Roma
Nome Cognome: famoso porco
Kernel: uname -r
Desktop: awesome
Distribuzione: Debian

Re: [PHP] Ottimizzare login

Messaggioda conraid » gio lug 04, 2013 6:22

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
conraid
Staff
Staff
 
Messaggi: 11987
Iscritto il: mer lug 13, 2005 23:00
Località: Livorno
Nome Cognome: Corrado Franco
Slackware: current

Re: [PHP] Ottimizzare login

Messaggioda aschenaz » gio lug 04, 2013 7:28

conraid ha scritto:... usa mysqli o pdo...


Mamma mia, riscrivere tonnellate di codice! #-o

Ma quale delle due estensioni è preferibile?
pensieriemotivi.aschenaz.eu - music-blog
Avatar utente
aschenaz
Staff
Staff
 
Messaggi: 4417
Iscritto il: mar lug 27, 2004 23:00
Località: Reggio Calabria
Nome Cognome: Nino
Slackware: current 64bit
Kernel: 3.14.5
Desktop: KDE 4.10.5

Re: [PHP] Ottimizzare login

Messaggioda conraid » gio lug 04, 2013 7:39

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
Avatar utente
conraid
Staff
Staff
 
Messaggi: 11987
Iscritto il: mer lug 13, 2005 23:00
Località: Livorno
Nome Cognome: Corrado Franco
Slackware: current

Re: [PHP] Ottimizzare login

Messaggioda kanzy » gio lug 04, 2013 11:37

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
kanzy
Linux 2.4
Linux 2.4
 
Messaggi: 206
Iscritto il: sab mag 10, 2008 14:02
Località: Godiasco PV
Nome Cognome: Franz Fricker
Slackware: 14.0-x86_64
Kernel: 3.2.29
Desktop: kde

Re: [PHP] Ottimizzare login

Messaggioda boh » gio lug 04, 2013 15:36

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
boh
Linux 2.6
Linux 2.6
 
Messaggi: 941
Iscritto il: gio set 15, 2005 23:00
Località: Milano
Slackware: 14.1 (x64)
Kernel: 3.10.17
Desktop: KDE 4.10.5

Re: [PHP] Ottimizzare login

Messaggioda masalapianta » gio lug 04, 2013 16:19

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.
Avatar utente
masalapianta
Iper Master
Iper Master
 
Messaggi: 2775
Iscritto il: dom lug 24, 2005 23:00
Località: Roma
Nome Cognome: famoso porco
Kernel: uname -r
Desktop: awesome
Distribuzione: Debian

Prossimo

Torna a Programmazione

Chi c’è in linea

Visitano il forum: Nessuno e 3 ospiti