SQL INJECTION ATTACK PREVENTION in PHP | CODE EXAMPLES

több éves penetrációs tesztelés és a fejlesztőcsapatokkal való együttműködés után észrevettem, hogy nincs teljes blogbejegyzés, amely részletes magyarázatot adna arra, hogyan lehet megakadályozni az SQL injection támadásokat a legnépszerűbb webes alkalmazásfejlesztési nyelveken és keretrendszereken. Ezért úgy döntöttem, hogy több bejegyzés sorozatát írom, hogy ez legyen a legteljesebb útmutató az SQL injekció megelőzéséhez.

ez az útmutató egy nyitott bejegyzéssorozat, és ez az első bejegyzés. Ha azt szeretné, hogy adjunk bármilyen technológia, kérjük, csak megjegyzést alább, és én nagyon boldog, hogy ismertesse az SQL injection prevention, hogy a technológia. Ez az útmutató a következő technológiákat elemzi:

  • PHP
    • Laravel
    • Symfony
    • CodeIgniter
    • Cakefp
    • FuelPHP
    • Zend
  • JEE
    • JDBC
    • JPA
  • ASP.NET
    • ADO.NET
    • ADO.Nettó Dopper
    • Nhibernát

ez az első bejegyzés a PHP nyelvre és annak minden keretrendszerére összpontosít. További cikkek következnek a többi felsorolt technológiával kapcsolatban.

azok számára, akik nem tudják, mi az SQL injection attack, hadd tegyek egy kis bevezetést, hogy elmagyarázzam nekik. Az SQL-befecskendezési támadások akkor fordulnak elő, amikor egy rossz felhasználó rosszindulatú SQL-kérést próbál beadni egy jogos kérésbe. Az SQL injekciós támadás hatása helyzetenként különbözik az alkalmazáskörnyezethez kapcsolódó több elemtől függően, és olyan “egyszerű”, mint az információszivárgás, a teljes szervervezérlésig terjedhet. Nem fogok mélyebben belemenni abba, ahogyan a támadó kihasználhatja ezt a sebezhetőséget, vagy hogyan fedezhetjük fel a blackbox tesztekben, mivel ez nem a bejegyzés célja. Látni fogjuk, hogyan lehet felfedezni a forráskódban, és hogyan lehet kijavítani.

hogyan lehet megakadályozni az SQL injekciós támadást egy tiszta PHP forráskódban ?

kezdjük az utunkat az egyik legrégebbi és legnépszerűbb fejlesztési technológiával, a PHP-vel, keretrendszerek nélkül. Most az első dolog az, hogy tudjuk, hogyan néz ki egy sebezhető forráskód sor, hogy képes legyen azonosítani a biztonsági rést.

íme egy példa egy hitelesítési kérelemre:

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

most, ha alaposan megvizsgálja a kérést, észre fogja venni, hogy a $_POST és a $_POST felhasználói paraméterek közvetlenül az SQL kérésbe kerülnek szűrés nélkül. Ezzel ez a kódsor sebezhetővé válik az SQL injekcióval szemben.

a biztonsági rés kijavításához szűrnie kell az adatokat, mielőtt felhasználná őket az sql kérésben. Ehhez a legjobb megoldás az elkészített állítások használata. Íme egy példa arra, hogyan használhatja az elkészített utasításokat a biztonsági rés kijavításához:

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

Helyes Gyakorlat

lehetősége van arra, hogy ne használja a bind_param() függvényt íme egy példa erre :

$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));

a forráskódok évekig tartó elemzése után … felfedeztem egy érdekes hibát, amelyet sok fejlesztő végez a biztonsági rés kijavítása közben. Vessen egy pillantást a következő példára:

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

ha megnézi ezt a példát, látni fogja, hogy az elkészített állításokat használjuk. A paramétereket azonban közvetlenül az SQL kérésbe injektálják. Ez egy nagyon gyakori hiba, amit a fejlesztők csinálnak, és a kódot sebezhetővé teszik az SQL injekcióval szemben, még akkor is, ha az elkészített utasításokat használjuk.

az elkészített utasítások mögött az a gondolat áll, hogy szűrjük a paramétereket, mielőtt befecskendeznénk őket az SQL kérésbe … tartsa ezt szem előtt.

nagyon fontos megjegyzés :

a PHP más funkciókat is kínál az SQL kérések szűrésére és az SQL befecskendezés megakadályozására, de ezek közül néhány nem hatékony. A mysql_real_escape_string () függvény például az egyik legismertebb PHP függvény, amely megakadályozza az SQL injekciót. Sajnos ez a funkció valóban hatékony. Ennek a funkciónak a használatával a MySQL könyvtár fordított perjelet ad a következő karakterekhez: NULL, \ x00, \ n, \ r,\,’, “és \ x1a. azonban egy ilyen helyzetben :

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

