SQL INJECTION ATTACK PREVENTION i PHP | kodexempel

efter flera års penetrationstestning och arbete med utvecklingsteam för att säkra sina system har jag märkt att det inte fanns något komplett blogginlägg som ger en detaljerad förklaring av hur man förhindrar SQL-injektionsattacker på alla de mest populära webbapplikationsutvecklingsspråken och ramarna. Därför bestämde jag mig för att skriva en serie flera inlägg för att göra den till den mest kompletta guiden för att förhindra SQL-injektion.

den här guiden är en öppen serie inlägg och det här är det första inlägget. Om du vill att jag ska lägga till någon teknik, vänligen bara kommentera nedan och jag kommer att vara mycket glad att förklara SQL injektion förebyggande för denna teknik. Denna guide kommer att analysera följande tekniker:

  • PHP
    • Laravel
    • Symfony
    • CodeIgniter
    • CakePHP
    • FuelPHP
    • Zend
  • JEE
    • JDBC
    • JPA
  • ASP.NET
    • ADO.NET
    • ADO.NET Dopper
    • NHibernate

detta första inlägg kommer att fokusera på PHP-språket och alla dess ramar. Fler artiklar kommer att följa för att hantera de andra listade teknikerna.

för dem som inte vet vad som är SQL injection attack, låt mig göra en liten introduktion för att förklara detta för dem. SQL-injektionsattacker inträffar när en dålig användare försöker injicera en skadlig SQL-begäran i en legitim begäran. Effekten av SQL injection attack skiljer sig från en situation till en annan beroende på flera element relaterade till appmiljön, och det kan gå från så “enkelt” som informationsläckage till en fullständig serverkontroll. Jag kommer inte att gå djupare in i hur en angripare kan utnyttja denna sårbarhet eller hur vi kan upptäcka den i blackbox-tester eftersom detta inte är syftet med detta inlägg. Vad vi kommer att se är hur man upptäcker det i källkoden och hur man fixar det.

hur kan man förhindra SQL-injektion attack i en ren PHP källkod ?

Låt oss börja vår resa med en av de äldsta och populära UTVECKLINGSTEKNOLOGIN PHP utan några ramar. Nu är det första att göra att veta hur en sårbar källkodslinje ser ut för att kunna identifiera sårbarheten.

här är ett exempel på en autentiseringsbegäran:

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

nu om du tittar närmare på begäran kommer du att märka att användarparametrarna $_POST och $_POST injiceras direkt i SQL-begäran utan filtrering. Om du gör det gör den här kodraden sårbar för SQL-injektion.

för att åtgärda denna sårbarhet måste du filtrera data innan du använder dem i sql-begäran. För att göra detta är den bästa lösningen att använda de förberedda uttalandena. Här är ett exempel på hur du kan använda de förberedda uttalandena för att åtgärda denna sårbarhet:

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

god praxis

du har möjlighet att inte använda funktionen bind_param () här är ett exempel på hur du gör detta :

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

efter år av analys av källkoder … har jag upptäckt ett intressant fel som många utvecklare gör när de fixar denna sårbarhet. Ta en titt på följande exempel:

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

om du tittar på det här exemplet ser du att vi använder de förberedda uttalandena. Parametrarna injiceras dock direkt i SQL-begäran. Detta är ett mycket vanligt misstag som utvecklare gör och gör koden sårbar för SQL-injektion även om vi använder de förberedda uttalandena.

tanken bakom de förberedda uttalandena är att filtrera parametrarna innan du injicerar dem i SQL-begäran … håll detta i ditt sinne.

mycket viktigt:

PHP erbjuder några andra funktioner för att filtrera SQL-förfrågningar och förhindra SQL-injektion, men vissa av dem är inte effektiva. Funktionen mysql_real_escape_string () är till exempel en av de mest kända PHP-funktionerna för att förhindra SQL-injektion. Tyvärr är denna funktion verkligen effektiv. Genom att använda den här funktionen lägger MySQL-biblioteket till ett backslash till följande tecken: NULL, \ x00, \ n, \ r,\,’, ” och \ x1a. men för en situation som den här :

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

