Sanitizarea datelor și validarea cu WordPress

Securitatea adecvată este esențială pentru păstrarea în siguranță a site-ului dvs. sau a temei sau a plug-in-urilor. O parte din aceasta înseamnă validarea adecvată a datelor și igienizarea. În acest articol vom examina de ce acest lucru este important, ce trebuie făcut și ce funcții oferă WordPress pentru a ajuta.

Deoarece se pare că există interpretări diferite cu privire la termenii "validare", "scăpare" și "dezintoxicare", voi clarifica mai întâi ce vreau să spun prin ele în acest articol:

  • Validare - Acestea sunt verificările care se execută pentru a vă asigura datele pe care le faceți avea este ceea ce este ar trebui să fi. De exemplu, un e-mail arată ca o adresă de e-mail, că o dată este o dată și că un număr este (sau este exprimat ca) un întreg
  • Sanitizare / evadare - Acestea sunt filtrele care se aplică datelor pentru ao face "sigură" într-un anumit context. De exemplu, pentru a afișa codul HTML într-o zonă de text, ar fi necesar să înlocuiți toate etichetele HTML cu echivalentele entității

De ce sanitizarea este importantă?

Când datele sunt incluse într-un anumit context (să spunem într-un document HTML) - aceste date ar putea fi interpretate greșit ca un cod pentru acel mediu (de exemplu, cod HTML). Dacă aceste date conțin cod rău intenționat, atunci utilizarea acelor date fără a le dezinfecta înseamnă că acel cod va fi executat. Codul nu trebuie să fie neapărat rău pentru ca acesta să producă efecte nedorite. Misiunea de igienizare este să vă asigurați că orice cod din date nu este interpretat ca un cod - altfel s-ar putea să ajungeți ca școala lui Bobby Tables ...

"Exploatații unei mame" - xkcd

Un exemplu aparent inofensiv ar putea fi pre-umplerea unui câmp de căutare cu termenul curent interogat, folosind unescaped $ _GET [ 's']:

 

Aceasta deschide o vulnerabilitate care ar putea permite javascriptul să fie injectat, de exemplu, înșelând pe cineva în vizită http://yoursite.com?s= "/>. Termenul de căutare "sare" din atributul valoare, iar următoarea parte a datelor este interpretată ca cod și executată. Pentru a preveni acest lucru, WordPress oferă get_search_query care returnează interogarea de căutare dezinfectată. Deși acesta este un exemplu "inofensiv", scenariul injectat ar putea fi mult mai rău intenționat și, în cel mai bun caz, ar fi "rupt" formularul dacă termenii de căutare conțin citate duble.

Modul în care acest cod rău intenționat (sau altfel) s-ar fi putut găsi pe site-ul dvs. nu reprezintă preocuparea aici - ci mai degrabă este împiedicarea executării acestuia. De asemenea, nu putem face presupuneri cu privire la natura acestui cod nedorit sau la intenția sa - ar fi putut fi pur și simplu o eroare din partea utilizatorului. Asta mă aduce la conducerea nr. 1 ...


Regula nr. 1: Nu ai încredere în nimeni

Este o maximă comună care este folosită în ceea ce privește dezinfecția datelor și este una bună. Ideea este că nu trebuie să presupuiți că toate datele introduse de utilizator sunt sigure. Nici nu trebuie să presupuiți că datele pe care le-ați recuperat din baza de date sunt sigure - chiar dacă ați făcut-o "în siguranță" înainte de a le introduce acolo. De fapt, dacă datele pot fi considerate "sigure" nu are sens fără context. Uneori, aceleași date pot fi utilizate în mai multe contexte din aceeași pagină. Titlurile, de exemplu, pot conține în siguranță citate sau ghilimele duble atunci când sunt în interiorul etichetelor antetului - dar vor cauza probleme dacă sunt utilizate (fără ieșire) într-un atribut de titlu al unei etichete de legătură. Deci, este inutil să se facă datele "în siguranță" atunci când se adaugă la baza de date, deoarece este adesea imposibil să se facă datele în siguranță pentru toate contextele simultan. (Desigur, trebuie să fie în siguranță pentru a adăuga la baza de date - dar vom ajunge la asta mai târziu).

