SQL INJECTION ATTACK PREVENTION in PHP / CODE EXAMPLES

useiden vuosien penetration testauksen ja kehitystiimien kanssa järjestelmien turvaamiseksi työskenneltyäni olen huomannut, että ei ollut täydellistä blogikirjoitusta, joka antaa yksityiskohtaisen selvityksen siitä, miten estää SQL injection attacks kaikissa suosituimmissa web-sovelluskehityksen kielissä ja kehyksissä. Siksi, päätin kirjoittaa useita virkoja, jotta se täydellisin opas estää SQL injektio.

tämä opas on avoin sarja virkoja ja tämä on ensimmäinen virka. Jos haluat minun lisätä mitään tekniikkaa, vain kommentoida alla ja olen erittäin iloinen selittää SQL injektio ehkäisy että tekniikka. Tässä oppaassa analysoidaan seuraavia tekniikoita:

  • PHP
    • Laravel
    • Symfony
    • CodeIgniter
    • CakePHP
    • FuelPHP
    • Zend
  • JEE
    • JDBC
    • JPA
  • ASP.NET
    • ADO.NET
    • ADO.Nettodopperi
    • Nhibernaatti

tämä ensimmäinen viesti keskittyy PHP-kieleen ja sen kaikkiin kehyksiin. Lisää artikkeleita seuraa käsitellä muita lueteltuja teknologioita.

niille, jotka eivät tiedä, mikä on SQL-pistoshyökkäys, teen pienen johdannon selittääkseni tämän heille. SQL-injektiohyökkäykset tapahtuvat, kun huono käyttäjä yrittää pistää haitallisen SQL-pyynnön lailliseen pyyntöön. SQL-injektiohyökkäyksen vaikutus vaihtelee tilanteesta toiseen riippuen useista sovellusympäristöön liittyvistä elementeistä, ja se voi siirtyä niinkin “yksinkertaisesta” kuin tietovuoto täydelliseen palvelinohjaukseen. En mene syvemmälle tapaan hyökkääjä voisi hyödyntää tätä haavoittuvuutta tai miten voimme löytää sen blackbox testejä, koska tämä ei ole tavoite tämän viestin. Mitä näemme on, miten löytää se lähdekoodi ja miten korjata se.

Miten estää SQL-pistoshyökkäys puhtaassa PHP-lähdekoodissa ?

aloittakaamme matkamme yhdellä vanhimmista ja suosituista kehitysteknologioista PHP: llä ilman kehyksiä. Nyt ensimmäiseksi pitää tietää, miltä haavoittuva lähdekoodirivi näyttää, jotta haavoittuvuus voidaan tunnistaa.

tässä on esimerkki todennuspyynnöstä:

$request = "SELECT * FROM users WHERE username=". $_POST ." AND password = ". $_POST;
$result = $mysqli->query($request);

jos tarkastelet pyyntöä tarkemmin, huomaat, että käyttäjän parametrit $_post ja $_POST pistetään suoraan SQL-pyyntöön ilman suodatusta. Näin tehdä tämä koodirivi altis SQL injektio.

korjataksesi tämän haavoittuvuuden sinun täytyy suodattaa tiedot ennen kuin käytät niitä sql-pyynnössä. Voit tehdä tämän paras ratkaisu on käyttää valmiita lausuntoja. Tässä on esimerkki siitä, miten voit käyttää valmiita lausuntoja korjata tämän haavoittuvuuden:

$conn = new mysqli($servername, $username, $password, $dbname);
$stmt = $conn->prepare("SELECT * FROM users WHERE username=? AND password=?");
$stmt->bind_param($username, $password);
$stmt->execute();

hyvä käytäntö

sinulla on mahdollisuus olla käyttämättä funktiota bind_param() tässä on esimerkki siitä, miten tämä tehdään :

$conn = new mysqli($servername, $username, $password, $dbname);
$stmt = $conn->prepare("SELECT * FROM users WHERE username=:username AND password=:password");
$stmt-> execute(array('username'=>$_POST,'password'=>$_POST));

vuosien jälkeen analysoimalla lähdekoodeja … olen löytänyt mielenkiintoisen virheen, että monet kehittäjät tekevät korjatessaan tätä haavoittuvuutta. Katso seuraavaa esimerkkiä:

$stmt = $conn->prepare("SELECT * FROM users WHERE username=".$_POST." AND password=".$_POST);

