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