Chiar dacă intenționați să utilizați aceste date într-un anumit context, spuneți un formular, este încă inutil să dezinstalați datele atunci când scrieți în baza de date deoarece, conform Regula 1, nu puteți avea încredere că este încă sigur când scoate-o din nou.


Regula nr. 2: Validare la intrare, ieșire la ieșire

Acesta este maximul procedural care stabilește când trebuie să validezi datele și când le dezinfectezi. Pur și simplu puneți - validați datele (verificați ce ar trebui să fie - și că este "valabil") de îndată ce îl primiți de la utilizator. Când veniți să utilizați aceste date, de exemplu atunci când le scoateți, trebuie să scăpați (sau să-l dezinfectați). Ce formă are această delimitare, depinde în întregime de contextul în care o utilizați.

Cel mai bun sfat este să faceți acest lucru "târziu": evitați datele dvs. imediat înainte de a le utiliza sau a le afișa. În acest fel puteți avea încredere că datele dvs. au fost dezinfectate corespunzător și nu trebuie să vă amintiți dacă datele au fost verificate anterior.


Regula nr. 3: Încredere WordPress

S-ar putea să vă gândiți "Ok, validați înainte de a scrie la baza de date și de a vă dezinfecta atunci când o utilizați. Dar nu trebuie să vă asigurați că datele sunt în siguranță pentru a scrie în baza de date?". În general, da. Atunci când adăugați date într-o bază de date sau pur și simplu utilizați o intrare pentru a interacționa cu o bază de date, va trebui să scăpați de date incase conținea orice comenzi SQL. Dar asta mă aduce la regula nr. 3, una care zboară în fața Regula nr. 1: Trust WordPress.

Într-un articol anterior, am luat informația utilizatorului (trimis de la un formular de căutare prin AJAX) și l-am folosit direct get_posts () pentru a returna postările care corespundeau acelei interogări de căutare:

 $ posts = get_posts (array ('s' => $ _ CERERE ['termen']));

Un cititor observativ a observat că nu am efectuat nici o dezintoxicare - și au avut dreptate. Dar nu aveam nevoie. Când utilizați funcții de nivel înalt, cum ar fi get_posts (), nu trebuie să vă faceți griji cu privire la dezinfectarea datelor - deoarece interogările bazei de date sunt toate scapate în mod corespunzător de interfețele WordPress. Este o chestiune diferită dacă utilizați o interogare SQL directă - dar vom examina acest lucru într-o secțiune ulterioară. În mod similar, funcții cum ar fi titlul(), the_permalink (), continutul() etc. să efectueze propriile igienizări (pentru contextul corespunzător).


Data validarii

Când primiți datele introduse de un utilizator, este important să valida aceasta. (API-ul pentru setări, acoperit în această serie, vă permite să specificați o funcție de apel invers pentru a face exact acest lucru). Datele nevalide sunt fie auto-corectate, fie procesul este anulat și utilizatorul este returnat în formular pentru a încerca din nou (sperăm că există un mesaj de eroare adecvat). Preocuparea nu este siguranta, ci mai degraba valabilitate - daca o faci bine, WordPress va avea grija de adaugarea in siguranta a datelor in baza de date. Ce înseamnă "valid" înseamnă de la tine - ar putea însemna o adresă de e-mail validă, un număr întreg pozitiv, un text cu o durată limitată sau unul dintr-o serie de opțiuni specificate. Cu toate acestea, aveți scopul de a determina validitatea, WordPress oferă o mulțime de funcții care vă pot ajuta.

numere

Când se așteaptă date numerice, este posibil să se verifice dacă datele sunt "o formă de număr", de exemplu is_int sau is_float. De obicei, este suficient să aruncați datele numeric cu: intval sau floatval.

Dacă trebuie să vă asigurați că numărul este umplut cu zerouri în frunte, WordPress furnizează funcția zeroise (). Care are următorii parametri:

  • Număr - numărul la pad
  • Prag - numărul de cifre la care numărul va fi căptușit

De exemplu:

 echo zeroise (70,4); // Prints 0070

