prevenirea injecțiilor SQL în PHP (și alte vulnerabilități)

dacă ați fost în jurul valorii de dezvoltare web pentru un timp, ați auzit aproape sigur termenul „injecție SQL” și unele povești terifiante despre asta.

PHP, ca multe alte limbi, nu este imun la acest tip de amenințare, care poate fi într-adevăr foarte periculos. Dar, din fericire, protejarea site-urilor dvs. web împotriva injecției SQL și a altor amenințări similare este ceva către care puteți face pași tangibili.

în această postare, veți afla ce este injecția SQL, care sunt consecințele unui atac reușit, cum un atacator poate profita de codul PHP vulnerabil, ce puteți face pentru a-l preveni și ce instrumente puteți utiliza pentru a detecta părțile codului dvs. care ar putea fi supuse acestui tip de amenințare. În plus, veți afla despre alte câteva vulnerabilități comune de care ar trebui să fiți conștienți pentru a crea aplicații mai sigure.

cum funcționează o injecție SQL?

primul lucru pe care trebuie să-l știți pentru a vă proteja codul de injecția SQL este să înțelegeți cum ar putea fi exploatat de un atacator.

ideea din spatele exploatării este destul de simplă: un atacator rulează cod SQL rău intenționat în baza dvs. de date prin intermediul aplicației.

cum ar putea cineva să realizeze asta? Abuzând de intrările aplicației dvs.

să ne uităm la un exemplu simplu. Să presupunem că aveți o aplicație care prezintă o listă de nume de utilizator, unde fiecare utilizator are un link către detaliile sale astfel:

și apoi, în fișierul user_details.php, aveți acest:

<?php $sql = "SELECT * FROM user WHERE id = ".$_GET;

dacă utilizatorul acționează conform așteptărilor și face clic pe numele unui utilizator, adresa URL a solicitării va arăta astfel: http://domain.com/user_details.php?id=8.

deci, ce e în neregulă cu ea?

valoarea $sql va fi șirul "SELECT * FROM user WHERE id = 8" și interogarea va rula foarte bine.

problema se află în porțiunea cursivă a acestei propoziții: dacă utilizatorul acționează așa cum este de așteptat și face clic pe numele unui utilizator, adresa URL a cererii va arăta astfel:

http://domain.com/user_details.php?id=8.

ce se întâmplă dacă utilizatorul nu acționează așa cum era de așteptat?

ce se întâmplă dacă cineva ar produce un URL care trimite altceva decât un număr ca ID?

URL-uri fabricate

dacă URL-ul ar fi ceva de genul http://domain.com/user_details.php?id=Peanuts, șirul SQL rezultat ar fi: "SELECT * FROM user WHERE id = Peanuts".

în acest caz, problema ar fi pentru utilizator. Interogarea ar eșua pur și simplu și, într-un scenariu cel mai rău caz, utilizatorul ar vedea un fel de mesaj ciudat.

dar dacă URL-ul arăta mai mult ca acesta:

http://domain.com/user_details.php?id=1+OR+1%3B? (Acesta este rezultatul urlencode('1 OR 1;'), apropo.)

în acest caz, SQL rezultat ar fi "SELECT * FROM user WHERE id = 1 OR 1;". Asta înseamnă că rezultatul interogării ar fi fiecare utilizator din Baza de date în loc de doar utilizatorul al cărui ID este egal cu 1. Au.

dar asta nu este încă prea rău, nu?

acum să încercăm un exemplu mai extrem.

să presupunem că URL-ul a fost ceva de genul

http://domain.com/user_details.php?id=1%27%3B+DROP+TABLE+users%3B--+, care se traduce în id=1; DROP TABLE users;--, producând în mod eficient această comandă SQL:

"SELECT * FROM users WHERE id = 1; DROP TABLE users;-- ". Și dacă executați această interogare … mare au.

în cazul în care nu sunteți 100% familiarizat cu sintaxa SQL, DROP TABLE ar șterge complet tabelul. Ar fi ca și cum n-ar fi existat niciodată.

desigur, o copie de rezervă recentă ar ajuta la reducerea daunelor, dar totuși. Acest lucru este rău.

dacă doriți să aflați mai multe despre acest tip de atac, există o postare excelentă aici.

dar cred că sunt destule vești proaste. Să trecem la un loc mai vesel: cum puteți preveni aceste tipuri de injecții SQL în aplicațiile dvs.

cum să preveniți injecțiile SQL în PHP

după cum ați văzut, problema este atunci când un atacator are capacitatea de a rula codul SQL fără ca dvs. să fiți conștienți de el.

această situație se prezintă ca o consecință a faptului că interogările au fost create din mers prin concatenarea șirurilor și includ date colectate din Intrări externe (de obicei, intrări de utilizator, dar și alte surse externe, cum ar fi fișiere, răspunsuri la apeluri API și așa mai departe).

deci, pentru a preveni această vulnerabilitate în codul dvs., trebuie să remediați sursele potențialelor probleme.

validați intrările

o modalitate simplă de a remedia vulnerabilitatea din exemplul de mai sus ar fi să verificați dacă parametrul ID este ceea ce se așteaptă de fapt de la acesta (adică., un număr întreg pozitiv):

un alt mod de a face acest tip de validare este de a utiliza filtrele încorporate PHP:

<?php
$id = filter_input( INPUT_GET, 'id', FILTER_VALIDATE_INT);

deci, prin validarea intrărilor dvs., împiedicați atacatorii să execute cod rău intenționat alături de al dvs.

nu există o modalitate ușoară de a-i împiedica să încerce, dar atâta timp cât încercările lor nu au succes, sunteți bine să mergeți.

utilizați instrucțiuni pregătite

