Salvataggio delle password e memorizzazione delle funzioni

4

(BTW, questo è tutto codificato in PHP come sono sicuro che sarai in grado di dire dalla funzione in basso)

Quando si salvano le password, sono a conoscenza del fatto che è necessario eseguire l'hash delle password, infatti qui è il mio codice (dimmi se è abbastanza sicuro):

function hash($password)
{
    return password_hash($password, PASSWORD_BCRYPT, array(
        'cost' => 12,
        'salt' => bin2hex(openssl_random_pseudo_bytes(16))
    ));
}

Tuttavia, la mia vera domanda è se sto usando un sistema di login appropriato o no. Nel prossimo paragrafo spiegherò come funziona il mio attuale sistema e qualcuno può dirmi se va bene o se deve essere cambiato. Ho sentito che il modo corretto che si suppone di fare è con un token che il client salva nei cookie o qualcosa del genere.

Quando l'utente arriva per la prima volta sul sito e il suo account è registrato, viene richiesto di accedere. Con la password che hanno fornito, l'ho cancellato e controllato se corrisponde, con password_verify (), la password nel database. Una volta convalidati hanno le informazioni di accesso corrette e posso andare avanti e autorizzarle ho impostato $ _SESSION il nome utente e la password (che capisco è memorizzato sul lato server), e se hanno spuntato il pulsante remember me salvi lo username e la password (non modificata) nei cookie scadrà tra 1 settimana.

Ogni volta che tentano di fare una nuova azione, ad esempio caricare una pagina come le informazioni dell'account, esegue una funzione nella parte superiore del codice che restituisce se sono autenticati o meno, per verificare se sono autentificati o no, controlla $ _SESSION per il nome utente e la password e li autentica di nuovo. Se hanno spuntato ricordati di me e il $ _SESSION è scaduto, prende il nome utente e la password da lì.

La mia preoccupazione è che sono sicuro che la maggior parte dei siti Web utilizza un sistema token, in modo che quando si effettua il login salvi un token nei cookie e poi, invece di accedere ogni volta, utilizzi il token. E anche sui forum, ad esempio, puoi controllare chi è online mentre con il mio, non puoi.

Qualcuno può rispondere se ciò che ho fatto è corretto, o deve essere cambiato, o non è il massimo, ma tecnicamente è sicuro. La parte della sessione che sono abbastanza sicuro è sicura, e ancora più sicura di alcuni video che ho visto, alcuni dicono che è possibile memorizzare l'ID dell'utente nella sessione, il che significa che se cambiano la password sono ancora loggati. Ma la parte dei biscotti, mi fa incazzare con i biscotti che rubano le paure salvandoli nei loro biscotti.

    
posta techraf 06.08.2016 - 14:18
fonte

4 risposte

0

Ho trovato una risposta, per questo sto usando JWT (s). Token Web Token. Sono due stringhe codificate Base64 di dati JSON e una firma valida alla fine che convalida che le informazioni non sono state modificate. Contiene quando termina la sessione di accesso e il loro nome utente. È particolarmente utile se si desidera utilizzare facilmente nuovi server in quanto non è necessario sincronizzarsi con un database per l'accesso.

Chiunque voglia fare l'autenticazione, lo consiglio vivamente. Così facile da usare, ecco anche una lib: link < - È una classe copiata di una che ho trovato su github tranne L'ho modificato per rimuovere gli errori e renderlo più semplice.

$key="1682da5b920f4ceb74a542922f43b2a4"/* You need to keep this to decode */
$a = new JWT;

$jwt = $a->encode(json_encode(array(
            "typ" => "JWT",
            "alg" => "HS256"
        )), json_encode(array(
            "iss" => "http://yourwebsite.com/",
            "iat" => time(),
            "exp" => time() + (20 * 60),
            "username" => "authenticated Username"
        )), $key);

        setcookie('jwt_token', $jwt, 0, '/');

Ricorda che i dati impostati nelle JWT non possono essere modificati, poiché la firma che la chiave fornirà in seguito la manterrà in questo modo.

Quando un utente sta tentando di accedere, eseguire la funzione $ a- > decode (), restituirà false se i dati sono stati manomessi, ad esempio cambiando nome utente e tentando di accedere come "amministratore ".

$jwt = $this->jwt->decode($_COOKIE['jwt_token'], $key);
        if($jwt == false) {
            echo 'Invalid JWT signature, tampered with!'
        } else {
            $json = json_decode($jwt, true);

            if(time() > $json['exp']) { /* expired */ }
            if(time() < $json['iat']) { /* invalid */ }

            /* 
             VALIDATED, let them through as being the user:
             $json['username']
            */
        }

se restituisce false, come indicato sopra, la firma non è valida in quanto è stata manomessa. È quindi possibile utilizzare l'array json_decoded per verificare informazioni come "exp", se time () > exp allora è scaduto. Se time () < quindi lo stanno anche spoofando. Una volta che tutto è stato convalidato, puoi controllare il nome utente e essere sicuri al 100% di avere il permesso di essere nell'account dell'utente.

    
risposta data 07.08.2016 - 16:54
fonte
1