a piros szín, amit egy rossz felhasználó küld

a mysql_real_escape_string() nem véd meg az ilyen támadás.

ezért mindig az elkészített utasítások használatát javaslom e funkció helyett.

hogyan lehet megakadályozni az SQL injekciós támadást a Laravel keretben ?

most, hogy láttuk az SQL injekciós támadást egy tiszta PHP kód ellen, most itt az ideje, hogy lássuk, hogyan tudjuk kijavítani a biztonsági rést egy keretrendszer alapú webes alkalmazásban. Mielőtt elkezdenénk beszélni erről, először hadd adjak egy kis leírást a Laravel keretrendszerről.

a Laravel egy nyílt forráskódú webes keretrendszer, amelyet PHP-ben írtak, tiszteletben tartva a modell-nézet-vezérlő elvet, és teljes egészében objektum-orientált programozásban fejlesztették ki.

1. példa

Íme egy példa egy sérülékeny SQL kérésre egy laravelben :

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

a Laravel keretrendszer néhány fantasztikus funkciót kínál, amelyek segítenek a fejlesztőknek az SQL kérés rosszindulatú injekciók elleni biztosításában. Sajnos az ilyen alkalmazásokban felfedezett SQL injection sebezhetőségek többsége a Laravel funkciók visszaélésével kapcsolatos.

elemezzük az előző példát, a Laravel dokumentációja szerint a DB::select függvény két paramétert kaphat. Az első az SQL kérés, a második pedig a paraméterek. Tehát az SQL injekció paramétereinek szűréséhez be kell illesztenie a paramétereket a kérésbe a második paraméter használatával, mint ez a példa :

$user = DB::select(‘select * a felhasználóktól, ahol felhasználónév=? Jelszó=?’, );

2. példa

a Laravel többféle módon kommunikálhat az adatbázissal ebben a példában látni fogja, hogy a laravel arra kényszeríti a fejlesztőt, hogy használjon olyan funkciókat, amelyek automatikusan szűrik a felhasználói adatokat, például a következő példát:

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

ezt a függvényt az SQL injection ellen kell védeni, és az egyetlen probléma az orderBy () függvény szintjén van. A Laravel dokumentációja szerint ez a funkció nem szűri a felhasználói adatokat, így ezen a funkción keresztül továbbra is lehetséges SQL injekciós támadás.

a legjobb dolog, ha nem adjuk meg a Felhasználónak a tábla nevének vezérlésének lehetőségét, de ha ez elkerülhetetlen, akkor fehér listát kell használnia a felhasználói adatok érvényesítéséhez, mielőtt beillesztené azokat a funkcióba.

hogyan lehet megakadályozni az SQL injekciós támadást a Symfony – ban ?

nézzünk meg egy másik jól ismert PHP keretrendszert, amely újrafelhasználható PHP komponenseket kínál a PHP alkalmazások fejlesztésének felgyorsítására. A symfonyt a legismertebb webes CMS-ek is használják, mint például a Drupal és a Magento.

a Symfony az egyik legbiztonságosabb keretrendszer, amellyel együtt dolgozhat, számos funkciót kínál a biztonságos kód írásához. Ha azonban ezeket a funkciókat nem használják jól, akkor sebezhető kódot kap. Tehát itt van egy példa a sebezhető kódra:

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

most elemezzük ezt a sebezhető kódot. A Symfony dokumentációja szerint a createQuery () egy olyan függvény, amely alapértelmezés szerint az elkészített utasításokat használja. Tehát az ilyen függvényből származó objektum hozzáférést biztosít a setParameter() függvényhez. Ez kiszűri az összes felhasználói adatot az SQL injekció elkerülése érdekében. Íme egy példa arra, hogyan kell használni :

$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);

hogyan lehet megakadályozni az SQL injekciós támadást a Codeigniterben ?

CodeIgniter az egyik legerősebb, könnyű és népszerű PHP keretrendszer, nagyon kis helyigénnyel. Olyan fejlesztők számára készült, akiknek egyszerű és elegáns eszköztárra van szükségük a teljes funkcionalitású webes alkalmazások létrehozásához. A Symfonyhoz és a Laravelhez hasonlóan a Codeigniter is tartalmaz néhány biztonsági rendszert, amelyek segítenek a fejlesztőknek biztonságosabb alkalmazások létrehozásában.

azonban a Codeigniterrel is néhány fejlesztő ugyanezt a hibát követi el, és szűrés nélkül adja be a felhasználói adatokat. Íme egy példa az ilyen hibákra, amelyek SQL injekciós támadáshoz vezetnek:

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