un alt mod în care vă puteți proteja codul împotriva injecțiilor SQL este utilizarea instrucțiunilor pregătite. Declarațiile pregătite sunt comenzi SQL precompilate.

pot fi utilizate cu o bibliotecă specifică de acces la baze de date (cum ar fi mysqli) sau cu Biblioteca mai generică dop.

să aruncăm o privire la un exemplu folosind mysqli:

dacă încercați acest cod (înlocuind acreditările bazei de date, desigur), veți vedea că, dacă este accesat printr-o adresă URL legală precum http://domain.com/user_details.php?id=1, veți obține același rezultat ca oricare dintre adresele URL rău intenționate de mai sus (care sunt informațiile despre utilizator asociate cu ID 1 și nimic altceva).

dacă preferați să utilizați dop, codul va arăta mai mult astfel:

nu prea mare diferență, nu?

în rezumat, declarațiile pregătite oferă o modalitate excelentă de a preveni injecțiile SQL. De asemenea, ele funcționează de obicei mai bine decât on-the-fly SQL.

acum, că știți instrumentul, trebuie doar să-l utilizați.

cum se detectează codul PHP care este vulnerabil la injecțiile SQL

odată ce vulnerabilitatea este găsită, remedierea acesteia nu este cu adevărat complicată. Dar cum găsiți aceste tipuri de vulnerabilități în codul dvs. în primul rând?

Ei bine, dacă aveți noroc și baza de cod este suficient de mică, o simplă revizuire a codului va face.

dar dacă aplicația dvs. este de dimensiuni medii până la mari, veți avea nevoie de ajutor suplimentar.

un instrument foarte popular (și open-source) pe care îl puteți utiliza în acest scop este sqlmap, un script Python simplu care va încerca să atace orice adresă URL pe care o alimentați și să raporteze constatările sale.

Iată un exemplu de ieșire dintr-o rulare împotriva unui site web bazat pe PHP al meu:

un alt instrument open-source pe care îl puteți utiliza este Arachni, un instrument mai sofisticat care include o interfață grafică web și a fost scris în Ruby.

Iată un exemplu de ieșire din rularea acestuia prin CLI:

dincolo de revizuirea și testarea codului, ar trebui să luați în considerare utilizarea unei soluții RASP, cum ar fi Sqreen, pentru a vă monitoriza mediile de producție pentru a opri executarea oricăror exploatări care trec prin etapele de revizuire și testare.

de ce alte vulnerabilități ar trebui să fiți conștienți?

injecții de cod

injecția SQL este doar un membru al unei familii mai mari de vulnerabilități: injecția de cod.

ideea din spatele diferitelor tehnici de injectare a codului este întotdeauna aceeași. Este vorba de a păcăli o aplicație nevinovată să ruleze cod rău intenționat.

acest lucru se poate face în mai multe moduri.

în PHP, există funcții concepute pentru a emite pur și simplu comenzi direct în sistemul de operare, cum ar fi funcția exec.

Iată un exemplu simplu al modului în care acest lucru ar putea fi exploatat:

<?php
exec( 'cp uploads/'.$_GET.' /secure/');

dacă cineva ar solicita http://domain.com/exec.php?file=a.txt%3B+rm+-Rf+%2A+%23, rezultatul ar fi executarea acestei comenzi:

cp uploads/a.txt; rm -Rf * # /secure/

și acest lucru ar putea șterge întregul disc de pe server—intrarea nevalidată lovește din nou!

Cross-site scripting

o altă vulnerabilitate foarte comună este cross-site scripting (XSS). În acest caz, victima este utilizatorul care vizitează site-ul dvs.

XSS este atunci când un atacator injectează cod JavaScript rău intenționat într-un formular HTML obișnuit, care va fi ulterior redat de browserul altui utilizator.

Uită-te la acest script PHP:

<?php
echo "<html><p>Hello {$_GET}!</p></html>";

în mod clar, intenția aici este de a crea o pagină simplă care să întâmpine utilizatorul.

dar când răi ajunge la ea, ceea ce îi împiedică să solicite

http://domain.com/greet.php?name=Mauro%3Cscript+language%3D%22javascript%22%3Ealert%28%22You+are+hacked%21%22%29%3B%3C%2Fscript%3E? Această solicitare va produce următorul HTML ca ieșire:

<html><p>Hello Mauro<script language="javascript">alert("You are hacked!");</script></p></html>

acesta este în mod clar un exploit foarte naiv—la urma urmei, care este răul în a arăta cuiva un simplu „ești hacked!”mesaj? Dar lucrurile pot deveni destul de serioase cu puțină imaginație. Rețineți că fiecare solicitare făcută unui server include cookie-ul de sesiune, astfel încât această vulnerabilitate poate fi vinovatul din spatele deturnării sesiunilor utilizatorilor.

apoi, din nou, în timp ce problemele arată urât, remedierile sunt foarte simple: este vorba despre validare și igienizare.

în cazul XSS, un apel simplu la htmlentities înainte de a produce ieșirea reală va face.

remedierea vs.detectarea vulnerabilităților de securitate

după cum ați văzut în acest post, remedierea vulnerabilităților de securitate—atât injecții SQL, cât și alte tipuri—nu este principala provocare. Realizând că codul dvs. este vulnerabil și unde poate fi exploatat, este. Aveți câteva opțiuni aici:

  • au foarte puternic disciplina de codificare
  • testați aplicațiile bine pentru probleme de securitate
  • pârghie instrumente de monitorizare și protecție pentru a preveni exploit și de a primi alerte în timp util

care o alegeți este de până la tine. Important este să fii atent la aceste probleme și să acționezi pe baza acestor cunoștințe. Stai în siguranță.

Leave a Reply

Adresa ta de email nu va fi publicată.