Parere su sicurezza login su webapp PHP

di il
6 risposte

Parere su sicurezza login su webapp PHP

Ciao, ho scritto una webapp in PHP che si appoggia ad un database mysql con PHPmyAdmin.

La web App richiede un Login e volevo un parere sulla robustezza della sicurezza del mio sistema ed eventualmente un consiglio per migliorarla nel caso fosse insufficiente.

Allora, per prima cosa l'Admin crea gli utenti e gli conferisce un livello utente (admin, superuser, user).
Sul database vengono salvati i dati utente compreso il livello e la password codificata con Argon2ID.

A questo punto l'utente può fare il login, il sistema di login confronta username e password con quanto salvato sul database e se corrisponde istanzia diverse variabili di sessione che riguardano l'utente, tra cui nome utente, e il suo livello. Tutte le pagine successive della webapp hanno in testa un controllo che verifica se esistono alcune di queste variabili che vengono istanziate solo in caso di login positivo. Se esistono e si tratta di una pagina che ha un livello di accesso elevato, il sistema controlla anche che la variabile di sessione "livello" dell'utente sia adeguata.

Se tutti i controlli vanno a buon fine il sistema genera la pagina. Se anche solo uno va male (mancano delle var di sessione o il livello non è adeguato), lo script reinvia l'utente all'index.php

Bene.... a che rischi mi espongo? Eventualmente come lo posso migliorare?

Grazie!

