2012-05-10 15 views
6

C'è un modo per garantire i dati $_POST ricevuti dal mio modulo e non un'influenza esterna. Fondamentalmente non voglio che qualcuno sia in grado di falsificare un $_POST in una pagina universalmente disponibile come la creazione di un account. La pagina di creazione dell'account è accessibile da qualsiasi utente, ma voglio garantire che solo i dati inviati dal mio modulo account_creation siano ciò che viene elaborato.

L'unica cosa che potevo pensare era avviare un $_SESSION e quindi fornire session_id al form usando un input nascosto. Su $ _POST il valore dell'ingresso nascosto verrà quindi confrontato con il session_id corrente.

Se esiste un metodo migliore per ottenere questo risultato? Se c'è, non vedo l'ora di sentirlo.

risposta

7

Non è possibile garantire che i dati provengano da un modulo . Una richiesta POST è solo una richiesta POST, può essere generata in diversi modi. Un modulo HTML è solo uno di quei modi che è molto facile da usare. Il server deve convalidare se i dati ricevuti tramite la richiesta POST sono validi o meno e se intervenire o meno.

Detto questo, ci sono cose che possono aiutare a limitare e convalidare i dati che vengono inviati. Prima di tutto, è necessario che un utente abbia effettuato l'accesso utilizzando i cookie (di sessione). Questo elimina richieste casuali da parte di utenti anonimi. In secondo luogo, è possibile incorporare un token come campo nascosto nel modulo che si salva anche nella sessione dell'utente. La richiesta POST deve contenere quel token per essere valido. Il token è semplicemente una stringa pseudo-casuale.
È possibile migliorare ciò preparando un hash dei campi modulo che si prevede che l'utente invii. Se il valore del modulo deve essere di sola lettura, è possibile includere anche il valore nell'hash. Per esempio.:

$rand = md5(mt_rand()); 
$hash = sha1('lastname:firstname:email:' . $rand); 

$_SESSION['rand'] = $rand; 
$_SESSION['hash'] = $hash; 

// on form submit: 

$keys = array_keys($_POST); 
$checkHash = sha1(join(':', $keys) . ':' . $_SESSION['rand']); 
if ($checkHash != $_SESSION['hash']) { 
    die('Form submission failed token validation'); 
} 

Questo è solo un esempio veloce, probabilmente si vorrà per ordinare le chiavi in ​​ordine alfabetico per assicurarsi che si otterrà lo stesso hash, ecc Essa dimostra il concetto di che l'utente debba avere un token univoco per ogni richiesta però che impedisce di temperare con i moduli e di inviare più o meno dati di quanto desiderato.

Ciò non significa che un utente abbia effettivamente utilizzato il modulo per inviare i dati.

1

Leggermente migliore è aggiungere ulteriori convalide come user_agent, user_ip e qualche altro $ _SERVER vars - quelle sono le due che uso.

Quindi, creare l'ID univoco (o ID sessione) come si descrive, ma aggiungere una piccola convalida in più che anche l'agente e l'ip corrispondono. Non infallibile, ma aggiunge un altro piccolo livello di sicurezza.

Modifica: devo aggiungere che non si restituisce l'agente utente; mantieni quel lato server e convalida silenziosamente l'ID di sessione restituito.

Inoltre, se un invio non riesce a convalidare, non rivelare mai all'utente il motivo per cui - in questo modo un imbroglione non sa in che modo li sta monitorando. Puoi anche aggiungere il monitoraggio di "5 invalidi e sei fuori", ma devi effettuare una sorta di accesso per quello.

1

L'utilizzo dell'ID di sessione è sicuramente un modo per farlo. Ma ci sono altre opzioni la maggior parte (se non tutte) delle quali comportano l'aggiunta di alcuni dati come campo nascosto.

  1. Utilizzare un CAPCHA. Questo sarà sempre univoco per ogni caricamento della pagina e quindi renderà obbligatorio l'uso del modulo.
  2. Generare dati casuali e memorizzarli nel DB (o solo nella variabile $_SESSION) e controllarli una volta inviato il modulo.

L'opzione 1 è quella che raccomando per un modulo di creazione utente in quanto richiama il doppio dovere. Si interrompe l'invio automatico del proprio modulo, assicurando al contempo che i dati dello $_POST provengano dal proprio modulo.

0

Questo è uno schema di modello standard per impedire XSRF. Essenzialmente è il simile a quello che hai menzionato. Il server crea un token casuale al momento del rendering del modulo per l'utente. È legato a un cookie del browser per l'utente. All'invio del modulo, viene pubblicato nuovamente sul server. Il server confronta quindi il token con ciò che è stato emesso e l'azione modulo viene eseguita solo dopo una corrispondenza corretta.

0

Ci sono molte buone menzioni di mettere un valore univoco nel modulo e la corrispondenza con il valore memorizzato nella sessione lato server. Fatelo, ma pensate anche a cosa succede quando un utente usa il pulsante Indietro e tenta eventualmente di inviare il modulo due volte, oppure apre una seconda finestra del browser (stessa sessione!), Oppure usano più moduli sul vostro sito.

Non creare bug pazzi non pensando al tuo sistema.

+0

Grazie per questo non avevo pensato alle altre implicazioni di questa azione. Anche se penso che questi problemi potrebbero essere evitati usando qualcosa di simile a 'if (! Isset ($ _ SESSION ['hash'])) {create hash} else {usa l'hash esistente}'. –

2
$ref = $_SERVER['HTTP_REFERER']; 
if($ref !== 'some site path/index.php') 
{ 
    die("Access Denied!"); 
} 

Questo dovrebbe evitare che la maggior parte delle persone dal pubblicare dati al database da un influenza esterna.