jos tarkastelette tätä esimerkkiä, huomaatte, että käytämme laadittuja lausuntoja. Parametrit pistetään kuitenkin suoraan SQL-pyyntöön. Tämä on hyvin yleinen virhe, että kehittäjät tekevät, ja tehdä koodin altis SQL injektio vaikka käytämme valmiita lausuntoja.

laadittujen lausekkeiden ideana on suodattaa parametrit ennen niiden pistämistä SQL-pyyntöön … pidä tämä mielessäsi.

erittäin tärkeä huomautus:

PHP tarjoaa joitakin muita toimintoja SQL-pyyntöjen suodattamiseen ja SQL-ruiskutuksen estämiseen, mutta osa niistä ei ole tehokkaita. Esimerkiksi mysql_real_escape_string () – funktio on yksi tunnetuimmista SQL-injektion estävistä PHP-funktioista. Valitettavasti tämä toiminto on todella tehokas. Tätä toimintoa käyttämällä MySQL-kirjasto lisää backslashin seuraaviin merkkeihin: NULL, \ x00, \ n, \ r,\,’, “ja \ x1a.:

$id = mysql_real_escape_string("1 OR 1=1");
$request = "SELECT * FROM users WHERE id = $id";

punainen väri on mitä huono käyttäjä lähettää

Mysql_real_escape_string () ei suojaa sinua tällaiselta hyökkäykseltä.

tästä syystä suosittelen aina käyttämään valmiita lausekkeita tämän funktion sijaan.

Miten estää SQL injection attack Laravel frameworkissa ?

nyt kun olemme nähneet SQL-injektiohyökkäyksen puhdasta PHP-koodia vastaan, nyt on aika katsoa, miten voimme korjata haavoittuvuuden kehyspohjaisessa verkkosovelluksessa. Ennen kuin alamme puhua tästä, haluan ensin antaa teille pienen kuvauksen Laravelin puitteista.

Laravel on avoimen lähdekoodin verkkokehys, joka on kirjoitettu PHP: llä noudattaen malli-näkymä-ohjain-periaatetta ja joka on kehitetty kokonaan olio-ohjelmoinnissa.

Esimerkki 1

tässä on esimerkki haavoittuvasta SQL-pyynnöstä laravelissa :

$user = DB::select('select * from users where username='. $request->post('username').' AND password='. $request->post('password'));

Laravel framework tarjoaa joitakin mahtavia toimintoja, joiden avulla kehittäjät voivat suojata SQL-pyynnön haitallisia injektioita vastaan. Valitettavasti, useimmat SQL injektio haavoittuvuuksia, että löydän tällaisia sovelluksia liittyvät väärinkäyttöön Laravel toimintoja.

analysoidaan edellistä esimerkkiä, Laravelin dokumentaation mukaan dB:: select-funktio voi vastaanottaa kaksi parametria. Ensimmäinen on SQL-pyyntö ja toinen on parametrit. Joten suodattaa parametrit SQL injektio sinun täytyy lisätä parametrit pyynnön käyttäen toista parametria kuten tässä esimerkissä:

$user = DB:: valitse (‘Valitse * käyttäjiltä missä käyttäjätunnus=? Ja salasana=?’, );

Esimerkki 2

Laravelilla on useita tapoja kommunikoida tietokannan kanssa tässä esimerkissä näet, että laravel pakottaa kehittäjän käyttämään joitakin toimintoja, jotka suodattavat käyttäjätiedot automaattisesti, kuten seuraavassa esimerkissä:

Users::where('username', $request->get('username'))->orderBy($request->get('orderby'))->get();

tämä funktio on tarkoitus suojata SQL-injektio ja ne ovat, ainoa ongelma on orderBy () funktion tasolla. Laravelin dokumentaation mukaan Tämä toiminto ei suodata käyttäjätietoja, joten SQL-pistoshyökkäys on edelleen mahdollista tämän toiminnon kautta.

parasta on olla antamatta käyttäjälle mahdollisuutta hallita taulukon nimeä, mutta jos tämä on jotain väistämätöntä, sinun on käytettävä valkoista listaa vahvistaaksesi käyttäjätiedot ennen kuin asetat ne kyseiseen funktioon.

Miten estää SQL-pistoshyökkäys Symfonyssa ?