E-mail-uri

Pentru a verifica validitatea mesajelor e-mail, WordPress are is_email () funcţie. Această funcție utilizează verificări simple pentru a valida adresa. De exemplu, verifică dacă conține simbolul "@", că acesta are mai mult de 3 caractere, domeniul conține numai cifre alfanumerice și cratime și așa mai departe. Evident, nu verifică dacă adresa de e-mail există. Presupunând că adresa de e-mail a trecut verificările, aceasta este returnată, altfel "false" este returnat.

 $ email = is_email (someone@e=ample.com); // $ email este setat la false. $ email = is_email ('[email protected]'); // $ e-mail este setat la '[email protected]'.

HTML

Adesea ați dori să permiteți numai niste Etichete HTML în datele dvs. - de exemplu, în comentariile postate pe site-ul dvs. WordPress oferă o familie de funcții ale formularului wp_kses_ * (KSES Strips Scripts Evil). Aceste funcții elimină (unele subseturi) de etichete HTML și pot fi folosite pentru a se asigura că legăturile din date sunt de protocoale specificate. De exemplu, wp_kses () funcția acceptă trei argumente:

  • conţinut - (șir) Conținut pentru filtrarea prin kses
  • allowed_html - Un tablou în care fiecare cheie este un element HTML permis și valoarea este o matrice de atribute admise pentru acel element
  • allowed_protocols - Opțional. Protocolul permis în link-uri (de exemplu http, mailto, a hrani etc)