6 Risposte

  • Re: Parere su sicurezza login su webapp PHP

    Che c'entra PHPmyadmin? Niente.
    Comunque spero che non manderai dal client la password in chiaro, sia pure magari su una SSL/TLS, ma solo il relativo hash.
    Ecco perchè non ha molto senso usare argonid, molto meglio una funziona hash disponibile in locale (tipicamente sha1 o sha256 ripetuta giusto un pochino di volte).

    Un altro possibile approccio è quello di codificare in un unico blobbole utente, livello e password, farne l'hash e spedirlo.
    il server farà un ciclo su tutte le righe degli utenti per trovare un match
  • Re: Parere su sicurezza login su webapp PHP

    Sto facendo delle prove, e sto imparando come trattare il tema della sicurezza.... quindi per prima cosa relax.

    L'architettura attuale prevede una pagina di login con una form che invia i dati di login ad una pagina php che fa i controlli: per prima cosa recupera la psw salvata sul database relativa a quel nome utente. Poi la confronta con quanto inviato dall' utente tramite la funzione php password_verify(). Se il confronto da esito positivo istanzia le variabili di sessione.

    Ora se capisco bene cosa mi stai dicendo, dovrei codificare in sha256 anche il dato che l' utente invia dalla pagina di login a quella che fa il controllo... giusto? Nel caso potresti darmi qualche consiglio su come farlo?

    Grazie!
  • Re: Parere su sicurezza login su webapp PHP

    Legolas84 ha scritto:


    Sto facendo delle prove, e sto imparando come trattare il tema della sicurezza.... quindi per prima cosa relax.
    Sono più che rilassato
    L'architettura attuale prevede una pagina di login con una form che invia i dati di login ad una pagina php che fa i controlli: per prima cosa recupera la psw salvata sul database relativa a quel nome utente.
    Sopra hai scritto hash, non password
    Poi la confronta con quanto inviato dall' utente tramite la funzione php password_verify(). Se il confronto da esito positivo istanzia le variabili di sessione.

    Ora se capisco bene cosa mi stai dicendo, dovrei codificare in sha256 anche il dato che l' utente invia dalla pagina di login a quella che fa il controllo... giusto? Nel caso potresti darmi qualche consiglio su come farlo?

    Grazie!
    Puoi operare da javascript con qualcosa del genere (in questo caso un banale SHA1)
    
    <script>
    			$(document).ready(function() {
    			
    			$('#login').click(function()
    			{
    			var username=$("#username").val();
    
    			var password=$("#password").val();
    
    			var name = CryptoJS.SHA1(username);
    // questa tristezza è fatta per i test su http (non si sa mai) a rischio wireshark
    			var hash = CryptoJS.SHA1("header"+password+"ilmiosaleeeeeeeee!!!");
    		    var dataString = 'username='+name+'&password='+hash;
    			if($.trim(username).length>0 && $.trim(password).length>0)
    			{
    			$.ajax({
                type: "POST",
                url: "ajaxlogin.php",
                data: dataString,
                cache: false,
                beforeSend: function(){ $("#login").val('Connessione...');},
                success: function(data){
                if(data)
                {
    				$("body").load("home.php").hide().fadeIn(1500).delay(6000);
                }
                else
                {
    				$('#box').shake();
    				$("#login").val('Login')
    				$("#error").html("<span style='color:#cc0000'>Errore:</span> Dati connessioni invalidi.");
                }
                }
                });
    			
    			}
    			return false;
    			});
    			
    				
    			});
    	</script>
    Lato autenticazione qualcosa del genere
    
    function calcolaPrivilegioPortale($i_utente,$i_passwordImmessa,&$o_utente,&$o_idwan,&$o_nickname)
    {
    	registra('PRIV+1','DUMMY',0,'DUMMY','SKYNET0',$i_utente.' '.$i_passwordImmessa);
    	$o_utente='';
    	$o_nickname='';
    	
    	if (!isset($i_utente))
    	{
    		return -1;
    	}
    	if (empty($i_utente))
    	{
    		return -2;
    	}
    	if (!isset($i_passwordImmessa))
    	{
    		return -3;
    	}
    	if (empty($i_passwordImmessa))
    	{
    		return -4;
    	}
    	if (strlen($i_utente)>45)
    	{	
    		return -5;
    	}
    	if (strlen($i_passwordImmessa)!==40)
    	{
    		return -6;
    	}
    	
    	if(preg_match('/[^a-f0-9]/', $i_passwordImmessa))
    	{	
    		return -7;
    	}
    
    	if (strlen($i_utente)!==40)
    	{
    		return -9;
    	}
    	
    	if(preg_match('/[^a-f0-9]/', $i_utente))
    	{	
    		return -10;
    	}
    	
    	registra('PRIV+2','DUMMY',0,'DUMMY','SKYNET0','Passate forche');
    			
    	try 
    	{
    		$conn = new PDO(DB_DSN,DB_USER,DB_PASSWORD);
    		$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    	} 
    	
    	catch (PDOException $e) 
    	{
    		return -11;
    	}
    	
    	registra('PRIV+3','DUMMY',0,'DUMMY','SKYNET0','Conn OK');
    		
    	try
    	{
    		$statement = $conn->prepare("SELECT ... from quellochevuoi where (...) and (sha1(connessioneutente)=:connessioneutente) limit 1");
    	}
    	catch (PDOException $e) 
    	{
    		registra('PRIV+4','DUMMY',0,'DUMMY','SKYNET0','Eccezione prepara');
    		return -12;
    	}
    		
    	$statement->bindParam(':connessioneutente', $i_utente);
    		
    				
    	try
    	{
    		@$statement->execute();
    	}
    	catch (PDOException $e) 
    	{
    		registra('PRIV+5','DUMMY',0,'DUMMY','SKYNET0','Eccezione X');
    		return -13;
    	}
    		
    	$row = $statement->fetch(); 
    	if (empty($row))
    	{
    		registra('PRIV+6','DUMMY',0,'DUMMY','SKYNET0','Row vuota');
    		return -14;
    	}
    	
    	$minuscolo=array_change_key_case($row);
    	$hash=sha1("header".$minuscolo['connessionepassword']."!ilmiosalegrosso!");
    
    	registra('PRIV+7','DUMMY',0,'DUMMY','SKYNET0','Hash '.$hash.' =>>> '.$i_passwordImmessa.' ||| '."header".$minuscolo['connessionepassword']."!ilmiosalegrosso!");
    	
    	
    	if ($i_passwordImmessa===$hash)	
    	{
    		$o_utente=$minuscolo['connessioneutente'];
    		$o_nickname=$minuscolo['filtronickname'];
    		$o_idwan=intval($minuscolo['idwan']);
    		registra('LOGIN+PARTE1','DUMMY',0,'DUMMY','SKYNET0',$o_utente.' '.$o_nickname.' '.$o_idwan);
    		return 0;
    	}
    	else
    	{
    		registra('LOGIN+FAL1','DUMMY',0,'DUMMY','SKYNET0','DUMMY');
    		
    		return -15;
    	}			
    }
    
    Chiaramente è solo uno schema.
    Una possibilità più furba è quello di giustapporre nomeutente e password in una singola stringa, calcolarne l'hash (magari ciclato 10 volte), poi di nuovo hashato con altro algoritmo (giusto per mettere fuori gioco le rainbowtable)
    e passi la stringa al server PHP

    Il quale farà la stessa cosa all' "inverso" (stile tenet).

    A cosa serve? A rendere la vita difficile ad un eventuale intercettatore di pacchetti sulla LAN del client: non vedrà in chiaro il nome utente, ed inoltre potrai fare controlli ben più stringenti, cioè sia sulla lunghezza dell'hash che sui caratteri che lo compongono, scartando senza pietà, non avendo dunque problemi di overflow, stringhe "strane" che possano confondere PHP e così via.
    Nell'esempio sopra sono i 40 caratteri ASCII dei 160 bit di SHA1

    La "sanitizzazione" dell'input (e dell'output) è fondamentale
  • Re: Parere su sicurezza login su webapp PHP

    Ciao, grazie mille dell'aiuto molto specifico e chiaro.... sto facendo alcune prove per adattarmi alla mia situazione specifica.
    CryptoJS è un plugin JavaScript da scaricare?

    GRAZIE
  • Re: Parere su sicurezza login su webapp PHP

    Puoi usare quello che vuoi, sono librerie javascript.
    https://code.google.com/archive/p/crypto-js
  • Re: Parere su sicurezza login su webapp PHP

    Ciao, piuttosto che fare creare la password all’amministratore potresti inviare una mail con link che contenga un token specifico per l’utente appena creato e quindi dare la possibilità all’utente stesso di creare la password.
Devi accedere o registrarti per scrivere nel forum
6 risposte