Čo je SQL Injection a ako zabrániť v PHP aplikáciách?

Takže si myslíte, že vaša databáza SQL je výkonná a bezpečná pred okamžitým zničením? SQL Injection nesúhlasí!


Áno, hovoríme o okamžitej deštrukcii, pretože tento článok nechcem otvoriť obvyklou chromou terminológiou „sprísnenia zabezpečenia“ a „zabránenia škodlivému prístupu“. SQL Injection je taký starý trik v knihe, že každý, každý vývojár, o tom vie veľmi dobre a dobre si uvedomuje, ako tomu zabrániť. Až na to, že sa raz prekĺznu a výsledky nemôžu byť ničím ničivým.

Ak už viete, čo je SQL Injection, môžete preskočiť na druhú polovicu článku. Ale pre tých, ktorí práve prichádzajú v oblasti webového vývoja a snívajú o tom, že prevezmú viac vyšších úloh, je určitý úvod v poriadku.

Čo je to SQL Injection?

Kľúčom k porozumeniu SQL Injection je jeho názov: SQL + Injection. Slovo „injekcia“ tu nemá žiadne lekárske významy, ale skôr je to použitie slovesa „injekcia“. Tieto dve slová spoločne vyjadrujú myšlienku zavedenia SQL do webovej aplikácie.

Uvedenie SQL do webovej aplikácie. , , hmmm. , , Nie je to to, čo robíme? Áno, ale nechceme, aby útočník riadil našu databázu. Pochopme to pomocou príkladu.

Povedzme, že vytvárate typický web PHP pre miestny obchod s elektronickým obchodom, takže sa rozhodnete pridať takýto kontaktný formulár:

Tvoje meno

Tvoja správa

Predpokladajme tiež, že súbor send_message.php ukladá všetko do databázy, aby si majitelia obchodu mohli čítať správy používateľov neskôr. Môže mať takýto kód:

<?php

$ name = $ _POST [‘name’];
$ message = $ _POST [‘message’];

// skontrolujte, či tento používateľ už nemá správu
mysqli_query ($ Conn, "VYBERTE * zo správ, kde meno = $ meno");

// Iný kód tu

Preto sa najprv snažíte zistiť, či tento používateľ už nemá neprečítanú správu. Dotaz VYBRAŤ * zo správ, kde meno = $ meno sa zdá dosť jednoduché, správne?

ZLE!

V našej nevine sme otvorili dvere okamžitému zničeniu našej databázy. Aby sa tak stalo, musí mať útočník splnené nasledujúce podmienky:

  • Aplikácia beží na databáze SQL (dnes je takmer každá aplikácia)
  • Aktuálne pripojenie k databáze má v databáze oprávnenie na úpravy a mazanie
  • Názvy dôležitých tabuliek je možné uhádnuť

Tretí bod znamená, že teraz, keď útočník vie, že prevádzkujete internetový obchod, s najväčšou pravdepodobnosťou ukladáte údaje o objednávke do tabuľky objednávok. Vyzbrojený tým všetkým, čo musí útočník urobiť, je poskytnúť ho ako svoje meno:

Joe; skrátiť objednávky ;? Áno Pane! Pozrime sa, čo sa stane po spustení skriptu PHP:

VYBRAŤ * ZO KAMOV, KDE meno = Joe; skrátiť objednávky;

Dobre, prvá časť dotazu obsahuje chybu syntaxe (bez úvodzoviek okolo „Joe“), ale dvojbodka núti stroj MySQL začať interpretovať nový: skrátiť objednávky. Rovnako ako to, v jednom jedinom swoop, celá história objednávok je preč!

Teraz, keď viete, ako SQL Injection funguje, je čas sa pozrieť, ako to zastaviť. Na úspešné vstrekovanie SQL je potrebné splniť dve podmienky:

  1. Skript PHP by mal mať v databáze oprávnenia na modifikáciu / vymazanie. Myslím si, že to platí pre všetky aplikácie a nebudete môcť nastaviť svoje aplikácie iba na čítanie. �� A hádajte čo, aj keď odstránime všetky oprávnenia na úpravy, injekcia SQL môže stále umožniť niekomu spustiť SELECT dotazy a zobraziť všetky databázy vrátane citlivých údajov. Inými slovami, zníženie úrovne prístupu k databáze nefunguje a vaša aplikácia to aj tak potrebuje.
  2. Vstup používateľa sa spracováva. Jediným spôsobom, ako môže SQL injekcia fungovať, je, keď prijímate údaje od používateľov. Opäť nie je praktické zastaviť všetky vstupy pre vašu aplikáciu len preto, že máte obavy z SQL injekcie.