most, hogy megoldja ezt a problémát, meg kell néznie a Codeigniter dokumentációját. Eszerint a query () függvény két paramétert vesz fel. Az első az sql lekérdezés, a második pedig a kötni kívánt paraméterek.

1.példa

alapértelmezés szerint ez a függvény szűri az összes kötött paramétert az SQL injekciók megakadályozása érdekében. Íme egy példa a funkció helyes használatára:

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

példa 2:

Codeigniter egy másik módja annak, hogy végre SQL kérés megakadályozza SQL injekciót. Íme egy példa az Active Record osztály használatára az SQL injekciók megelőzésére:

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

a get_where () függvény már nem létezik a CodeIgniter 4-es verziójában.

Megjegyzés 1

Codeigniter hez is egy függvény, aki úgy néz ki, mysql_real_escape_string() nevű függvény escape(). De ahogy először mondtam, a mysql_real_escape_string () bizonyos esetekben megkerülhető, ezért kerülni kell a használatát. Az a tény, hogy az escape() függvény nem pontosan ugyanaz, akkor lehetséges lenne, hogy megkerülje azt is. Ezért nem bátorítom a fejlesztőket az escape() funkció használatára.

Megjegyzés 2

hogyan lehet megakadályozni az SQL injekciós támadást a CakePHP – ben ?

a CakePHP egy gyors fejlesztési keretrendszer a PHP számára, amely olyan közismert tervezési mintákat használ, mint az asszociatív Adattérképezés, a Front Controller és az MVC. A CakePHP egy csomó beépített összetevőt kínál a webes alkalmazások fejlesztésének megkönnyítésére, és biztonságosabbá teszi őket.

azonban a CakePHP alkalmazások is érzékenyek az SQL injekciókra, ha nem használják jól. Íme egy példa az SQL injekciós támadás sebezhető kódjára ebben a keretben:

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

az execute() függvény alapértelmezés szerint az elkészített utasításokat használja. Az előző példa azonban továbbra is sebezhető az SQL injekciós támadással szemben, mivel a felhasználói adatokat közvetlenül egy legitim sql kérésbe illesztik be. Íme egy példa a funkció helyes használatára:

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

a CakePHP keretrendszer egy Query Builder nevű rendszert is kínál, amely arra kényszeríti a felhasználói adatok szűrését, hogy megakadályozza az SQL injekciós támadásokat. A CakePHP dokumentáció szerint a fedelek alatt a Lekérdezéskészítő az elkészített utasításokat használja.

íme egy példa arra, hogyan használhatja az ilyen rendszert a megfelelő módon:

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

hogyan lehet megakadályozni az SQL injekciós támadást a FuelPHP-ben ?

a FuelPHP az egyik legújabb PHP keretrendszer, amely a piac minden keretrendszerének legjobb ötletei alapján született. PHP 5 – tel lett kifejlesztve és teljesen objektum-orientált. A FuelPHP-ben a biztonság volt az aggodalom középpontja, ami arra késztette a közreműködőket, hogy számos biztonsági mechanizmust vezessenek be a felhasználói adatok szűrésére. Az SQL injection megtámadja az ilyen mechanizmusok fuelphp-ben történő megvalósításának egyik okát.

azonban még egy ilyen erős keretrendszer mellett is, ezeknek a mechanizmusoknak az egyszerű visszaélése veszélyezteti az egész kódot egy SQL injekciós támadáshoz. Íme egy példa az ilyen kódhibára:

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

ennek kijavításához két technika is létezik, mint a többi keretrendszer. Az első az, hogy valóban helyesen használja a query () függvényt, a paraméterek kötésével, mint a következő példa :

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

a második megoldás a FuelPHP keretrendszerben megvalósított ORM mechanizmus használata az adatbázissal való kommunikációhoz. Íme egy példa arra, hogyan kell használni:

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

hogyan lehet megakadályozni az SQL injekciós támadást a zend framework – ben ?

Zend framework (változott Laminas Project) Az egyik legismertebb keretrendszer a világon a PHP. A teljesítmény hangolását szem előtt tartva fejlesztették ki, ami megmagyarázza, hogy minden új verzió sokkal gyorsabb, mint a régi. A Zend-et a legjobb biztonsági gyakorlatokkal is fejlesztették, ami arra késztette fejlesztőit, hogy további biztonsági mechanizmusokat hajtsanak végre az ismert számítógépes fenyegetések kezelésére.

ezen mechanizmusok egy részét az SQL injekciós támadások kezelésére hajtották végre. De mint mindig, ezeknek a mechanizmusoknak a visszaélése sebezhető kódhoz vezet. A cikk ezen részében példát mutatok egy ilyen hibára:

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

itt van, hogyan lehet kijavítani ezt a biztonsági rést:

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

Leave a Reply