Katsotaanpa toista tunnettua PHP-kehystä, joka tarjoaa joukon uudelleenkäytettäviä PHP-komponentteja nopeuttamaan PHP-sovellusten kehitystä. Symfony käytetään myös joitakin tunnetuimpia web CMS kuten Drupal ja Magento.

Symfony on yksi turvallisimmista kehyksistä, joiden kanssa voi työskennellä, se tarjoaa laajan määrän toimintoja turvallisen koodin kirjoittamiseen. Kuitenkin, jos näitä toimintoja ei käytetä hyvin, saat haavoittuva koodi. Joten tässä on esimerkki haavoittuva koodi:

$entityManager = $this->getEntityManager();
$query = $entityManager->createQuery('SELECT p
FROM App\Entity\Product p
WHERE p.price > '. $request->query->get('price')
);

analysoidaan tämä haavoittuva koodi. Symfonyn dokumentaation mukaan createQuery() on funktio, joka käyttää oletusarvoisesti laadittuja lausekkeita. Niin, objekti tuloksena tällainen funktio antaa sinulle pääsyn setparametri () funktio. Tämä suodattaa kaikki käyttäjätiedot välttääkseen SQL-injektion. Tässä on esimerkki siitä, miten sitä käytetään :

$entityManager = $this->getEntityManager();
$query = $entityManager->createQuery('SELECT p
FROM App\Entity\Product p
WHERE p.price > :price
ORDER BY p.price ASC'
)->setParameter('price', $price);

Miten estää SQL injektio hyökkäys Codeigniter ?

CodeIgniter yksi tehokkaimmista, kevyimmistä ja suosituimmista PHP-kehyksistä, jolla on hyvin pieni jalanjälki. Se on rakennettu kehittäjille, jotka tarvitsevat yksinkertainen ja tyylikäs työkalupakki luoda monipuolinen web-sovelluksia. Kuten Symfony ja Laravel, Codeigniterin mukana tulee myös joitakin tietoturvajärjestelmiä, jotka auttavat kehittäjiä luomaan turvallisempia sovelluksia.

kuitenkin myös Codeigniterin kanssa jotkut kehittäjät tekevät saman virheen ja pistävät käyttäjän tiedot ilman suodatusta. Tässä on esimerkki tällaisista virheistä, jotka johtavat SQL-injektiohyökkäykseen:

$query = 'SELECT * FROM users WHERE username = '. $this-> input->post('username'). ' AND password= '. $this-> input->post('password');
$this->db->query($query);

nyt korjata tämän ongelman, sinun täytyy vilkaista Codeigniter dokumentaatio. Sen mukaan kysely () – funktio ottaa kaksi parametria. Ensimmäinen on SQL-kysely, ja toinen on parametrit, jotka haluat sitoa.

Esimerkki 1

oletuksena tämä funktio suodattaa kaikki sidotut parametrit SQL-injektioiden estämiseksi. Tässä on esimerkki oikea tapa käyttää tätä toimintoa:

$query = 'SELECT * FROM users WHERE username = ? AND password = ? ';
$this->db->query($query, array($this->input->post('username'), $this-> input-> post('password')));

Esimerkki 2:

Codeigniter antaa toisen tavan suorittaa SQL-pyyntö estää SQL-injektiot. Tässä on esimerkki aktiivisen Tietueluokan käyttämisestä SQL-injektioiden estämiseen:

$this->db->get_where('users',array('username'=>$this->input->post('username') ,'password' => $this->input->post('password')));

funktiota Get_where () ei enää ole Codeigniterin versiossa 4.

huom. 1

Codeigniter tarjoavat myös funktion, joka näyttää, mysql_real_escape_string () funktio nimeltään escape (). Mutta, kuten sanoin ensin mysql_real_escape_string () voidaan ohittaa joissakin tapauksissa ja sinun täytyy välttää sitä. Se, että escape () – funktio tekee täsmälleen saman, niin se olisi mahdollista ohittaa myös. Tämän vuoksi en kannusta kehittäjiä käyttämään escape () – toimintoa.

Huom. 2

Miten estää SQL injection attack CakePHP ?

CakePHP on PHP: n nopea kehityskehys, jossa käytetään yleisesti tunnettuja suunnittelumalleja, kuten assosiatiivinen Data Mapping, Front Controller ja MVC. CakePHP tarjoavat joukko sisäänrakennettu komponentti helpottaa web-sovellusten kehittämistä ja tekee niistä turvallisempia.

