Home » Ontwikkeling, Sekuriteit
06.06.2020 Category: Ontwikkeling, Sekuriteit
Dink u dat u SQL-databasis performant en veilig is vir onmiddellike vernietiging? Wel, SQL-inspuiting stem nie saam nie!
Ja, dit is 'n onmiddellike vernietiging waaroor ons praat, want ek wil nie hierdie artikel open met die gewone lam terminologie van "verskerping van veiligheid" en "voorkoming van kwaadwillige toegang nie." SQL Injection is so 'n ou truuk in die boek dat almal, elke ontwikkelaar, baie goed daarvan weet en goed weet hoe om dit te voorkom. Behalwe vir die een of ander tyd wanneer dit gly, en die resultate kan niks minder as rampspoedig wees nie.
As u reeds weet wat SQL-inspuiting is, kan u vry wees om na die laaste helfte van die artikel oor te gaan. Maar vir diegene wat pas opdaag op die gebied van webontwikkeling en wil droom om meer senior rolle te beklee, is 'n paar inleiding in orde.
1 Wat is SQL-inspuiting?
2 Voorkoming van SQL-inspuiting in PHP
3 Voorkom die gebruik van WAF
4 SQL-inspuiting en moderne PHP-raamwerke
Wat is SQL-inspuiting?
Die sleutel tot die verstaan ​​van SQL-inspuiting is in die naam: SQL + Injection. Die woord "inspuiting" hier het geen mediese konnotasies nie, maar die gebruik van die werkwoord "inspuit". Hierdie twee woorde dra saam die idee om SQL in 'n webtoepassing te plaas.
Sit SQL in 'n webtoepassing. . . hmmm. . . Is dit nie wat ons in elk geval doen nie? Ja, maar ons wil nie hê dat 'n aanvaller ons databasis moet bestuur nie. Laat ons dit verstaan ​​met behulp van 'n voorbeeld.
Gestel u bou 'n tipiese PHP-webwerf vir 'n plaaslike e-handelswinkel, en besluit dan om 'n kontakvorm soos hierdie by te voeg:
Laat ons aanneem dat die lêer send_message.php alles in 'n databasis stoor, sodat die winkeleienaars later later gebruikersboodskappe kan lees. Dit het dalk 'n kode soos hierdie:
$ naam = $ _POST ['naam'];
$ boodskap = $ _POST ['boodskap'];
// kyk of hierdie gebruiker reeds 'n boodskap het
mysqli_query ($ conn, "KIES * uit boodskappe waar naam = $ naam");
// Ander kode hier
U probeer dus eers kyk of hierdie gebruiker reeds 'n ongeleesde boodskap het. Die navraag SELECT * uit boodskappe waar naam = $ naam eenvoudig genoeg lyk, reg?
In ons onskuld het ons die deure oopgemaak vir die onmiddellike vernietiging van ons databasis. Om dit te kan doen, moet die aanvaller aan die volgende voorwaardes voldoen:
Die toepassing word uitgevoer op 'n SQL-databasis (vandag is byna elke toepassing)
Die huidige databasisverbinding het toestemmings vir "wysig" en "verwyder" op die databasis
Die name van die belangrike tabelle kan geraai word
Die derde punt beteken dat noudat die aanvaller weet dat u 'n e-handelswinkel bestuur, u die bestellingsdata waarskynlik in 'n bestellingstabel sal stoor. Gewapen met dit alles, moet die aanvaller dit doen as hul naam:
Joe; bestellings af te sny ;? Ja meneer! Kom ons kyk wat die navraag sal word as dit deur die PHP-skrif uitgevoer word:
KIES * UIT Boodskappe WAAR naam = Joe; afgekapte bestellings;
Goed, die eerste deel van die navraag het 'n sintaksfout (geen aanhalings rondom "Joe" nie), maar die semi-kolon dwing die MySQL-enjin om 'n nuwe een te begin interpreteer: bestellings afkap. Net so is die hele bestelgeskiedenis in een enkele draai!
Noudat u weet hoe SQL-inspuiting werk, is dit tyd om te kyk hoe u dit kan stop. Die twee voorwaardes wat aan 'n suksesvolle SQL-inspuiting moet voldoen, is:
Die PHP-skrip moet op die databasis wysigings / uitvee hê. Ek dink dit is waar van alle toepassings en u kan nie u toepassings slegs leesbaar maak nie. Guess En raai wat, selfs al verwyder ons alle wysigingsvoorregte, kan SQL-inspuiting nog steeds iemand toelaat om SELECT-navrae uit te voer en al die databasisse, sensitiewe data wat daarin is, te besigtig. Met ander woorde, die vermindering van toegang tot die databasis werk nie, en u toepassing het dit in elk geval nodig.
Gebruikersinvoer word verwerk. Die enigste manier waarop SQL-inspuiting kan werk, is wanneer u data van gebruikers aanvaar. Weereens is dit nie prakties om alle insette vir u aansoek te stop nie, net omdat u bekommerd is oor SQL-inspuiting.
Voorkoming van SQL-inspuiting in PHP
Aangesien databasisverbindings, navrae en gebruikersinsette nou deel uitmaak van die lewe, hoe kan ons SQL-inspuiting voorkom? Gelukkig is dit redelik eenvoudig, en daar is twee maniere om dit te doen: 1) gebruikerinvoer te ontsmet en 2) voorbereide stellings te gebruik.
As u 'n ouer PHP-weergawe (5.5 of laer gebruik, en dit gebeur baie met gedeelde hosting), is dit verstandig om al u gebruikersinvoer te gebruik via 'n funksie genaamd mysql_real_escape_string (). Wat dit doen, verwyder eintlik alle spesiale karakters in 'n string, sodat hulle hul betekenis verloor as dit deur die databasis gebruik word.
Byvoorbeeld, as u 'n string het soos ek 'n string is, kan die enkele aanhalingskarakter (') deur 'n aanvaller gebruik word om die databasisvraag wat geskep word te manipuleer en 'n SQL-inspuiting te veroorsaak. Deur dit deur mysql_real_escape_string () te laat loop, is ek 'n string, wat 'n terugslag by die enkele aanhaling voeg, en dit vrylaat. Gevolglik word die hele string nou as 'n onskadelike string na die databasis oorgedra, in plaas daarvan om aan die navraagmanipulasie deel te neem..
Daar is een nadeel met hierdie benadering: dit is 'n baie ou tegniek wat saam met die ouer vorme van databasistoegang in PHP werk. Vanaf PHP 7 bestaan ​​hierdie funksie nie eens meer nie, wat ons na ons volgende oplossing bring.
Gebruik voorbereide stellings
Opgestelde opmerkings is 'n manier om databasisvrae veiliger en betroubaar te maak. Die idee is dat in plaas daarvan om die rou navraag na die databasis te stuur, ons eers aan die databasis die struktuur van die navraag wat ons sal stuur, vertel. Dit is wat ons bedoel met die opstel van 'n verklaring. Sodra 'n verklaring opgestel is, stuur ons die inligting as in parameterreeks insette sodat die databasis 'die gapings kan vul' deur die insette in te sluit by die navraagstruktuur wat ons voorheen gestuur het. Dit verwyder die spesiale krag wat die insette kan hê, waardeur dit in die hele proses as bloot veranderlikes (of as u wil) beskou word. Hoe lyk voorbereide verklarings:
$ gebruikersnaam = "username";
$ wagwoord = "wagwoord";
// Skep verbinding
$ conn = nuwe mysqli ($ servername, $ gebruikersnaam, $ wagwoord, $ dbname);
// Kontroleer verbinding
sterf ("Verbinding misluk: " . $ conn->connect_error);
// berei en bind
$ stmt = $ konn->voor te berei ("VERGOED IN MyGuests (voornaam, van, e-pos) WAARDES (?,?,?)");
$ stmt->bind_param ("sss", $ voornaam, $ van, $ e-pos);
// stel parameters en voer uit
$ voornaam = "John";
$ familienaam = "Doe";
$ e-pos = "[Email protected]";
$ stmt->uit te voer ();
$ voornaam = "Mary";
$ familienaam = "Moe";
$ voornaam = "Julie";
$ familienaam = "Dooley";
eggo "Nuwe rekords is suksesvol geskep";
Ek weet die proses klink onnodig ingewikkeld as u nuut is met voorbereide stellings, maar die konsep is die moeite werd. hier is 'n lekker inleiding daaraan.
Vir diegene wat reeds vertroud is met die uitbreiding van die PDO van PHP en dit gebruik om voorbereide stellings te maak, het ek 'n klein advies.
Waarskuwing: Wees versigtig as u BOB instel
As ons BOB vir databasistoegang gebruik, kan ons 'n verkeerde gevoel van sekuriteit kry. 'Nou ja, ek gebruik BOB. Nou hoef ek nie aan iets anders te dink nie "- dit is hoe ons denke oor die algemeen verloop. Dit is waar dat BOB (of MySQLi-voorbereide stellings) voldoende is om allerlei SQL-inspuitingsaanvalle te voorkom, maar u moet versigtig wees wanneer u dit instel. Dit is normaal om kode van tutoriale of van u vorige projekte af te plak en aan te gaan, maar hierdie instelling kan alles ongedaan maak:
$ dbConnection->setAttribute (BOB: ATTR_EMULATE_PREPARES, waar);
Wat hierdie instelling doen, is om die PDO te sê om voorbereide stellings na te boots eerder as om die voorbereide stellingsfunksie van die databasis te gebruik. Gevolglik stuur PHP eenvoudige navrae-snare na die databasis, selfs al lyk dit asof u kode voorbereide stellings skep en parameters instel en dit alles. Met ander woorde, u is net so kwesbaar vir SQL-inspuiting soos voorheen. ��
Die oplossing is eenvoudig: maak seker dat hierdie emulasie onwaar is.
$ dbConnection->setAttribute (BOB: ATTR_EMULATE_PREPARES, onwaar);
Nou word die PHP-skrif gedwing om voorbereide verklarings op databasisvlak te gebruik, wat voorkom dat alle SQL-inspuitings voorkom.
Voorkom die gebruik van WAF
Weet u dat u ook webtoepassings teen SQL-inspuiting kan beskerm deur WAF (firewall) te gebruik?
Wel, nie net SQL-inspuiting nie, maar baie ander laag 7-kwesbaarhede, soos skripsies op verskillende terreine, stukkende verifikasie, vervalsing van webwerwe, blootstelling aan data, ens. Óf u kan self gehuisves word soos Mod Security of cloud-based soos die volgende:.
SQL-inspuiting en moderne PHP-raamwerke
Die SQL-inspuiting is so gereeld, so maklik, so frustrerend en so gevaarlik dat alle moderne PHP-webraamwerke ingebou is met teenmaatreëls. In WordPress het ons byvoorbeeld die $ wpdb->funksie voor te berei (), terwyl u 'n MVC-raamwerk gebruik, dit alle vuil werk vir u doen, en u nie eers hoef te dink om SQL-inspuiting te voorkom nie. Dit is 'n bietjie irriterend dat u in WordPress uitsprake eksplisiet moet voorberei, maar hey, dit is WordPress waaroor ons praat. ��
Hoe dit ook al sy, my punt is dat die moderne ras van webontwikkelaars nie oor SQL-inspuiting hoef te dink nie, en gevolglik is hulle nie eens bewus van die moontlikheid nie. As sodanig, selfs al laat hulle een agterdeur oop in hul toepassing (miskien is dit 'n $ _GET-navraagparameter en ou gewoontes om 'n vuil navraag in te skiet), kan die resultate katastrofies wees. Dit is dus altyd beter om die tyd te neem om dieper in die fondamente te duik.
SQL Injection is 'n baie nare aanval op 'n webtoepassing, maar word maklik vermy. Soos ons in hierdie artikel sien, is versigtig met die verwerking van gebruikersinvoer (terloops, SQL-inspuiting nie die enigste bedreiging wat die hantering van gebruikersinvoere inhou nie) en die vrae oor die databasis is daarvoor. Dit gesê, ons werk nie altyd in die veiligheid van 'n webraamwerk nie, so dit is beter om bewus te wees van hierdie soort aanval en nie daarvoor te val nie..