2009-12-16 4 views
8

Sto sviluppando un sistema di accesso e autenticazione per un nuovo sito PHP e sto leggendo i vari attacchi e vulnerabilità. Tuttavia, è un po 'confuso, quindi voglio verificare che il mio approccio abbia senso.Sviluppo di una strategia di accesso e autenticazione PHP sicura

Ho intenzione di memorizzare i seguenti dati:

  • Nella sessione: user-id, hash + salata HTTP_USER_AGENT

  • Nel biscotto e nel database: Token casuale , hash + identificatore salato

Su ogni pagina, I intenzione di fare quanto segue:

  1. Se esiste una sessione, l'autenticazione tramite questo. Verificare che lo HTTP_USER_AGENT corrisponda a quello nella sessione memorizzata.

  2. Se non esiste alcuna sessione, utilizzare il cookie per l'autenticazione. Verificare che il token e l'identificativo nel cookie corrispondano a quelli nel database.

  3. Se il cookie non è valido o non esiste, chiedere all'utente di accedere.

Ci sono evidenti difetti in questo? Finché imposto un timeout nel cookie, dovrei essere abbastanza sicuro, giusto? C'è qualcosa che mi manca?

Molte grazie in anticipo.

+0

anche prendere in considerazione l'uso di un sistema di token una volta per azioni critiche ... – TheHippo

+0

Esatto, la memorizzazione dell'ID di sessione nel database è un grosso errore. Memorizzando l'ID di sessione nel database si rende l'iniezione di SQL sul sistema molto più preziosa. Devi presumere che il tuo sistema si scontrerà e che devi avere un piano d'azione per gestire la violazione. Questo è il motivo per cui le password sono archiviate come hash. Ancora più php viene fornito con un gestore di sessione, se reinventi il ​​wheal ti assicuro che sarà meno sicuro. – rook

+0

Anche qui c'è molta buona lettura: http://stackoverflow.com/questions/549/the-definitive-guide-to-website-authentication-beta#477579 –

risposta

12

Pochi pensieri casuali:

  1. E se rubo il cookie di uno degli utenti (utilizzando un attacco XSS iniettando del codice JS nel tuo sito web)? Cadrò quindi nel caso 2. e quindi potrò effettuare il login. IMHO, se vuoi un'autenticazione veramente sicura, non usare i cookie tipo "ricordami" per memorizzare le credenziali dell'utente.
  2. Se si memorizzano le credenziali in un cookie, si prega di non memorizzare la password in chiaro.
  3. Il controllo di HTTP_USER_AGENT è un buon primo passo per impedire il dirottamento di sessione, ma forse è possibile combinarlo con l'indirizzo IP? È molto più difficile essere sullo stesso host rispetto al tuo obiettivo piuttosto che utilizzare semplicemente lo stesso browser.

Ma in ogni caso, grazie per aver dedicato del tempo a pensare a un buon schema di autenticazione. Molti sviluppatori PHP non lo fanno.

MODIFICA: per la cronaca, vorrei chiarire un punto qui: ci sono due biscotti in questa discusione. Uno viene impostato automaticamente da PHP per propagare l'ID di sessione (a volte, vediamo siti Web inserendolo nell'URL, ad esempio www.example.com/page.php?sessionId = [...]) e il secondo creato da te per memorizzare le credenziali dell'utente e autenticarlo quando la sessione viene persa. L'attacco XSS si applica a entrambi, ovvero un utente malintenzionato potrebbe rubare il cookie di sessione e dirottare la sessione (che ha una durata limitata), o rubare il cookie delle credenziali e autenticarlo in un secondo momento.

+0

Il controllo di una combinazione di user agent e dei primi 3 ottetti dell'IP è abbastanza buono. Ho scritto un articolo sull'argomento http://www.jqueryin.com/2009/11/20/php-secure-sessions/. –

+0

Infatti, l'user agent + indirizzo IP è più che sufficiente. Ma perché perdere l'ultimo ottetto? IMO, è la parte più significativa dell'indirizzo IP, poiché il mio vicino potrebbe trovarsi nella stessa sottorete dell'ISP e quindi avere gli stessi primi tre ottetti? Ottimo articolo, io personalmente uso due sali: uno fisso in un file di configurazione e uno generato casualmente sulla creazione dell'utente. – Wookai

+0

La memorizzazione del cookie nel database è un'idea HORRILBE. Significa che se un utente malintenzionato ha una vulnerabilità di sql injection, può ottenere immediatamente l'accesso senza dover craccare una password con hash. – rook

2

non ci dovrebbe essere. la sessione php è memorizzata sul server non l'utente. php lascia semplicemente un cookie di sessione puntandolo ad esso. se non si è in hosting condiviso, la sessione non deve nemmeno essere sottoposta a hash.

joe

1

dipende da quanto sicuro si vuole essere ..

vulnerabilità Cross-site: Diciamo un altro sito indirizza il browser per inviare un modulo al tuo sito che fa qualcosa come la pubblicazione di spam (o peggio) se tale l'utente è già registrato sull'invio del modulo funzionerà. Dovrai controllare il referer e un formID nascosto generato per ogni modulo per proteggerlo completamente.