Prevencia SQL injekcie v PHP

Vzhľadom na to, že pripojenie k databázam, dotazy a vstupy používateľov sú súčasťou života, ako zabránime vkladaniu SQL? Našťastie je to celkom jednoduché a existujú dva spôsoby, ako to urobiť: 1) dezinfikovať vstup používateľa a 2) použiť pripravené vyhlásenia.

Dezinfikujte vstup používateľa

Ak používate staršiu verziu PHP (5.5 alebo nižšiu, a to sa stáva pri zdieľanom hostení veľa), je rozumné spustiť všetok váš vstup pomocou funkcie s názvom mysql_real_escape_string (). V podstate to, čo robí, odstráni všetky špeciálne znaky v reťazci, aby pri použití v databáze stratili svoj význam.

Napríklad, ak máte reťazec, ako som reťazec, môže útočník použiť znak jednoduchej citácie (‘) na manipuláciu s vytvoreným databázovým dopytom a na vyvolanie injekcie SQL. Jeho spustenie cez mysql_real_escape_string () vytvorí reťazec, ktorý pridá spätné lomítko do jedinej ponuky a vynechá ho. Výsledkom je, že celý reťazec sa teraz odovzdáva ako neškodný reťazec do databázy, namiesto toho, aby sa mohol zúčastňovať manipulácie s dopytmi..

Tento prístup má jednu nevýhodu: je to skutočne stará technológia, ktorá sa spája so staršími formami prístupu k databázam v PHP. Od PHP 7 táto funkcia už neexistuje, čo nás privádza k ďalšiemu riešeniu.

Použite pripravené výkazy

Pripravené výkazy sú spôsobom, ako zvýšiť bezpečnosť a spoľahlivosť databázových dopytov. Ide o to, že namiesto odoslania nespracovaného dotazu do databázy, najprv informujeme databázu o štruktúre dotazu, ktorý pošleme. To je to, čo myslíme „prípravou“ vyhlásenia. Akonáhle je príkaz pripravený, odovzdáme informácie ako parametrizované vstupy, aby databáza mohla „vyplniť medzery“ zapojením vstupov do štruktúry dotazu, ktorú sme predtým poslali. Týmto sa odstráni akákoľvek špeciálna sila, ktorú môžu mať vstupy, čo spôsobí, že sa s nimi bude počas celého procesu zaobchádzať ako s obyčajnými premennými (alebo užitočným zaťažením, ak chcete). Ako vyzerajú pripravené vyhlásenia:

<?php
$ servername = "localhost";
$ username = "užívateľské meno";
$ password = "heslo";
$ dbname = "mydb";

// Vytvorenie spojenia
$ conn = nové mysqli ($ servername, $ username, $ password, $ dbname);

// Skontrolujte pripojenie
ak ($ ​​conn->connect_error) {
die ("Pripojenie zlyhalo: " . $ Conn->connect_error);
}

// pripraviť a zviazať
$ stmt = $ conn->pripraviť ("VLOŽTE DO MyGuests (meno, priezvisko, e-mail) HODNOTY (?,?,?)");
$ stmt->bind_param ("sss", $ krstné meno, $ priezvisko, $ email);

// nastaviť parametre a vykonať
$ firstname = "John";
$ priezvisko = "Laň";
$ email = "[Email protected]";
$ stmt->spustiť ();

$ firstname = "mary";
$ priezvisko = "Moe";
$ email = "[Email protected]";
$ stmt->spustiť ();

$ firstname = "Julie";
$ priezvisko = "Dooley";
$ email = "[Email protected]";
$ stmt->spustiť ();

echo "Nové záznamy boli úspešne vytvorené";

$ stmt->Zavrieť();
$ Conn->Zavrieť();
?>