wp_kses () este o funcție foarte flexibilă, permițându-vă să eliminați etichetele nedorite sau doar atributele nedorite din etichete. De exemplu, pentru a permite doar sau (dar permiteți numai atributul href):

 $ content = "Clic aici pentru a vizita  wptuts+ "; echo wp_kses ($ content, array ('strong' => array (), 'a' => array ('href'));  wptuts+ ": Faceți clic aici pentru a vizita  wptuts+ 

Desigur, specificarea fiecărei etichete permise și a fiecărui atribut permis poate fi o sarcină laborioasă. Deci, WordPress oferă alte funcții care vă permit să utilizați wp_kses cu etichete și protocoale permise în prealabil - și anume cele utilizate pentru validarea postărilor și comentariilor:

  • wp_kses_post ()
  • wp_kses_data ()

Funcțiile de mai sus sunt utile în asigurarea faptului că HTML-ul primit de la utilizator conține elemente albe listate. Odată ce am făcut acest lucru, am dori să ne asigurăm că fiecare etichetă este echilibrată, adică fiecare etichetă de deschidere are eticheta de închidere corespunzătoare. Pentru aceasta putem folosi balanceTags (). Această funcție acceptă două argumente:

  • conţinut - Conținut pentru filtrarea și echilibrarea etichetelor din
  • forța de echilibru - Adevărat sau fals, pentru a forța echilibrarea etichetelor
 // Conținut cu închidere lipsă  tag $ content = "Clic aici pentru a vizita  wptuts + "echo balanceTags ($ content, true), // Imprimă HTML" Faceți clic aici pentru a vizita  wptuts+ "

Numele de fișiere

Dacă doriți să creați un fișier într-unul din directoarele site-ului dvs., veți dori să vă asigurați că numele fișierului este valabil și legal. De asemenea, doriți să vă asigurați că numele fișierului este unic pentru acel director. Pentru acest WordPress oferă:

  • sanitize_file_name (nume fișier $) - santifică (sau validează) numele de fișier prin eliminarea caracterelor ilegale în nume de fișiere în anumite sisteme de operare sau care ar necesita evadarea la linia de comandă. Înlocuiește spațiile cu liniuțe și liniuțe consecutive cu o singură linie și elimină perioadele, liniuțele și sublinierile de la începutul și sfârșitul numelui de fișier.
  • wp_unique_filename ($ dir, $ filename) - returnează un unic (pentru director $ dir), nume fișier dezinfectat (utilizează sanitize_file_name).

Datele din câmpurile de text

Când primiți date introduse într-un câmp de text, probabil că doriți să eliminați spații albe, file și linii, precum și să eliminați toate etichetele. Pentru acest WordPress prevede sanitize_text_field ().

Chei

WordPress oferă de asemenea sanitize_key. Aceasta este o funcție foarte generică (și ocazional utilă). Pur și simplu asigură faptul că variabila returnată conține numai cifre alfanumerice, liniuțe și subliniere.


Sanitizarea datelor

În timp ce validarea se referă la asigurarea valabilității datelor - sanitizarea datelor se referă la realizarea acestora sigur. În timp ce unele dintre funcțiile de validare menționate mai sus ar putea fi utile pentru a vă asigura că datele sunt sigure - în general, nu este suficientă. Chiar și datele "valide" ar putea fi nesigure în anumite contexte.


Regula nr. 4: Siguranța datelor este în legătură cu contextul

Pur și simplu nu te poți întreba "Cum pot face aceste date în siguranță?". În schimb, ar trebui să întrebați, "Cum pot face aceste date în siguranță pentru utilizarea în X".

Pentru a ilustra acest punct, să presupunem că aveți un widget cu o textarea în care intenționați să permiteți utilizatorului să introducă anumite coduri HTML. Să presupunem că ei intră apoi:

  Salut Lume

Acest lucru este perfect valabil și sigur în HTML - cu toate acestea când faceți clic pe salvare, constatăm că textul a sărit din textarea. Codul HTML nu este sigur ca valoare pentru textarea:

Ceea ce este sigur de utilizat într-un singur context nu este neapărat sigur în altul. Ori de câte ori utilizați sau afișați date, trebuie să aveți în vedere ce forme de dezinfectare trebuie făcute pentru a face utilizarea acestor date în siguranță. Acesta este motivul pentru care WordPress oferă adesea mai multe funcții pentru același conținut, de exemplu:

Toți aceștia efectuează dezinfectarea necesară pentru un anumit context - și dacă le folosiți, trebuie să fiți sigur că le folosiți pe cel corect. Uneori, totuși, vom avea nevoie să realizăm propriile noastre dezinsecții - adesea pentru că avem intrări personalizate dincolo de titlul standard al postului, permalink-ului, conținutului etc. pe care WordPress îl ocupă pentru noi.

Escaping HTML

Când imprimați variabilele la pagină, trebuie să fim atenți la modul în care browserul le va interpreta. Să luăm în considerare următorul exemplu:

 

Presupune $ title = . Mai degrabă decât afișarea codului HTML

De fapt, dacă faceți acest lucru, ar trebui aproape să folosiți acest lucru wp_localize_script () - care se ocupă de dezintoxicare pentru dvs. (Dacă cineva se poate gândi la un motiv pentru care ar fi mai bine să folosiți metoda de mai sus, aș vrea să o aud).

Cu toate acestea, pentru a face exemplul de mai sus sigur, puteți utiliza funcția esc_js funcţie:

 

Escaping Textarea

Când se afișează conținutul într-o textare, esc_html nu este suficientă pentru că nu dublează entitățile de codare. De exemplu:

 text îndrăzneţ'?> 

$ var tipărite în textarea vor apărea ca:

 text îndrăzneţ

Mai degrabă decât codarea & la fel de & în Etichete.

Pentru acest WordPress prevede esc_textarea, care este aproape identic cu esc_html, dar are entități dublate de codare. În esență, este puțin mai mult decât un înveliș pentru htmlspecialchars. În acest exemplu:

 text îndrăzneţ'?> 

Antispambot

Afișarea adreselor de e-mail de pe site-ul dvs. îi lasă să fie predispuse la colecționari de e-mail. O metodă simplă este de a ascunde adresa de e-mail. WordPress oferă antispambot, care codifică părți aleatoare ale adresei de e-mail în entitățile HTML (și echivalente hexazecimale dacă $ mailto = 1). În fiecare pagină încărcați codificarea ar trebui să fie diferită și în timp ce adresa returnată se redresează corect în browser, ar trebui să apară ca gobbledygook la spambots. Funcția acceptă două argumente:

  • e-mail - adresa pentru a obfuscate
  • mailto - 1 sau 0 (1 dacă folosiți protocolul mailto într-o etichetă de legătură)
 $ email = "[email protected]"; $ e-mail = sanitize_email ($ email); echo '' .antispambot ($ email). ' „;

Cheile de interogare

Dacă doriți să adăugați (sau să eliminați) variabile dintr-un șir de interogări (acest lucru este foarte util dacă doriți să permiteți utilizatorilor să selecteze o comandă pentru mesajele dvs.), cea mai sigură și mai ușoară cale este de a utiliza add_query_arg și remove_query_arg. Aceste funcții tratează toate escapingurile necesare pentru argumentele și valorile lor pentru a fi utilizate în URL.

add_query_arg acceptă două argumente:

  • parametrii de interogare - o matrice asociativă de parametri -> valori
  • URL-ul - adresa URL pentru a adăuga parametrii și valorile acestora la. Dacă este omisă, se folosește adresa URL a paginii curente

remove_query_arg acceptă, de asemenea, două argumente, primul este o serie de parametri pentru a elimina, al doilea este ca mai sus.

 // Dacă suntem la www.example.com/wp-admin/edit.php?post_type=book $ query_params = array ('page' => 'my-bage'); $ url = add_query_arg ($ query_params); // ar stabili $ url pentru a fi: // www.example.com/wp-admin/edit.php?post_type=book&page=my-page

Validare și igienizare

După cum sa menționat anterior, dezintoxicarea nu are prea mult sens fără un context - deci este destul de lipsit de sens să dezinstalați datele când scrieți în baza de date. De multe ori, trebuie să păstrați datele oricum în format brut și, în orice caz - regula nr. 1 dictează că trebuie să ne întoarcem întotdeauna la ieșire.

Validarea datelor, pe de altă parte, ar trebui făcută de îndată ce a fost primită și înainte de a fi scrisă în baza de date. Ideea este că datele "nevalide" trebuie fie să fie auto-corectate, fie să fie marcate cu datele, iar datele trebuie să fie valide doar în baza de date.

Acestea fiind spuse - este posibil să doriți și să efectuați validarea când sunt afișate și datele. De fapt, uneori, "validarea" va asigura, de asemenea, că datele sunt sigure. Dar prioritatea aici este în ceea ce privește siguranța și ar trebui să evitați validarea excesivă care ar fi rulată la încărcarea fiecărei pagini ( wp_kses_ * funcțiile, de exemplu, sunt foarte scumpe de efectuat).


Evadarea bazei de date

Când utilizați funcții cum ar fi get_posts sau clase, cum ar fi WP_Query și WP_User_Query, WordPress are grijă de dezinfectarea necesară în interogarea bazei de date. Cu toate acestea, atunci când se recuperează date dintr-o tabelă personalizată sau în alt mod se efectuează o interogare SQL directă în baza de date - igienizarea adecvată este apoi la dvs. WordPress, cu toate acestea, oferă o clasă utilă, $ wpdb clasa, care ajută la scăparea interogărilor SQL.

Să considerăm acest lucru "SELECTAȚIcomanda, unde $ vârstă și $ firstname sunt variabile care stochează o vârstă și un nume pe care îl interogăm:

 SELECT * WHERE vârstă = "$ vârstă" ȘI primul nume = '$ primul nume'

Nu am scăpat de aceste variabile, deci ar putea fi injectate eventualele comenzi suplimentare. Împrumutând exemplul xkcd de mai sus:

 $ age = 14; $ firstname = "Robert"; DROP TABLE Studenți; "; $ sql = "SELECT * WHERE vârstă =" $ vârstă "ȘI primul nume = '$ primul nume';"; $ results = $ wpdb-> interogare

Se va executa ca comandă (comenzi):

 SELECTARE * WHERE vârstă = "14" ȘI prenume = "Robert"; DROP TABLE Studenți; ';

Și ștergeți întreaga tabelă a studenților.

Pentru a preveni acest lucru, putem folosi $ Wpdb-> pregăti metodă. Aceasta acceptă doi parametri:

  • Comanda SQL ca șir, unde variabilele de șir sunt înlocuite de substituent % s și numerele zecimale sunt înlocuite cu substituentul % d și plutește prin % f
  • O serie de valori pentru substituenții de mai sus, în ordinea în care apar în interogare

În acest exemplu:

 $ age = 14; $ firstname = "Robert"; DROP TABLE Studenți; "; $ sql = $ wpdb-> prepare ('SELECT * WHERE vârstă =% d AND firstname =% s;', array ($ age, $ firstname)); $ rezultatele = $ wpdb-> get_results ($ sql);

Interogarea SQL scăpată ($ sql în acest exemplu) pot fi apoi utilizate cu una dintre metodele:

  • $ Wpdb-> get_row ($ sql)
  • $ Wpdb-> get_var ($ sql)
  • $ Wpdb-> get_results ($ sql)
  • $ Wpdb-> get_col ($ sql)
  • $ Wpdb-> interogare ($ sql)

Introducerea și actualizarea datelor

Pentru inserarea sau actualizarea datelor, WordPress face viața mai ușoară prin furnizarea de $ Wpdb-> insera () și $ Wpdb-> actualizare () metode.

$ Wpdb-> insera () metoda acceptă trei argumente:

  • Numele tabelului - numele tabelului
  • Date - array de date pentru a introduce ca perechi de coloane-> valoare
  • formate - array de formate pentru valorile corespunzătoare ('% s''% d"sau"% f„)
 $ age = 14; $ firstname = "Robert"; DROP TABLE Studenți; "; $ wpdb-> insert ('Studenți', array ('firstname' => $ firstname, 'age' => age age), array ('% s', '% d'));

$ Wpdb-> actualizare () metoda acceptă cinci argumente:

  • Numele tabelului - numele tabelului
  • Date - array de date pentru actualizare ca perechi de coloane-> valoare
  • Unde - array de date pentru a se potrivi ca perechi de coloane-> valoare
  • Formatul datelor - array de formate pentru valorile de date corespunzătoare
  • În cazul în care Format - set de formate pentru valorile corespunzătoare "unde"
 // Actualizați Robert '; DROP TABLE Studenții; la Bobby $ oldname = "Robert"; Studenți la DROP TABLE; "; $ newname = "Bobby"; $ wpdb-> update ('Studenți', array ('firstname' => $ newname), array ('firstname' => $ oldname), array ('% s');

Amandoua $ Wpdb-> insera () si $ Wpdb-> actualizare () Metodele efectuează toate dezinfecția necesară pentru scrierea în baza de date.

Asemenea declarații

Deoarece $ Wpdb-> pregăti foloseste metoda % pentru a distinge între deținătorii locului, trebuie să se acorde atenție atunci când se utilizează % wildcard în instrucțiunile SQL LIKE. Codul sugerează că le scăpa cu o secundă %. Alternativ, puteți să scăpați de termenul de căutare like_escape și apoi adăugați macheta % după caz, înainte de a include acest lucru în interogare folosind metoda de pregătire. De exemplu:

 $ Varsta = 14; $ firstname = "Robert"; DROP TABLE Studenți; "; SELECT * WHERE vârstă = $ vârstă (primul nume LIKE '% $ prima nume%');

Ar fi sigur în:

 $ Varsta = 14; $ firstname = "Robert"; DROP TABLE Studenți; "; SELECT * WHERE vârstă = $ vârstă AND (prima nume LIKE '% $ prima nume%'); $ query = $ wpdb-> prepare ('SELECT * WHERE vârstă =% d AND (prima nume LIKE% s);

rezumat

Aceasta nu este o listă exhaustivă a funcțiilor disponibile pentru validare și dezintoxicare, dar ar trebui să acopere marea majoritate a cazurilor de utilizare. O mulțime de aceste (și alte) funcții pot fi găsite în /wp-includes/formatting.php și aș recomanda cu fermitate să sapi în codul de bază și să aruncați o privire asupra modului în care WordPress core corectează validarea și dezinfectarea datelor.

Ați găsit acest articol util? Aveți alte sugestii privind cele mai bune practici pentru validarea și dezinfectarea datelor în WordPress? Spuneți-ne în comentariile de mai jos.

Cod