i röd färg är vad en dålig användare skickar dig

mysql_real_escape_string() skyddar dig inte mot sådan attack.

det är därför jag alltid rekommenderar att du använder de förberedda uttalandena istället för den här funktionen.

hur kan man förhindra SQL-injektion attack i Laravel framework ?

nu när vi har sett SQL-injektionsattacken mot en ren PHP-kod är det dags att se hur vi kan fixa sårbarheten i en rambaserad webbapplikation. Innan vi börjar prata om detta, låt mig först ge dig en liten beskrivning av Laravel-ramverket.

Laravel är ett webbramverk med öppen källkod skriven i PHP med respekt för principen model-view-controller och helt utvecklad i objektorienterad programmering.

exempel 1

här är ett exempel på en sårbar SQL-begäran i en laravel :

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

Laravel framework erbjuder några fantastiska funktioner för att hjälpa utvecklare att säkra SQL-begäran mot skadliga injektioner. Tyvärr är de flesta SQL-injektionssårbarheter som jag upptäcker i sådana appar relaterade till missbruk av Laravel-funktioner.

låt oss analysera föregående exempel, enligt Laravel-dokumentationen kan DB::select-funktionen få två parametrar. Den första är SQL-förfrågan och den andra är parametrarna. Så för att filtrera parametrarna för SQL-injektion måste du infoga parametrarna i begäran med den andra parametern precis som det här exemplet:

$user = DB:: select (‘Välj * från användare där användarnamn=? Och lösenord=?’, );

exempel 2

Laravel har flera sätt att kommunicera med databasen i det här exemplet ser du att laravel tvingar utvecklaren att använda vissa funktioner som automatiskt filtrerar användardata, som följande exempel:

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

denna funktion är tänkt att säkras mot SQL-injektion och de är, det enda problemet är på orderBy() funktionsnivå. Enligt Laravel-dokumentationen filtrerar inte denna funktion användardata så en SQL-injektionsattack är fortfarande möjlig genom denna funktion.

det bästa du kan göra är att inte ge användaren möjlighet att kontrollera tabellnamnet, men om det här är något oundvikligt måste du använda en vit lista för att validera användardata innan du sätter in den i den funktionen.

hur kan man förhindra SQL-injektion attack i Symfony ?

Låt oss se ett annat välkänt PHP-ramverk som erbjuder en uppsättning återanvändbara PHP-komponenter för att påskynda utvecklingen av PHP-appar. Symfony används också av några av de mest kända webb-CMS som Drupal och Magento.

Symfony är en av de säkraste ramarna som du kan arbeta med, det erbjuder ett brett antal funktioner för att skriva en säker kod. Men om dessa funktioner inte används väl får du en sårbar kod. Så här är ett exempel på en sårbar kod:

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

låt oss nu analysera denna sårbara kod. Enligt Symfony-dokumentationen är createQuery () en funktion som som standard använder de förberedda uttalandena. Så, objektet som härrör från en sådan funktion ger dig tillgång till setParameter () – funktionen. Den här filtrerar alla användardata för att undvika en SQL-injektion. Här är ett exempel på hur man använder det :

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

hur kan man förhindra SQL-injektion attack i Codeigniter ?

CodeIgniter en av de mest kraftfulla, lätta och populära PHP-ramarna med ett mycket litet fotavtryck. Den byggdes för utvecklare som behöver en enkel och elegant verktygslåda för att skapa fullfjädrad webbapplikationer. Liksom Symfony och Laravel kommer Codeigniter också med vissa säkerhetssystem för att hjälpa utvecklare att skapa säkrare appar.

men även med Codeigniter gör vissa utvecklare samma misstag och injicerar användardata utan filtrering. Här är ett exempel på sådana fel som leder till en SQL-injektionsattack:

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

