Asigurați-vă formularul cu cheile formularului

Securitatea este un subiect fierbinte. Asigurarea că site-urile dvs. sunt sigure este extrem de importantă pentru orice aplicație web. De fapt, îmi petrec 70% din timpul meu asigurând cererile mele. Unul dintre cele mai importante lucruri pe care trebuie să le asigurăm sunt formele. Astăzi, vom examina o metodă de prevenire a formularului XSS (scripting cross-site) și a cererii de interfață cross-site pe formulare.

De ce?

Datele POST pot fi trimise de pe un site web la altul. De ce e rău? Un scenariu simplu ...

Un utilizator, conectat la site-ul dvs., vizitează un alt site în timpul sesiunii. Acest site web va putea trimite date POST pe site-ul dvs. - de exemplu, cu AJAX. Deoarece utilizatorul este conectat la site-ul dvs., celălalt site va putea să trimită date postate unor formulare securizate care sunt accesibile numai după autentificare.

De asemenea, trebuie să protejăm paginile noastre împotriva atacurilor folosind cURL

Cum rezolvăm acest lucru?

Cu chei de formă! Vom adăuga la fiecare formular un hash special (o cheie de formular) pentru a vă asigura că datele vor fi procesate numai atunci când au fost trimise de pe site-ul dvs. Web. După trimiterea unui formular, scriptul nostru PHP va valida cheia de formular trimisă în raport cu cheia de formular pe care am setat-o ​​într-o sesiune.

Ce trebuie să facem:

  1. Adăugați o cheie de formular pentru fiecare formular.
  2. Stocați cheia de formular într-o sesiune.
  3. Validați cheia de formular după trimiterea formularului.

Pasul 1: o formă simplă

Mai întâi avem nevoie de un simplu formular pentru demonstrații. Una dintre formele cele mai importante pe care trebuie să le asigurăm este formularul de autentificare. Formularul de conectare este vulnerabil la atacurile de forță. Creați un fișier nou și salvați-l ca index.php în rădăcina web. Adăugați în interiorul corpului următorul cod:

     Securizarea formularelor cu chei de formă   

Acum avem o pagină XHTML simplă, cu un formular de autentificare. Dacă doriți să utilizați chei de formular pe site-ul dvs., puteți înlocui scriptul de mai sus cu propria pagină de conectare. Acum, să continuăm acțiunea reală.

Pasul 2: Crearea unei clase

Vom crea o clasă PHP pentru cheile noastre de formular. Deoarece fiecare pagină poate conține numai unu form cheia, am putea face un singleton din clasa noastră pentru a ne asigura că clasa noastră este folosită corect. Deoarece crearea singletons este un subiect mai avansat OOP, vom trece peste acea parte. Creați un fișier nou numit formkey.class.php și plasați-o în radacina web. Acum trebuie să ne gândim la funcțiile de care avem nevoie. În primul rând, avem nevoie de o funcție pentru a genera o cheie de formă, astfel încât să o putem plasa în forma noastră. În fișierul dvs. PHP introduceți următorul cod:

 

Mai sus, vedeți o clasă cu trei părți: două variabile și o funcție. Facem funcția privată, deoarece această funcție va fi utilizată numai de către noi producțiefuncții pe care le vom crea ulterior. În cele două variabile, vom stoca cheile de formă. Acestea sunt, de asemenea, private deoarece pot fi folosite numai de funcțiile din cadrul clasei noastre.

Acum, trebuie să ne gândim la o modalitate de a genera cheia noastră de formă. Deoarece cheia de formular trebuie să fie unică (altfel nu avem nici o securitate), folosim o combinație a adresei IP a utilizatorilor pentru a lega cheia unui utilizator, mt_rand () pentru ao face unică și funcția uniqid () pentru ao face chiar mai unică. De asemenea, criptăm aceste informații cu md5 () pentru a crea un hash unic pe care îl putem introduce apoi în paginile noastre. Pentru că am folosit md5 (), un utilizator nu poate vedea ce am folosit pentru a genera cheia. Întreaga funcție:

 // Funcția de generare a funcției private cheie generateKey () // Obține adresa IP a utilizatorului $ ip = $ _SERVER ['REMOTE_ADDR']; // Folosim mt_rand () în loc de rand (), deoarece este mai bine să generăm numere aleatorii. // Folosim "adevărat" pentru a obține un șir mai lung. // Vezi http://www.php.net/mt_rand pentru o descriere precisă a funcției și mai multe exemple. $ uniqid = uniqid (mt_rand (), adevărat); // returnați returnarea hash-ului md5 ($ ip. $ Uniqid); 

