5 D e 5 E SIA: Creazione di uno script "login utente" in php e mysql con protezione sha1

5 D e 5 E SIA: Creazione di uno script "login utente" in php e mysql con sha1
(sistema di protezione)



fonte originale articolo sul Web: https://www.targetweb.it/script-login-utente-in-php-e-mysql-sicuro/

Nell’articolo di oggi voglio approfondire con voi il perfetto sistema di login in php/mysql con uno sguardo particolare alla sicurezza del sistema.
[lightgrey_box] Attenzione: la versione di login che vedi in questo articolo è già stata migliorata grazie ai consigli degli utenti. Intanto che aspetti il nuovo articolo ti consiglio di dare un’occhiata ai commenti. Grazie per l’attenzione e per la pazienza.[/lightgrey_box]
Questo articolo vi sarà molto utile se avete intrapreso la (dura) carriera dello sviluppatore php. Nella progetta di un cms che si rispetti infatti questo step è a dir poco essenziale e fornisce ai vostri utente un accesso sicuro a tutte le aree riservate del cms come gestione articoli o gestionali vari.

01. Primo passo: Creiamo la tabella mysql

Il primo passo è quello di creare il database del sito e relativa tabella “utenti” dove andremo ad inserire i seguenti campi:
A) Id: conterrà l’id auto-incrementato dei vari utenti con accesso al cms
B) username: Il nome dell’utente (o più) che ha accesso al login.  Tipo Varchar.
C) password: La password univoca dell’utente registrato. Questo campo va filtrato usando il comando sha1 o md5. Sha1 e md5 servono per crittografare la password in modo tale che, se mai qualche intenzionato riuscisse a leggere il campo “pass” questa non potrebbe essere usata in alcun modo dato che risulta “scomposta” secondo il metodo di crittografia scelto.
Creiamo quindi la tabella all’interno del database “login”. Per farlo accediamo a phpmyadmin. A questo punto abbiamo due scelte: la prima è creare la tabella e relativi campi in modo visuale grazie a phpmyadmin; La seconda invece è quella di inserire all’interno del database “login” il seguente codice all’interno della sezione “sql” del pannello:
CREATE TABLE `login` (
`id` INT( 11 ) NOT NULL AUTO_INCREMENT ,
`username` VARCHAR( 64 ) NOT NULL ,
`password` VARCHAR( 64 ) NOT NULL ,
PRIMARY KEY ( `id` )
) ENGINE = MYISAM

INSERT INTO `login` (
`id` ,
`username` ,
`password`
)
VALUES (
NULL , 'utente', sha1( 'prova' )
);
Controllate che la tabella “utenti” sia stata creata in modo corretto. A questo punto siete pronti per il punto successivo.

02. Creazione della home

La prima pagina del vostro cms sarà ovviamente una pagina di login. solo nel caso l’utente si connetta e sia autorizzato avrà accesso alla sua sezione “privata”. Per fare il box di login creiamo lo scheletro con html e stilizziamo il tutto con i css come siamo abituati:
<?php include('config.php'); ?>
<!DOCTYPE html>
<html>
<head>

    <title>Collegati per amministrare il sito - <?php echo $sito_internet ?></title>

    <!--Pannello di gestione creato da Mel Riccardo-->
    <link href="css/admin.css" rel="stylesheet" type="text/css" />

</head>
<body>

    <form id="login" action="verifica.php" method="post">
        <fieldset id="inputs">
            <input id="username" name="username" type="text" placeholder="Username" autofocus required>
            <input id="password" name="password" type="password" placeholder="Password" required>
        </fieldset>
        <fieldset id="actions">
            <input type="submit" id="submit" value="Collegati">
            <a href="../index.php" id="back">Ritorna al sito</a>
        </fieldset>
    </form>

</body>
</html>
Come vedete nella prima riga di codice ho incluso il file config.php dal quale possiamo recuperare in modo dinamico molte informazioni (come ad esempio il nome del sito). Ecco la struttura di base del file config.php (la cui funzione principale è lo storage delle credenziali per collegarsi al database):
 //generali

 $sito_internet = "Targetweb";

 $data =(date("d-m-y"));

 $vers = "2.0";

 //URL PER HTACCESS

 $base_url = "http://localhost/tuosito";

 //connessione DB

 $host = "localhost";

 $db_user = "root";

 $db_psw = "wtargetweb";

 $db_name = "target";
