SQL INJECTION ATTACK PREVENTION in PHP | CODE EXAMPLES
na een aantal jaren van penetratie testen en werken met ontwikkelteams om hun systemen te beveiligen, heb ik gemerkt dat er geen complete blog post die een gedetailleerde uitleg geeft over hoe SQL injection aanvallen te voorkomen in de meest populaire web applicatie ontwikkeling talen en frameworks. Daarom heb ik besloten om een reeks van meerdere berichten te schrijven om het de meest complete gids te maken om SQL-injectie te voorkomen.
deze gids is een open reeks posten en dit is de eerste post. Als u wilt dat ik een technologie toe te voegen, gelieve gewoon commentaar hieronder en Ik zal erg blij zijn om uit te leggen SQL injectie preventie voor die technologie. Deze gids zal het analyseren van de volgende technologieën:
- PHP
- Laravel
- Symfony
- CodeIgniter
- CakePHP
- FuelPHP
- Zend
- JEE
- JDBC
- JPA
- ASP.NET
- ADO.NET
- ADO.NETDOPPER
- Imbernate
deze eerste post zal zich richten op de PHP taal en al zijn frameworks. Meer artikelen zullen volgen om te gaan met de andere genoemde technologieën.
voor degenen die niet weten wat SQL injection attack is, laat me een kleine introductie doen om dit aan hen uit te leggen. SQL injectie aanvallen gebeuren wanneer een slechte gebruiker probeert om een kwaadaardig SQL verzoek te injecteren in een legitiem verzoek. De impact van SQL injection attack verschilt van een situatie naar een andere afhankelijk van meerdere elementen met betrekking tot de app-omgeving, en het kan gaan van zo “eenvoudig” als informatielek naar een volledige server controle. Ik zal niet dieper ingaan op de manier waarop een aanvaller zou kunnen profiteren van deze kwetsbaarheid of hoe we het kunnen ontdekken in blackbox tests als dit is niet het doel van deze post. Wat we zullen zien is hoe het te ontdekken in de broncode en hoe het te repareren.
hoe SQL injectie aanval te voorkomen in een pure PHP broncode ?
laten we onze reis beginnen met een van de oudste en populaire ontwikkelingstechnologie PHP ZONDER frameworks. Nu is het eerste wat je moet doen om te weten hoe een kwetsbare broncodelijn eruit ziet om de kwetsbaarheid te kunnen identificeren.
hier is een voorbeeld van een authenticatieverzoek:
$request = "SELECT * FROM users WHERE username=". $_POST ." AND password = ". $_POST;
$result = $mysqli->query($request);
als je nu goed naar het verzoek kijkt zul je merken dat de gebruikersparameters $_POST en $_POST direct in het sql-verzoek worden geïnjecteerd zonder enige filtering. Door dit te doen maken deze codelijn kwetsbaar voor SQL injectie.
om deze kwetsbaarheid op te lossen moet u de gegevens filteren voordat u ze gebruikt in de SQL-aanvraag. Om dit te doen is de beste oplossing om de voorbereide verklaringen te gebruiken. Hier is een voorbeeld van hoe u de voorbereide verklaringen kunt gebruiken om deze kwetsbaarheid op te lossen:
$conn = new mysqli($servername, $username, $password, $dbname);
$stmt = $conn->prepare("SELECT * FROM users WHERE username=? AND password=?");
$stmt->bind_param($username, $password);
$stmt->execute();
goede praktijk
u heeft de mogelijkheid om de functie bind_param() niet te gebruiken hier is een voorbeeld van hoe u dit kunt doen :
$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));
na jaren van het analyseren van broncodes … ik heb een interessante fout ontdekt die veel ontwikkelaars doen, terwijl de vaststelling van deze kwetsbaarheid. Bekijk het volgende voorbeeld:
$stmt = $conn->prepare("SELECT * FROM users WHERE username=".$_POST." AND password=".$_POST);
als u naar dit voorbeeld kijkt, zult u zien dat we gebruik maken van de voorbereide verklaringen. De parameters worden echter direct geïnjecteerd in het sql-verzoek. Dit is een veel voorkomende fout die ontwikkelaars doen, en maken de code kwetsbaar voor SQL injectie, zelfs als we gebruik maken van de voorbereide verklaringen.
het idee achter de voorbereide statements is om de parameters te filteren voordat je ze injecteert in het sql-verzoek … houd dit in je gedachten.
Zeer Belangrijke opmerking:
PHP biedt enkele andere functies om SQL-verzoeken te filteren en SQL-injectie te voorkomen, maar sommige zijn niet efficiënt. De mysql_real_escape_string () functie, bijvoorbeeld, is een van de meest bekende PHP functies om SQL injectie te voorkomen. Helaas, deze functie is echt efficiënt. Door deze functie te gebruiken, zal de MySQL bibliotheek een backslash toevoegen aan de volgende karakters: NULL, \ x00, \ n, \ r,\,’, “en \ x1a. echter, voor een situatie als deze:
$id = mysql_real_escape_string("1 OR 1=1");
$request = "SELECT * FROM users WHERE id = $id";
in rood is wat een slechte gebruiker je zal sturen
de mysql_real_escape_string () zal je niet beschermen tegen een dergelijke aanval.
daarom adviseer ik altijd om de voorbereide statements te gebruiken in plaats van deze functie.
hoe SQL-injectieaanval voorkomen in Laravel framework ?
nu we de SQL injectie aanval tegen een pure PHP-code hebben gezien, is het nu tijd om te zien hoe we de kwetsbaarheid in een framework gebaseerde webapplicatie kunnen repareren. Voordat we hier over beginnen te praten, Laat me je eerst een kleine beschrijving geven van het Laravel framework.
Laravel is een open-source web framework geschreven in PHP met respect voor het model-view-controller principe en volledig ontwikkeld in object-georiënteerd programmeren.
Voorbeeld 1
hier is een voorbeeld van een kwetsbare SQL-aanvraag in een laravel :
$user = DB::select('select * from users where username='. $request->post('username').' AND password='. $request->post('password'));
de Laravel framework biedt een aantal geweldige functies om ontwikkelaars te helpen om de SQL-aanvraag te beveiligen tegen kwaadaardige injecties. Helaas, de meeste van de SQL injectie kwetsbaarheden die ik Ontdek in dergelijke apps zijn gerelateerd aan misbruik van Laravel functies.
laten we het vorige voorbeeld analyseren, volgens Laravel documentatie kan de DB::select functie twee parameters ontvangen. De eerste is het sql-verzoek en de tweede zijn de parameters. Dus om de parameters voor SQL injectie te filteren moet je de parameters in het verzoek invoegen met behulp van de tweede parameter, net als dit voorbeeld:
$user = DB:: select (‘select * from users where username=? En password=?’, );
Voorbeeld 2
Laravel heeft meerdere manieren om met de database te communiceren in dit voorbeeld zul je zien dat laravel de ontwikkelaar dwingt om enkele functies te gebruiken die automatisch de gebruikersgegevens filteren, zoals het volgende voorbeeld:
Users::where('username', $request->get('username'))->orderBy($request->get('orderby'))->get();
deze functie wordt verondersteld te worden beveiligd tegen SQL injectie en ze zijn, het enige probleem is op de orderBy() functie niveau. Volgens Laravel documentatie filtert deze functie de gebruikersgegevens niet, zodat een SQL injectie aanval nog steeds mogelijk is via deze functie.
het beste is om de gebruiker niet de mogelijkheid te geven om de tabelnaam te beheren, maar als dit onvermijdelijk is, dan moet u een witte lijst gebruiken om de gebruikersgegevens te valideren voordat u deze in die functie plaatst.
hoe SQL injectie aanval te voorkomen in Symfony ?
laten we een ander bekend PHP framework bekijken dat een set van herbruikbare PHP componenten biedt om de ontwikkeling van PHP apps te versnellen. Symfony wordt ook gebruikt door enkele van de meest bekende web CMS zoals Drupal en Magento.
Symfony is een van de meest veilige frameworks waarmee u kunt werken, het biedt een groot aantal functies om een veilige code te schrijven. Echter, als deze functies niet goed worden gebruikt dan krijg je een kwetsbare code. Hier is een voorbeeld van een kwetsbare code:
$entityManager = $this->getEntityManager();
$query = $entityManager->createQuery('SELECT p
FROM App\Entity\Product p
WHERE p.price > '. $request->query->get('price')
);
laten we nu deze kwetsbare code analyseren. Volgens de documentatie van Symfony is createQuery() een functie die standaard de voorbereide statements gebruikt. Het object dat uit zo ‘ n functie voortvloeit, geeft je dus toegang tot de functie setParameter (). Deze filtert alle gebruikersgegevens om een SQL-injectie te voorkomen. Hier is een voorbeeld van hoe het te gebruiken :
$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);
hoe te voorkomen dat SQL injectie aanval in Codeigniter ?
CodeIgniter een van de meest krachtige, lichtgewicht en populaire PHP frameworks met een zeer kleine footprint. Het is gebouwd voor ontwikkelaars die behoefte hebben aan een eenvoudige en elegante toolkit om full-featured webapplicaties te creëren. Net als Symfony en Laravel, Codeigniter komt ook met een aantal beveiligingssystemen om ontwikkelaars te helpen om veiliger apps te maken.
echter, ook met Codeigniter maken sommige ontwikkelaars dezelfde fout en injecteren de gebruikersgegevens zonder enige filtering. Hier is een voorbeeld van dergelijke fouten die leiden tot een SQL injectie aanval:
$query = 'SELECT * FROM users WHERE username = '. $this-> input->post('username'). ' AND password= '. $this-> input->post('password');
$this->db->query($query);
nu om dit probleem op te lossen, moet u een kijkje nemen op CodeIgniter documentatie. Volgens het, de query () functie nemen twee parameters. De eerste is de SQL query, en de tweede zijn de parameters die u wilt binden.
Voorbeeld 1
standaard filtert deze functie alle gebonden parameters om SQL-injecties te voorkomen. Hier is een voorbeeld van de juiste manier om deze functie te gebruiken:
$query = 'SELECT * FROM users WHERE username = ? AND password = ? ';
$this->db->query($query, array($this->input->post('username'), $this-> input-> post('password')));
Voorbeeld 2:
Codeigniter biedt een andere manier om SQL-aanvraag uit te voeren zal SQL-injecties voorkomen. Hier is een voorbeeld van het gebruik van de Active Record Class om SQL injecties te voorkomen:
$this->db->get_where('users',array('username'=>$this->input->post('username') ,'password' => $this->input->post('password')));
hoe te voorkomen dat SQL injectie aanval in CakePHP ?
CakePHP is een snel ontwikkelings framework voor PHP dat algemeen bekende ontwerppatronen gebruikt zoals associatieve data Mapping, Front Controller en MVC. CakePHP bieden een bos van ingebouwde component om de ontwikkeling van webapplicaties te vergemakkelijken en zal waardoor ze veiliger.
CakePHP-apps zijn echter ook kwetsbaar voor SQL-injecties als het niet goed wordt gebruikt. Hier is een voorbeeld van een kwetsbare code voor SQL injectie aanval in dit kader:
$results = $connection-> execute('SELECT * FROM users WHERE username = '. $this->request->getParam('username').' AND password='. $this->request->getParam('password'))->fetchAll('assoc');
de functie execute() gebruikt standaard de voorbereide statements. Echter, het vorige voorbeeld nog steeds kwetsbaar voor SQL injectie aanval, als de gebruikersgegevens rechtstreeks worden ingevoegd in een legitieme SQL verzoek. Hier is een voorbeeld van de juiste manier om deze functie te gebruiken:
$results = $connection->execute('SELECT * FROM users WHERE username = :username AND password=:password', )->fetchAll('assoc');
het CakePHP framework biedt ook een systeem genaamd Query Builder, die gebruikersgegevens filteren dwingt om SQL injectie aanvallen te voorkomen. Volgens CakePHP documentatie, onder de covers, de Query Builder gebruik maken van de voorbereide verklaringen.
hier is een voorbeeld van hoe u een dergelijk systeem op de juiste manier kunt gebruiken:
use Cake\ORM\Locator\LocatorAwareTrait;
$users = $this->getTableLocator()->get('users');
// Start a new query.
$query = $users->find();
$query->where();
hoe te voorkomen dat SQL injectie aanval in FuelPHP ?
FuelPHP is een van de meest recente PHP framework dat werd geboren op basis van de beste ideeën van elk framework in de markt. Het is ontwikkeld met PHP 5 en is volledig objectgeoriënteerd. In FuelPHP, veiligheid was het front en het centrum van zorg,die zijn medewerkers geduwd om vele beveiligingsmechanismen te implementeren om gebruikersgegevens te filteren. SQL injection valt een van de redenen aan om dergelijke mechanismen in FuelPHP te implementeren.
echter, zelfs met zo ‘ n krachtig framework, brengt een eenvoudig misbruik van deze mechanismen de hele code in gevaar voor een SQL injectie aanval. Hier is een voorbeeld van een dergelijke code fout:
$query = "SELECT * FROM article WHERE id = ". Input::get('id');
$result = DB::query($query)->execute();
om dit op te lossen, zijn er ook twee technieken zoals de andere frameworks. De eerste is om daadwerkelijk correct gebruik van de query() functie, door het binden van de parameters zoals het volgende voorbeeld :
$query = "SELECT * FROM article WHERE id = :id"; // our query
$result = DB::query($query)->bind('id', Input::get('id'))->execute();
de tweede oplossing is het gebruik van het ORM-mechanisme geïmplementeerd in het FuelPHP framework om te communiceren met de database. Hier is een voorbeeld van hoe het te gebruiken:
$user = DB::select()->from('article')->where('id', Input::get('id'))->execute();
hoe te voorkomen dat SQL injectie aanval in zend framework ?
Zend framework (gewijzigd in Laminas Project) is een van de meest bekende framework in de wereld van PHP. Het werd ontwikkeld met performance tuning in het achterhoofd, wat verklaart waarom elke nieuwe versie is veel sneller dan de oude. Zend werd ook ontwikkeld met de best security practices, waardoor zijn ontwikkelaars extra beveiligingsmechanismen moesten implementeren om bekende cyberdreigingen aan te pakken.
sommige van deze mechanismen werden geïmplementeerd om de SQL-injectieaanvallen aan te pakken. Maar zoals altijd leidt misbruik van die mechanismen tot een kwetsbare code. In dit deel van het artikel ga ik een voorbeeld van een dergelijke fout laten zien:
$adapter->query('SELECT * FROM `article` WHERE `id` = '. $this->getRequest()->getPost('id'));
hier is hoe deze kwetsbaarheid op te lossen:
$adapter->query('SELECT * FROM `article` WHERE `id` = ?', );
Leave a Reply