Viem, že tento proces znie zbytočne zložito, ak ste pripravení na výroky, ale tento koncept stojí za to. tady pekný úvod.

Pre tých, ktorí už sú oboznámení s rozšírením CHOP PHP a používajú ho na vytváranie pripravených vyhlásení, mám malú radu.

Varovanie: Pri nastavovaní CHOP buďte opatrní

Pri používaní CHOP na prístup do databázy sa môžeme dostať do falošného pocitu bezpečia. „Aha, používam CHOP. Teraz už nemusím premýšľať o ničom inom. “- takto sa myslíme všeobecne. Je pravda, že CHOP (alebo príkazy pripravené pomocou MySQLi) sú dostatočné na to, aby zabránili všetkým možným útokom SQL injekcie, ale pri ich nastavovaní musíte byť opatrní. Je bežné len kopírovať a prilepovať kód z výukových programov alebo z predchádzajúcich projektov a pokračovať ďalej, ale toto nastavenie môže vrátiť všetko späť:

$ Prepojenie DB->setAttribute (CHOP :: ATTR_EMULATE_PREPARES, true);

Čo toto nastavenie robí, je povedať CHOP, aby emulovalo pripravené príkazy, skôr ako skutočne použilo funkciu pripravených príkazov v databáze. Preto PHP posiela do databázy jednoduché reťazce dotazov, aj keď váš kód vyzerá, že vytvára pripravené príkazy a nastavovacie parametre a to všetko. Inými slovami, ste rovnako zraniteľní voči SQL injekcii ako predtým. ��

Riešenie je jednoduché: uistite sa, že táto emulácia je nastavená na false.

$ Prepojenie DB->setAttribute (CHOP :: ATTR_EMULATE_PREPARES, false);

Teraz je skript PHP nútený používať pripravené príkazy na úrovni databázy, čím bráni všetkým druhom vstrekovania SQL.

Prevencia používania WAF

Viete, že môžete chrániť webové aplikácie pred SQL injekciou pomocou WAF (firewall webových aplikácií)??

Nuž, nielen vstrekovanie SQL, ale mnoho ďalších zraniteľností vrstvy 7, ako je skriptovanie medzi servermi, nefunkčná autentifikácia, falšovanie medzi servermi, vystavenie údajov atď. Buď môžete použiť hostiteľa, ako je napríklad Mod Security alebo cloud, ako nasledujúce.

SQL injection a moderné PHP rámce

SQL injekcia je taká bežná, tak jednoduchá, tak frustrujúca a tak nebezpečná, že všetky moderné webové webové rámce PHP prichádzajú so zabudovanými protiopatreniami. Napríklad v programe WordPress máme $ wpdb->Funkcia prepar (), zatiaľ čo ak používate rámec MVC, robí všetku špinavú prácu za vás a nemusíte ani premýšľať o tom, ako zabrániť SQL injekcii. Je trochu nepríjemné, že v programe WordPress musíte výslovne pripraviť vyhlásenia, ale hej, hovoríme o ňom WordPress. ��

Myslím si však, že moderné plemeno webových vývojárov nemusí premýšľať o SQL vstrekovaní, a preto si ani neuvedomujú možnosť. Preto, aj keď vo svojej aplikácii nechajú otvorené jedno zadné dvere (možno ide o parameter dopytu $ _GET a staré návyky vypálenia špinavého problému s dopytom), výsledky môžu byť katastrofické. Preto je vždy lepšie si urobiť čas na hlbšie ponorenie sa do základov.

záver

SQL Injection je veľmi nepríjemný útok na webovú aplikáciu, dá sa však ľahko vyhnúť. Ako sme videli v tomto článku, opatrnosť pri spracovávaní vstupu používateľa (mimochodom, SQL Injection nie je jedinou hrozbou, ktorú prináša spracovanie vstupu používateľa) a dotazovanie databázy je všetko, čo je k dispozícii. To znamená, že nie vždy pracujeme na zabezpečení webového rámca, takže je lepšie poznať tento typ útoku a nezaťahovať ho..

Jeffrey Wilson Administrator
Sorry! The Author has not filled his profile.
follow me
    Like this post? Please share to your friends:
    Adblock
    detector
    map