Introduceți codul de mai sus în secțiunea dvs. formkey.class.php fişier. Înlocuiți funcția cu noua funcție.

Pasul 3: Introducerea unei chei de formular în formularul nostru

Pentru acest pas, vom crea o nouă funcție care va afișa un câmp HTML ascuns cu cheia noastră de formular. Funcția constă în trei etape:

  1. Generați o cheie formulară cu ajutorul funcției generateKey ().
  2. Stocați cheia de formular în variabila noastră $ formKey și într-o sesiune.
  3. Ieșiți câmpul HTML.

Ne numim funcția noastră outputKey () și să o facă publică, pentru că trebuie să o folosim în afara clasei noastre. Funcția noastră va numi funcția privată generateKey () pentru a genera o nouă cheie de formular și ao salva local într-o sesiune. În cele din urmă, vom crea codul XHTML. Acum adăugați următorul cod în clasa PHP:

 // Funcția de ieșire a cheii formularului outputKey () // Generați cheia și păstrați-o în interiorul clasei $ this-> formKey = $ this-> generateKey (); // Stocați cheia de formular în sesiunea $ _SESSION ['form_key'] = $ this-> formKey; // Efectuați ecoul cheii formularului "formKey. "" /> ";

Acum, vom adăuga cheia de formular în formularul nostru de autentificare pentru ao asigura. Trebuie să includem clasa în index.php fişier. De asemenea, trebuie să începem sesiunea deoarece clasa noastră folosește sesiuni pentru a stoca cheia generată. Pentru aceasta, adăugăm următorul cod deasupra etichetei doctype și head:

 

Codul de mai sus este destul de explicativ. Pornim sesiunea (pentru că stocăm cheia de formular) și încărcăm fișierul de clasă PHP. După aceea, începem clasa cu new formKey (), aceasta va crea clasa noastră și va stoca în $ formKey. Acum trebuie doar să modificăm formularul nostru astfel încât acesta să conțină cheia formularului:

 
outputKey (); ?>
tipul de intrare = "parola" nume = "parola" />

Și asta e tot! Pentru că am creat funcția outputKey (), trebuie doar să o includem în forma noastră. Putem folosi cheile formularului în orice formă prin adăugarea outputKey (); ?> Acum revedeți doar sursa paginii dvs. web și puteți vedea că există o cheie de formă atașată la formular. Singurul pas rămas este validarea cererilor.

Pasul 4: Validarea

Nu vom valida întregul formular; numai cheia formularului. Validarea formularului este de bază PHP și tutoriale pot fi găsite pe tot webul. Să validăm cheia de formular. Deoarece funcția noastră "generateKey" suprascrie valoarea sesiunii, adăugăm un constructor în clasa noastră PHP. Un constructor va fi chemat când clasa noastră este creată (sau construită). Constructorul va stoca cheia anterioară din clasă inainte de noi creăm un nou; așa că vom avea întotdeauna cheia formularului anterior pentru validarea formularului nostru. Dacă nu am făcut acest lucru, nu am putea să validăm cheia de formular. Adăugați următoarea funcție PHP la clasa dvs.:

 // Constructorul stochează cheia de formă (dacă există) în variabila noastră de clasă. funcția __construct () // Avem nevoie de cheia anterioară pentru a o stoca dacă (isset ($ _ SESSION ['form_key'])) $ this-> old_formKey = $ _SESSION ['form_key']; 

Un constructor ar trebui să fie întotdeauna numit __construi(). Atunci când se cheamă constructorul, verificăm dacă este setată o sesiune și dacă este așa, o păstrăm local pe site-ul nostru old_formKey variabil.

Acum suntem capabili să validăm cheia noastră de formă. Creăm o funcție de bază în clasa noastră care validează cheia de formular. Această funcție ar trebui să fie și publică, pentru că o vom folosi în afara clasei noastre. Funcția va valida valoarea POST a cheii de formular față de valoarea stocată a cheii de formular. Adăugați această funcție la clasa PHP:

 // Funcția care a validat cheia formularului Validarea funcției publice POST () // Folosim vechea formKey și nu noua versiune generată dacă ($ _ POST ['form_key'] == $ this-> old_formKey) // cheia este validă, returnează adevărat. return true;  altfel // Cheia este nevalidă, return false. return false; 