Secondo: se si dispone di traffico medio-alto, gli ID di sessione possono essere ripetuti o persino indovinati, verificherei contro un ID generato di seconda mano che è memorizzato nei cookie degli utenti.

1

Lo schema sembra inutilmente complesso in alcuni modi, in quanto la complessità aggiunta non ti porta nulla in funzionalità o sicurezza.

  1. Tutti i dati inviati dal browser (ad esempio cookie, agente utente) sono falsificabili. Controllare l'agente utente sarà di aiuto solo quando l'autore dell'attacco è dietro lo stesso NAT dell'utente falso e l'autore dell'attacco sta utilizzando un browser diverso ma non pensa di cambiare lo User-agent.
  2. Le sessioni memorizzano l'id di sessione lato client utilizzando i cookie o un parametro di query URL. Se si desidera prolungare la durata di una sessione, utilizzare session_set_cookie_params per mantenere il cookie di sessione più a lungo.

L'agente utente non è un dato segreto, quindi non è necessario eseguire l'hashing.

Gli attacchi che cookie di sessione + il controllo remoto IP non prenderà sono:

  1. l'attaccante è dietro lo stesso NAT come l'utente
  2. attacchi di iniezione ciechi, in cui l'attaccante parodie IP dell'utente. Nonostante siano solo di scrittura, possono comunque causare danni.
  3. attacchi che utilizzano il browser dell'utente, ad esempio cross-site request forgery (CSRF).

2) potrebbe essere impedito se è possibile elaborare un modo di inviare una sfida al browser dell'utente, che deve essere risposto a prima di completare la richiesta, ma questo è difficile quando non si scrive il client. Con AJAX può essere fatto. 3) (come notato da MindStalker) può essere prevenuto controllando l'intestazione Referer, che funziona perché gli attacchi CSRF non hanno la capacità di influenzare le intestazioni arbitrarie e XMLHttpRequest non dovrebbe consentire l'impostazione dell'intestazione Referer (come da W3C standard , anche se le implementazioni potrebbero non essere conformi). Con iframe, potrebbe essere possibile aggirare un controllo Referer. Inoltre, l'intestazione del Referer potrebbe essere bloccata sul lato client.

2

La memorizzazione del cookie nel database è un'idea HORRILBE. Significa che se un utente malintenzionato ha una vulnerabilità di sql injection, può ottenere immediatamente l'accesso senza dover craccare una password con hash.

A proposito dei quali è necessario utilizzare sha256 per le password, se si utilizza md5() si è tecnicamente vulnerabili agli attacchi e si potrebbe ricevere un numero CVE.

MAI generare i propri ID sessione, utilizzare session_start() e $ _SESSION super global.

Questo è un modo sicuro per reindirizzare le persone. Se non si muore dopo colpo di testa() il resto del codice php viene comunque eseguito, anche se la sua non è visualizzato dai browser normali (gli hacker ancora vedono :)

header("location: index.php"); 
die(); 

Per essere onesti, se la sicurezza si confonde, don scrivere sistemi di sicurezza Le persone hanno scritto più di 1.000 sistemi di login per PHP da solo e la maggior parte sono vulnerabili. Questo progetto ha un sistema di autenticazione sicuro: http://code.google.com/p/michael-the-messenger/downloads/list

+0

Sul primo punto - Non intendo che prenderà il cookie dell'utente e lo memorizzerà nel database; sarebbe sciocco! Intendo dire che un token e un identificatore vengono creati e quindi una copia viene inserita nel cookie e l'altra nel database. Nessun dato dal cookie passa nel database, quindi non può essere iniettato in questo modo. Grazie per l'idea di header(), non l'ho mai saputo. –

+0

Esatto, questo è un grosso errore. Memorizzando il valore del cookie nel database si rende molto più prezioso l'injection sql contro il proprio sistema. Devi presumere che il tuo sistema si scontrerà e che devi avere un piano d'azione per gestire la violazione. Questo è il motivo per cui le password sono archiviate come hash. Ancora più php viene fornito con un gestore di sessione, se reinventi il ​​wheal ti assicuro che sarà meno sicuro. – rook

+0

Non preoccuparti: non ho intenzione di creare il mio gestore di sessione personale! –

1

La maggior parte dei siti utilizza solo la sessione PHP; i dati della sessione ($ _SESSION) sono in a file su il tuo server. Tutto ciò che viene inviato al browser è un ID di sessione. Assicurati di rigenerare la sessione ogni richiesta (session_regenerate_id). Non è necessario inviare due cookie o altro.

Questo è meno vulnerabile al dirottamento di sessione poiché ogni richiesta è un nuovo ID, quindi una vecchia intercettata da un utente malintenzionato è inutile.

La soluzione migliore, ovviamente, sarebbe utilizzare SSL durante l'intera sessione.

0

IMHO è anche importante che le informazioni sulla sessione vengano modificate dopo un accesso riuscito. Per salvare le informazioni sulla sessione in un database non viene salvato a causa di iniezioni.

0

-uso sha1 con sale -certamente è necessario definire che ogni modulo non è sicuro, quindi utilizzare token per ogni modulo. Che tu crei ogni voce di modulo e la disinfetti usando preg_match. Un processo chiamato servizi igienico-sanitari.