I am aware that you have to hash your passwords, infact here's my code (tell me if it's secure enough)

Sì, è sicuro. Non vorrei passare il sale però, password_hash gestisce automaticamente i sali.

I set in the $_SESSION the username and password (which I understand is stored on the server side)

Sì, è memorizzato sul lato server. Tuttavia, non è necessario archiviare informazioni sensibili nella sessione se è possibile evitarlo, cosa che in questo caso può essere (non è necessaria la password nella sessione).

Questo è un problema di sicurezza in quanto può portare alla perdita della password in chiaro, poiché i dati di sessione possono essere letti su host condivisi, tramite inclusioni di file e così via.

if they ticked the remember me button I save the username and password (unhashed) in the cookies

Ancora una volta, non va bene. Davvero non vuoi memorizzare la password senza alcuno sforzo, specialmente il cookie.

Chiunque abbia accesso temporaneo al browser delle vittime ora avrà accesso alla password in chiaro, a cui si può accedere tramite XSS (almeno se il tuo cookie non è httpOnly, quale dovrebbe essere), e così via.

Quello che vuoi usare è un identificatore casuale che generi e memorizzi nel database (idealmente con hash).

The session part I'm pretty sure is secure, and even more secure than some videos I've watched, some say that you can just store the user's ID in the session which means if they change their password they're still logged in. But the cookies part, it's tripping me up with cookie stealing scares saving it unhashed in their cookies.

Sembri sapere che non segui le migliori pratiche. Allora perché costruirti il tuo qui? Il tuo approccio non sembra offrire alcun vantaggio, ma ha alcuni aspetti negativi piuttosto seri.

    
risposta data 06.08.2016 - 15:06
fonte
1

Promemoria rapido:

  • Non definire il sale, lascia che sia la funzione password_hash () a gestirlo per te. Nota che è deprecato in PHP7 .
  • bcrypt tronca la password più lunga di 72 caratteri e sul byte NUL (\ 0). Questo è di progettazione, non a causa dell'implementazione di PHP. Per questi motivi, è raccomandato per passare il risultato base64_encode () dell'hash ('SHA-384') a password_hash () invece della password originale direttamente:
function safePasswordHash($password) {
    return password_hash(
        base64_encode(
            hash('sha384', $password, false)
        ), PASSWORD_BCRYPT, array('cost' => 12)
    );
}

Prova: link

Basato su questo articolo , puoi anche utilizzare un selettore e un token casuali per associare ogni utente a uno stato di autenticazione in una tabella separata (ad esempio "token_auth").

Quindi prima generi due stringhe casuali di 12 caratteri:

  • Un "selettore", usato come identificatore;
  • Un "validatore", memorizzato in testo normale nel cookie e nel valore hash nel database (campo "token"). Usa SHA-256 qui.

Quindi imposti il cookie come "selettore: validatore" ad es. . "FhpyQLjXYCc9: qXE6Bh417rYg"

Per garantire che il cookie sia valido, devi prima recuperare il "token" che corrisponde al "selettore" nel tuo database e quindi confrontarlo con il valore SHA-256 del "validatore" presente nel cookie.

Utilizza la funzione hash_equals () per evitare potenziali attacchi temporali.

    
risposta data 07.08.2016 - 09:09
fonte
0

La tua intuizione sull'archiviazione delle password in testo semplice in un cookie è corretta - non è una buona idea farlo e ci sono alternative più sicure. Stai salendo e tagliando le tue password, ma memorizzarle in testo in chiaro nella variabile $_SESSION di contrattempi: significa che se un utente malintenzionato ha avuto accesso al tuo server, sarebbe in grado di ottenere le password di tutte le firme attualmente firmate -in utenti.

Per quanto ne so, il metodo standard è esattamente come dici tu - usando un token. Questo è molto più sicuro: non è mai necessario memorizzare le password degli utenti in testo normale ovunque. L'idea generale è questa:

  • Quando un utente registra il proprio nome utente e amp; password (su HTTPS), la verifichi con password_verify() .
  • Se l'autenticazione ha esito positivo, salvi un cookie sul computer dell'utente con quanto segue: username=xxxx&expiry=xxxx&digest=xxxx . Quanto tempo durerà il token dipende da te. Puoi anche aggiungere altre variabili, come admin=true e così.
  • Il digest è un HMAC, un codice di autenticazione dei messaggi basato su hash. Dimostra che solo tu (il server) potresti aver creato il cookie e che non è stato manomesso. Puoi utilizzare PHP hash_hmac () per questo. Tieni presente che dovrai salvare una chiave segreta sul tuo server.
  • Ora, quando un utente tenta di accedere ad un'altra pagina, devi solo verificare che abbia il tuo cookie e (in modo cruciale) che digest= corrisponda alla hash_hmac() degli altri dati del cookie. Se un utente tenta di manomettere il proprio cookie, ad es. cambiandolo con un nome utente diverso, HMAC non convalida.

C'è un ottimo articolo su questo argomento che consiglio di leggere: Do and Dont's of Client Authentication on the Web (link PDF).

    
risposta data 06.08.2016 - 15:08
fonte