CakePHP-sovellukset ovat kuitenkin alttiita myös SQL-pistoksille, jos sitä ei käytetä hyvin. Tässä on esimerkki haavoittuva koodi SQL injektio hyökkäys tässä yhteydessä:

$results = $connection-> execute('SELECT * FROM users WHERE username = '. $this->request->getParam('username').' AND password='. $this->request->getParam('password'))->fetchAll('assoc');

suorita () – funktio oletusarvoisesti käyttää valmiita lausekkeita. Edellinen esimerkki on kuitenkin edelleen altis SQL-injektiohyökkäykselle, sillä käyttäjätiedot syötetään suoraan lailliseen sql-pyyntöön. Tässä on esimerkki oikea tapa käyttää tätä toimintoa:

$results = $connection->execute('SELECT * FROM users WHERE username = :username AND password=:password', )->fetchAll('assoc');

CakePHP framework tarjoaa myös järjestelmän nimeltä Query Builder, joka pakottaa käyttäjän tietojen suodatuksen estämään SQL-injektiohyökkäykset. CakePHP: n dokumentaation mukaan kansien alla kyselyn rakentaja käyttää valmiita lausuntoja.

tässä on esimerkki siitä, miten voit käyttää tällaista järjestelmää oikealla tavalla:

use Cake\ORM\Locator\LocatorAwareTrait;
$users = $this->getTableLocator()->get('users');
// Start a new query.
$query = $users->find();
$query->where();

Miten estää SQL injektio hyökkäys FuelPHP ?

FuelPHP on yksi viimeisimmistä PHP-puitteista, joka on syntynyt markkinoiden kunkin kehyksen parhaiden ideoiden pohjalta. Se on kehitetty PHP 5: llä ja on täysin oliopainotteinen. FuelPHP: ssä turvallisuus oli päällimmäisenä ja keskipisteenä, mikä sai sen avustajat toteuttamaan monia tietoturvamekanismeja käyttäjän tietojen suodattamiseksi. SQL injection hyökkää yksi syy toteuttaa tällaisia mekanismeja FuelPHP.

kuitenkin, jopa näin voimakkaissa puitteissa, näiden mekanismien yksinkertainen väärinkäyttö vaaransi koko koodin SQL-injektiohyökkäyksen vuoksi. Tässä on esimerkki tällaisesta koodivirheestä:

$query = "SELECT * FROM article WHERE id = ". Input::get('id');
$result = DB::query($query)->execute();

korjata tämä, on myös kaksi tekniikkaa kuin muut puitteet. Ensimmäinen on todella oikein käyttäen kyselyn () funktio, sitomalla parametrit, kuten seuraava esimerkki :

$query = "SELECT * FROM article WHERE id = :id"; // our query
$result = DB::query($query)->bind('id', Input::get('id'))->execute();

toinen ratkaisu on käyttää FuelPHP-puitteissa toteutettua ORM-mekanismia yhteydenpitoon tietokannan kanssa. Tässä on esimerkki siitä, miten sitä käytetään:

$user = DB::select()->from('article')->where('id', Input::get('id'))->execute();

Miten estää SQL injection attack Zend framework ?

Zend framework (muutettu nimellä Laminas Project) on yksi tunnetuimmista PHP: n kehyksistä maailmassa. Se kehitettiin suorituskyvyn viritys mielessä, mikä selittää, miksi jokainen uusi versio on paljon nopeampi kuin vanha. Zendille kehitettiin myös parhaat tietoturvakäytännöt, jotka patistivat hänen kehittäjiään ottamaan käyttöön lisää tietoturvamekanismeja tunnettujen kyberuhkien varalta.

osa näistä mekanismeista toteutettiin SQL-injektiohyökkäysten torjumiseksi. Mutta kuten aina, näiden mekanismien väärinkäyttö johtaa haavoittuvaan säännöstöön. Tässä osassa artikkelin aion näyttää esimerkin tällaisesta virheestä:

$adapter->query('SELECT * FROM `article` WHERE `id` = '. $this->getRequest()->getPost('id'));

näin korjaat tämän haavoittuvuuden:

$adapter->query('SELECT * FROM `article` WHERE `id` = ?', );

Leave a Reply