nu för att åtgärda problemet måste du ta en titt på Codeigniter-dokumentationen. Enligt det tar funktionen query () två parametrar. Den första är sql-frågan, och den andra är parametrarna som du vill binda.

exempel 1

som standard filtrerar denna funktion alla bindade parametrar för att förhindra SQL-injektioner. Här är ett exempel på rätt sätt att använda den här funktionen:

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

exempel 2:

Codeigniter ger ett annat sätt att utföra SQL-begäran kommer att förhindra SQL-injektioner. Här är ett exempel på att använda Active Record-klassen för att förhindra SQL-injektioner:

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

funktionen get_where () finns inte längre i version 4 av Codeigniter.

Notera 1

Codeigniter erbjuder också en funktion som ser ut, mysql_real_escape_string() funktion som kallas escape(). Men som jag först sa mysql_real_escape_string () kan kringgås i vissa fall och du måste undvika att använda den. Det faktum att escape () – funktionen gör exakt samma, då skulle det vara möjligt att kringgå det också. Det är därför jag inte uppmuntrar utvecklare att använda escape () – funktionen.

Notera 2

Hur förhindrar SQL-injektionsattack i CakePHP ?

CakePHP är ett ramverk för snabb utveckling för PHP som använder allmänt kända designmönster som associativ data Mapping, Front Controller och MVC. CakePHP erbjuder ett gäng inbyggd komponent för att underlätta utvecklingen av webbapplikationer och kommer att göra dem säkrare.

CakePHP-appar är dock också sårbara för SQL-injektioner om de inte används väl. Här är ett exempel på en sårbar kod för SQL-injektionsattack i detta ramverk:

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

funktionen execute () använder som standard de förberedda uttalandena. Det föregående exemplet är dock fortfarande sårbart för SQL-injektionsattack, eftersom användardata infogas direkt i en legitim sql-begäran. Här är ett exempel på rätt sätt att använda den här funktionen:

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

CakePHP framework erbjuder också ett system som heter Query Builder, vilket tvingar användardata filtrering för att förhindra SQL-injektionsattacker. Enligt CakePHP-dokumentationen använder Frågebyggaren de förberedda uttalandena under omslagen.

här är ett exempel på hur du kan använda ett sådant system på rätt sätt:

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

hur kan man förhindra SQL-injektion attack i FuelPHP ?

FuelPHP är ett av de senaste PHP-ramarna som föddes baserat på de bästa ideerna för varje ram på marknaden. Den utvecklades med PHP 5 och är helt objektorienterad. I FuelPHP var säkerhet det främsta och centrala problemet, vilket drev sina bidragsgivare att implementera många säkerhetsmekanismer för att filtrera användardata. SQL-injektion attackerar en av anledningarna till att implementera sådana mekanismer i FuelPHP.

men även med ett så kraftfullt ramverk sätter en enkel missbruk av dessa mekanismer hela koden i fara för en SQL-injektionsattack. Här är ett exempel på ett sådant kodfel:

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

för att åtgärda detta finns det också två tekniker som de andra ramarna. Den första är att faktiskt korrekt använda funktionen query () genom att binda parametrarna som följande exempel :

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

den andra lösningen är att använda ORM-mekanismen implementerad i FuelPHP-ramverket för att kommunicera med databasen. Här är ett exempel på hur man använder det:

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

hur kan man förhindra SQL-injektion attack i Zend framework ?

Zend framework (ändrad till Laminas Project) är en av de mest kända ramarna i PHP-världen. Den utvecklades med tanke på prestandajustering, vilket förklarar varför varje ny version är mycket snabbare än den gamla. Zend utvecklades också med de bästa säkerhetspraxis, som drev sina utvecklare att genomföra ytterligare säkerhetsmekanismer för att hantera kända cyberhot.

några av dessa mekanismer implementerades för att hantera SQL-injektionsattackerna. Men som alltid leder missbruk av dessa mekanismer till en sårbar kod. I den här delen av artikeln kommer jag att visa ett exempel på ett sådant fel:

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

så här åtgärdar du denna sårbarhet:

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

Leave a Reply