În index.php, validăm cheia de formular utilizând funcția pe care tocmai am creat-o în clasa noastră. Desigur, validăm doar după o cerere POST. Adăugați următorul cod după $ formKey = new formKey ();

 $ error = 'Nici o eroare'; // Cererea este? dacă $ _ SERVER ['REQUEST_METHOD'] == 'post') // Validează cheia formularului dacă ! isset ($ _ POST ['form_key']) cheia este nevalidă, se afișează o eroare $ error = 'eroare cheie formulă!';  altceva // Efectuați restul validării aici $ error = 'Nici o eroare cheie de formă!'; 

Am creat o variabilă $ eroare care stochează mesajul nostru de eroare. Dacă a fost trimisă o solicitare POST, validăm formula noastră $ FormKey-> valida (). Dacă aceasta se întoarce falsă, cheia de formular este nevalidă și afișăm o eroare. Rețineți că validăm doar cheia de formular - vi se cere să validați singur restul formularului.

În HTML, puteți plasa următorul cod pentru a afișa mesajul de eroare:

 

Acest lucru va ecou $ eroare dacă este setată.

Dacă porniți serverul și mergeți la index.php, veți vedea forma noastră și mesajul "Nici o eroare". Când trimiteți un formular, veți vedea mesajul "Eroare cheie de formă" deoarece este o solicitare POST validă. Încercați acum să reîncărcați pagina și să acceptați atunci când browserul dvs. cere ca datele POST să fie trimise din nou. Veți vedea că scriptul nostru declanșează un mesaj de eroare: "Eroare cheie formulă!" Formularul dvs. este acum protejat împotriva introducerii de pe alte site-uri web și a erorilor cu reîncărcări de pagină! Eroarea este afișată și după o reîmprospătare deoarece o nouă cheie de formular a fost generată după ce am trimis formularul. Acest lucru este bun deoarece, acum, utilizatorul nu poate posta accidental un formular de două ori.

Codul complet

Iată întregul cod PHP și HTML:

index.php

 validați ()) // Cheia formularului este nevalidă, arătați o eroare $ error = 'Eroare cheie formulă!';  altceva // Efectuați restul validării aici $ error = 'Nici o eroare cheie de formă!'; ?>     Securizarea formularelor cu chei de formă   
outputKey (); ?>

fomrkey.class.php

 old_formKey = $ _SESSION ['form_key'];  // Funcție pentru generarea funcției private cheie generateKey () // Obține adresa IP a utilizatorului $ ip = $ _SERVER ['REMOTE_ADDR']; // Folosim mt_rand () în loc de rand (), deoarece este mai bine să generăm numere aleatorii. // Folosim "adevărat" pentru a obține un șir mai lung. // Vezi http://www.php.net/mt_rand pentru o descriere precisă a funcției și mai multe exemple. $ uniqid = uniqid (mt_rand (), adevărat); // returnați returnarea hash-ului md5 ($ ip. $ Uniqid);  // Funcția de ieșire a funcției publice de tip outputKey () // Generează cheia și păstrează-o în interiorul clasei $ this-> formKey = $ this-> generateKey (); // Stocați cheia de formular în sesiunea $ _SESSION ['form_key'] = $ this-> formKey; // Efectuați ecoul cheii formularului "($ _ POST ['form_key'] == $ // POST ['form_key'] == $ Formularul de validare a cheii de formate Validarea funcției publice a datelor POST () // Folosim vechea formKey și nu noua versiune generată dacă ($ _ POST ['form_key'] == $ acest lucru-> old_formKey) // Cheia este validă, returnează adevărat, returnează adevărat; altceva // Cheia este nevalidă, returnează false, returnează false;?

Concluzie

Adăugarea acestui cod la orice formular important de pe site-ul dvs. web va crește dramatic securitatea formularului. Ea chiar oprește problemele răcoritoare, așa cum am văzut la pasul 4. Deoarece cheia de formular este valabilă doar pentru o cerere, nu este posibilă o dublă postare.

Acesta a fost primul meu tutorial, sper ca iti place si il folosesti pentru a-ti imbunatati securitatea! Vă rog să-mi spuneți gândurile, prin intermediul comentariilor. Aveți o metodă mai bună? Anunță-ne.

Citirea în continuare

  • WordPress utilizează de asemenea cheile formularului (denumirea nonceselor): Wordpress Nonces
  • Șapte obiceiuri pentru scrierea de aplicații PHP securizate
  • Urmăriți-ne pe Twitter sau abonați-vă la feed-ul RSS NETTUTS pentru mai multe tutoriale și articole zilnice de dezvoltare web.


Cod