La base_url ci servirà per articoli futuri quindi non preoccupatevi (per ora).
Ovviamente potete stilizzare il login box come meglio desiderate a seconda delle vostre esigenze. Ecco il css per stilizzare e usare i nuovi campi html5 che vedete nello scheletro di sopra.
  /*-------------------LOGIN--------------------*/

 #login

 {
    background-color: #fff;

    background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#eee));

    background-image: -webkit-linear-gradient(top, #fff, #eee);

    background-image: -moz-linear-gradient(top, #fff, #eee);

    background-image: -ms-linear-gradient(top, #fff, #eee);

    background-image: -o-linear-gradient(top, #fff, #eee);

    background-image: linear-gradient(top, #fff, #eee);  

    height: 240px;

    width: 400px;

    margin: -150px 0 0 -230px;

    padding: 30px;

    position: absolute;

    top: 50%;

    left: 50%;

    z-index: 0;

    -moz-border-radius: 3px;

    -webkit-border-radius: 3px;

    border-radius: 3px;  

    -webkit-box-shadow:

          0 0 2px rgba(0, 0, 0, 0.2),

          0 1px 1px rgba(0, 0, 0, .2),

          0 3px 0 #fff,

          0 4px 0 rgba(0, 0, 0, .2),

          0 6px 0 #fff,  

          0 7px 0 rgba(0, 0, 0, .2);

    -moz-box-shadow:

          0 0 2px rgba(0, 0, 0, 0.2),  

          1px 1px   0 rgba(0,   0,   0,   .1),

          3px 3px   0 rgba(255, 255, 255, 1),

          4px 4px   0 rgba(0,   0,   0,   .1),

          6px 6px   0 rgba(255, 255, 255, 1),  

          7px 7px   0 rgba(0,   0,   0,   .1);

    box-shadow:

          0 0 2px rgba(0, 0, 0, 0.2),  

          0 1px 1px rgba(0, 0, 0, .2),

          0 3px 0 #fff,

          0 4px 0 rgba(0, 0, 0, .2),

          0 6px 0 #fff,  

          0 7px 0 rgba(0, 0, 0, .2);

 }

 #login:before

 {

    content: '';

    position: absolute;

    z-index: -1;

    border: 1px dashed #ccc;

    top: 5px;

    bottom: 5px;

    left: 5px;

    right: 5px;

    -moz-box-shadow: 0 0 0 1px #fff;

    -webkit-box-shadow: 0 0 0 1px #fff;

    box-shadow: 0 0 0 1px #fff;

 }

 fieldset

 {

    border: 0;

    padding: 0;

    margin: 0;

 }

 #inputs input

 {

    background: #f9f9f9 url(../images/login-sprite.png) no-repeat;

    padding: 15px 15px 15px 30px;

    margin: 0 0 10px 0;

    width: 353px; /* 353 + 2 + 45 = 400 */

    border: 1px solid #ccc;

    -moz-border-radius: 5px;

    -webkit-border-radius: 5px;

    border-radius: 5px;

    -moz-box-shadow: 0 1px 1px #ccc inset, 0 1px 0 #fff;

    -webkit-box-shadow: 0 1px 1px #ccc inset, 0 1px 0 #fff;

    box-shadow: 0 1px 1px #ccc inset, 0 1px 0 #fff;

 }

 #username{  background-position: 5px -2px !important;}

 #password{  background-position: 5px -52px !important;}

 #inputs input:focus

 {

    background-color: #fff;

    border-color: #e8c291;

    outline: none;

    -moz-box-shadow: 0 0 0 1px #e8c291 inset;

    -webkit-box-shadow: 0 0 0 1px #e8c291 inset;

    box-shadow: 0 0 0 1px #e8c291 inset;

 }

 #actions{ margin: 25px 0 0 0;}

 #submit

 {  

    background-color: #ffb94b;

    background-image: -webkit-gradient(linear, left top, left bottom, from(#fddb6f), to(#ffb94b));

    background-image: -webkit-linear-gradient(top, #fddb6f, #ffb94b);

    background-image: -moz-linear-gradient(top, #fddb6f, #ffb94b);

    background-image: -ms-linear-gradient(top, #fddb6f, #ffb94b);

    background-image: -o-linear-gradient(top, #fddb6f, #ffb94b);

    background-image: linear-gradient(top, #fddb6f, #ffb94b);

    -moz-border-radius: 3px;

    -webkit-border-radius: 3px;

    border-radius: 3px;

    text-shadow: 0 1px 0 rgba(255,255,255,0.5);

     -moz-box-shadow: 0 0 1px rgba(0, 0, 0, 0.3), 0 1px 0 rgba(255, 255, 255, 0.3) inset;

     -webkit-box-shadow: 0 0 1px rgba(0, 0, 0, 0.3), 0 1px 0 rgba(255, 255, 255, 0.3) inset;

     box-shadow: 0 0 1px rgba(0, 0, 0, 0.3), 0 1px 0 rgba(255, 255, 255, 0.3) inset;    

    border-width: 1px;

    border-style: solid;

    border-color: #d69e31 #e3a037 #d5982d #e3a037;

    float: left;

    height: 35px;

    padding: 0;

    width: 120px;

    cursor: pointer;

    font: bold 15px Arial, Helvetica;

    color: #8f5a0a;

 }

 #submit:hover,#submit:focus

 {  

    background-color: #fddb6f;

    background-image: -webkit-gradient(linear, left top, left bottom, from(#ffb94b), to(#fddb6f));

    background-image: -webkit-linear-gradient(top, #ffb94b, #fddb6f);

    background-image: -moz-linear-gradient(top, #ffb94b, #fddb6f);

    background-image: -ms-linear-gradient(top, #ffb94b, #fddb6f);

    background-image: -o-linear-gradient(top, #ffb94b, #fddb6f);

    background-image: linear-gradient(top, #ffb94b, #fddb6f);

 } 

 #submit:active

 {  

    outline: none;

     -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.5) inset;

     -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.5) inset;

     box-shadow: 0 1px 4px rgba(0, 0, 0, 0.5) inset;  

 }

 #submit::-moz-focus-inner

 {

  border: none;

 }

 #actions a

 {

    color: #3151A2;    

    float: right;

    line-height: 35px;

    margin-left: 10px;

 }

03. Creazione del file di verifica

A questo punto abbiasmo bisogno di un file che, una volta premuto si “accedi” verifichi se l’utente ha i privilegi o meno di entrare. Per farlo creiamo un file verifica.php e mettiamo al suo interno questo codice:
<?php
session_start(); //inizio la sessione
//includo i file necessari a collegarmi al db con relativo script di accesso
include("connessione_db.php");
include("config.php"); 

//mi collego
mysql_select_db("$db_name",$connessione); 

//variabili POST con anti sql Injection
$username=mysql_real_escape_string($_POST['username']); //faccio l'escape dei caratteri dannosi
$password=mysql_real_escape_string(sha1($_POST['password'])); //sha1 cifra la password anche qui in questo modo corrisponde con quella del db

 $query = "SELECT * FROM login WHERE username = '$username' AND password = '$password' ";
 $ris = mysql_query($query, $connessione) or die (mysql_error());
 $riga=mysql_fetch_array($ris);  

/*Prelevo l'identificativo dell'utente */
$cod=$riga['username'];

/* Effettuo il controllo */
if ($cod == NULL) $trovato = 0 ;
else $trovato = 1;  

/* Username e password corrette */
if($trovato === 1) {

 /*Registro la sessione*/
  session_register('autorizzato');

  $_SESSION["autorizzato"] = 1;

  /*Registro il codice dell'utente*/
  $_SESSION['cod'] = $cod;

 /*Redirect alla pagina riservata*/
   echo '<script language=javascript>document.location.href="privato.php"</script>'; 

} else {

/*Username e password errati, redirect alla pagina di login*/
 echo '<script language=javascript>document.location.href="index.php"</script>';

}
?>
Il funzionamento generale, per chi mastica un minimo di php è abbastanza semplice, si esegue il loop sulla tabella “utenti”  e si verifica che  il nome e la password inserita sia uguale a uno dei dati inseriti in tabella. Se viene trovata una corrispondenza il file reindirizza a privato.php, altrimenti riporta il ciclo al form di accesso iniziale perchè non si possiedono i privilegi necessari.
TIPS: Se volete fare apparire un messaggio in caso di mancato login potete scrivere il link usando un testo via GET che andrà poi recuperato nell’index principale.
es. index.php?&messaggio=Non-puoi-entrare
Usando un semplice if nell’index contenente il login form potete facilmente reperire il messaggio via GET: ecco lo schema:
if GET–>messaggio —> echo”messaggio”

04. Proteggere la pagina privata da accesso diretto

Ma come faccio a proteggere la pagina privato.php nel caso qualche male intenzionato la carichi direttamente (cosa difficile dato che potremmo usare qualsiasi nome, ma pur sempre plausibile).?
Per fare questo controllo ci viene in contro la variabile di sessione “cod” apertanel corso della verifica durante l’accesso. La sessione indica che l’utente che vuole visualizzare quella pagina HA IL DIRITTO di visualizzarla in quanto si è loggato con successo in precedenza.
Detto questo possiamo verificare e proteggere la pagina da caricamento diretto in questo modo:
<?php
session_start();
//se non c'è la sessione registrata
if (!session_is_registered('autorizzato')) {
  echo "<h1>Area riservata, accesso negato.</h1>";
  echo "Per effettuare il login clicca <a href='index.php'><font color='blue'>qui</font></a>";
  die;
}

//Altrimenti Prelevo il codice identificatico dell'utente loggato
session_start();
$cod = $_SESSION['cod']; //id cod recuperato nel file di verifica
?>
Easy! Basterà inserire queste poche righe di codice all’inizio di ogni pagina per rendere la pagina inviolabile da un eventuale accesso diretto.

05. Funzione di  LogOut con messaggio

Creiamo un file logout.php e mettiamo al suo interno questo codice:
<?php
session_start();
$_SESSION = array();
session_destroy(); //distruggo tutte le sessioni

//creo una varibiale con un messaggio
$msg = "Informazioni: log-out effettuato con successo.";

//la codifico via urlencode informazioni-logout-effettuato-con-successo
$msg = urlencode($msg); // invio il messaggio via get

//ritorno a index.php usando GET posso recuperare e stampare a schermo il messaggio di avvenuto logout
header("location: index.php?msg=$msg");
exit();
?>
Per richiamare lo script vi basterà creare un link “logout” al click dell’utente sarà disconnesso!
Nota: è obbligatorio lasciare session_start() davanti al codice.
Nota2: Assicuratevi di non lasciare righe vuote prima di queste righe di codice (la funzione header a volte da problemi).

06. Sicurezza & co.

Alcune noti importanti sulla sicurezza che dovreste sapere se volete diventare degli sviluppatori:
A) Sql injection: E’ una tecnica hacker che usa alcuni caratteri speciali per “aprire” il codice e rendere controlli mysql inutili, scardinando pertanto il sistema di login. Per testare il vostro login provate a scrivere:
Username: admin ‘ or 1=’1 /*
Password: pippo
Se non avete fatto escape dei caratteri (mysql_real_escape_string) eliminando l’apostrofo il sistema rendere illeggibile la seconda parte della query mysql facendo entrare chiunque e con qualsiasi password.
Come faccio a difendermi? lo script che leggete in questo articolo usa la tecnica mysql_real_escape_string per risolvere questo problema.
B) Brute Force: E’ una tecnica hacker che cerca la possibile  password per accedere al sistema sfruttando alcuni algoritmi di ricerca. Nel nostro sistema  abbiamo ovviato al problema usando la crittografia sha1. Se volete esiste un altro sistema chiamato md5, provatelo!
C) Differenza POST/GET : questa differenza è molto importante e i primi tempi è possibile cadere in errori, più o meno gravi. Ricordate che i dati che passate via GET sono VISIBILI e pertanto intercettabili. Il metodo POST è la scelta obbligata per dati sensibili e passare dati in modo sicuro.
D) Accesso diretto: se la sessione non viene verificata in tutte le pagine, alcuni dati potrebbero essere visti in chiaro sempre a patto che il maleintenzionato sappia il nome della pagina da aprire (caso remoto, ma possibile). Per difendervi vedi il punto 4 della guida.

07. Conclusioni

Bene se siete arrivati a questo ultimo capitolo avrete con tutta probabilità creato il vostro primo sistema di login utente sicuro, veloce e flessibile. Non vi fermate qui però, continuate  a tenervi aggiornati sulle ultime tecniche di sicurezza per essere sempre un passo avanti rispetto ai vostri rivali. 
Nel prossimo articolo dedicato al mondo del php e del developing tratterò un approccio “multi-livello” del sistema di login, molto scalabile e “diverso dal solito” . rimanete connessi su Targetweb.it e condividete la conoscenza su twitter o facebook…potrebbe aiutare altri che come voi vogliono imparare!
[button link=”http://www.red-team-design.com/slick-login-form-with-html5-css3″ color=”blue” size=”small” target=”blank”]Grafica Form Credits[/button]
fonte originale dell'articolo: https://www.targetweb.it/script-login-utente-in-php-e-mysql-sicuro/
Considerazioni sulla sicurezza:
Con il termine SHA (acronimo dell'inglese Secure Hash Algorithm) si indica una famiglia di cinque diverse funzioni crittografiche di hash sviluppate a partire dal 1993 dalla National Security Agency (NSA) e pubblicate dal NIST come standard federale dal governo degli USA ( FIPS PUB 180-4).

Come ogni algoritmo di hash, l'SHA produce un message digest, o "impronta del messaggio", di lunghezza fissa partendo da un messaggio di lunghezza variabile. La sicurezza di un algoritmo di hash risiede nel fatto che la funzione non sia reversibile (non sia cioè possibile risalire al messaggio originale conoscendo solo questo dato) e che non deve essere mai possibile creare intenzionalmente due messaggi diversi con lo stesso digest. Gli algoritmi della famiglia sono denominati SHA-1, SHA-224, SHA-256, SHA-384 e SHA-512: le ultime 4 varianti sono spesso indicate genericamente come SHA-2, per distinguerle dal primo. Il primo produce un digest del messaggio di soli 160 bit, mentre gli altri producono digest di lunghezza in bit pari al numero indicato nella loro sigla (SHA-256 produce un digest di 256 bit). L'SHA-1 è il più diffuso algoritmo della famiglia SHA ed è utilizzato in numerose applicazioni e protocolli nonostante sia ormai insicuro e verrà presto sostituito dagli altri, più moderni ed efficienti.

La sicurezza di SHA-1 è stata appunto compromessa dai crittoanalisti.[1] Sebbene non siano ancora noti attacchi alle varianti SHA-2, esse hanno un algoritmo simile a quello di SHA-1 per cui sono in atto sforzi per sviluppare algoritmi di hashing alternativi e migliorati.[2][3]Un concorso aperto per la realizzazione di una nuova funzione SHA-3 venne annunciato nel Federal Register il 2 novembre 2007[4] dal NIST e attraverso una competizione pubblica, simile a quella adottata per il processo di sviluppo dell'AES,[5] ha portato in data 2 ottobre 2012 ad annunciare come vincitore l'algoritmo Keccak. Opera di un team di analisti italiani e belgi, il Keccak[6] sembra dunque destinato a venire gradualmente incluso e adottato nelle soluzioni di sicurezza informatica più variegate.

Il 23 febbraio 2017 un team di Google ha annunciato la prima tecnica pratica per generare una collisione hash.[7][8]

Gli hash come md5 sha1 non servono per proteggersi dai brute force.
Questi eseguono tentativi ripetuti e se si utilizza una password semplice o classica (come da esempio “prova”) fra i tentativi effettuati verrà scovata in breve tempo.

Gli hash vengono impiegati per due motivi:
– deontologico: nemmeno l’amministratore del sito/database deve poter conoscere le password dei propri utenti (infatti vi è l’abitudine ad utilizzare sempre la stessa su diversi servizi web).
– sicurezza: in caso di sql injection il malintenzionato, in caso di password in chiaro, verrebbe in possesso delle password di tutti i nostri utenti.

Commenti

Post popolari in questo blog

Simulazioni di reti (con Cisco Packet Tracer)

Esercizi sulla rappresentazione della virgola mobile IEEE 754 (Floating Point)