Hva er SQL-injeksjon og hvordan forhindre jeg i PHP-applikasjoner?

Så du tror at SQL-databasen din er performant og trygg mot øyeblikkelig ødeleggelse? SQL Injection er uenig!


Ja, det er øyeblikkelig ødeleggelse vi snakker om, fordi jeg ikke ønsker å åpne denne artikkelen med den vanlige haltende terminologien “strammere sikkerhet” og “forhindre ondsinnet tilgang.” SQL Injection er et så gammelt triks i boken at alle, enhver utvikler, kjenner godt til den og er godt klar over hvordan de kan forhindre det. Bortsett fra det en merkelig gang når de glir opp, og resultatene kan være intet mindre enn katastrofale.

Hvis du allerede vet hva SQL Injection er, kan du gjerne hoppe til siste halvdel av artikkelen. Men for de som nettopp kommer opp innen webutvikling og drømmer om å ta på seg mer seniorroller, er en viss introduksjon i orden.

Hva er SQL Injection?

Nøkkelen til å forstå SQL Injection er i navnet: SQL + Injection. Ordet “injeksjon” her har ikke noen medisinske konnotasjoner, men er snarere bruken av verbet “injiserer.” Sammen formidler disse to ordene ideen om å sette SQL i en nettapplikasjon.

Sette SQL i en webapplikasjon. . . hmmm. . . Er det ikke det vi gjør uansett? Ja, men vi vil ikke at en angriper skal drive databasen vår. La oss forstå det ved hjelp av et eksempel.

La oss si at du bygger et typisk PHP-nettsted for en lokal e-handelsbutikk, så du bestemmer deg for å legge til et kontaktskjema som dette:

Navnet ditt

Din beskjed

La oss anta at filen send_message.php lagrer alt i en database slik at butikkeierne kan lese brukermeldinger senere. Det kan ha noen kode som dette:

<?php

$ name = $ _POST [‘name’];
$ melding = $ _POST [‘melding’];

// sjekk om denne brukeren allerede har en melding
mysqli_query ($ conn, "VELG * fra meldinger der navn = $ navn");

// Annen kode her

Så du prøver først å se om denne brukeren allerede har en ulest melding. Spørsmålet VELG * fra meldinger der navn = $ navn virker enkelt nok, ikke sant?

FEIL!

I vår uskyld har vi åpnet dørene for øyeblikkelig ødeleggelse av databasen vår. For at dette skal skje, må angriperen ha følgende betingelser oppfylt:

  • Applikasjonen kjører på en SQL-database (i dag er nesten alle applikasjoner)
  • Den nåværende databaseforbindelsen har “rediger” og “slett” tillatelser i databasen
  • Navnene på de viktige tabellene kan gjettes

Det tredje punktet betyr at nå som angriperen vet at du driver en e-handelsbutikk, vil du sannsynligvis lagre ordredataene i en ordretabell. Bevæpnet med alt dette, er alt angriperen trenger å gjøre å oppgi dette som deres navn:

Joe; avkort ordrer ;? Ja, sir! La oss se hva spørringen blir når den blir kjørt av PHP-skriptet:

VELG * FRA meldinger HVOR navn = Joe; avkort ordrer;

OK, den første delen av spørringen har en syntaksfeil (ingen anførselstegn rundt “Joe”), men semikolon tvinger MySQL-motoren til å begynne å tolke en ny: avkort ordrer. Akkurat sånn, i en eneste swoop, er hele ordrehistorikken borte!

Nå som du vet hvordan SQL Injection fungerer, er det på tide å se på hvordan du stopper det. De to betingelsene som må oppfylles for vellykket SQL-injeksjon er:

  1. PHP-skriptet skal ha endring / sletting av rettigheter i databasen. Jeg tror at dette stemmer med alle applikasjoner, og at du ikke vil gjøre programmene dine skrivebeskyttet. �� Og gjett hva, selv om vi fjerner alle modifiseringsrettigheter, kan SQL-injeksjon fortsatt tillate noen å kjøre SELECT-spørsmål og se alle databasene, sensitive data som er inkludert. Med andre ord, å redusere databaseadgangsnivået fungerer ikke, og applikasjonen din trenger det uansett.
  2. Brukerinndata blir behandlet. Den eneste måten SQL-injeksjon kan fungere på er når du godtar data fra brukere. Nok en gang er det ikke praktisk å stoppe alle innganger for søknaden din bare fordi du er bekymret for SQL-injeksjon.

Forhindrer SQL-injeksjon i PHP

Nå, med tanke på at databaseforbindelser, spørsmål og brukerinnganger er en del av livet, hvordan forhindrer vi SQL-injeksjon? Heldigvis er det ganske enkelt, og det er to måter å gjøre det på: 1) desinfisere brukerinnsats, og 2) bruke utarbeidede uttalelser.

Rense brukerinndata

Hvis du bruker en eldre PHP-versjon (5.5 eller lavere, og dette skjer mye på delt hosting), er det lurt å kjøre alle brukerinndataene dine gjennom en funksjon som heter mysql_real_escape_string (). I utgangspunktet fjerner alle spesialtegn i en streng slik at de mister betydningen når de brukes av databasen.

For eksempel, hvis du har en streng som jeg er en streng, kan en enkelt sitatkarakter (‘) brukes av en angriper til å manipulere databaseforespørselen som opprettes og forårsake en SQL-injeksjon. Å kjøre den gjennom mysql_real_escape_string () produserer jeg en streng, som legger til et tilbakeskritt til det eneste sitatet og slipper unna det. Som et resultat blir hele strengen nå sendt som en ufarlig streng til databasen, i stedet for å kunne delta i spørringmanipulering.

Det er en ulempe med denne tilnærmingen: det er en virkelig, virkelig gammel teknikk som følger med de eldre formene for databasetilgang i PHP. Fra PHP 7 finnes denne funksjonen ikke engang lenger, noe som bringer oss til vår neste løsning.

Bruk forberedte utsagn

Utarbeidede uttalelser er en måte å lage databasespørsmål på en tryggere og pålitelig måte. Ideen er at i stedet for å sende den rå spørringen til databasen, forteller vi først databasen strukturen til spørringen vi sender. Dette er hva vi mener med å “utarbeide” en uttalelse. Når en uttalelse er utarbeidet, passerer vi informasjonen som parametriiserte innganger, slik at databasen kan “fylle hullene” ved å koble inngangene til spørringstrukturen vi sendte før. Dette tar bort all spesiell kraft som inngangene kan ha, og får dem til å bli behandlet som bare variabler (eller nyttelast, hvis du vil) i hele prosessen. Slik ser forberedte utsagn ut:

<?php
$ servernamn = "lokal vert";
$ brukernavn = "brukernavn";
$ passord = "passord";
$ dbname = "mydb";

// Opprett forbindelse
$ conn = nytt mysqli ($ servernnavn, $ brukernavn, $ passord, $ dbname);

// Kontroller tilkoblingen
if ($ konn->connect_error) {
dø("Tilkoblingen mislyktes: " . $ conn->connect_error);
}

// forberede og bind
$ stmt = $ conn->forberede("INSERT I MyGuests (fornavn, etternavn, e-post) VERDIER (?,?,?)");
$ stmt->bind_param ("sss", $ fornavn, $ etternavn, $ e-post);

// angi parametere og kjør
$ fornavn = "John";
$ etternavn = "Doe";
$ e-post = "[Email protected]";
$ stmt->henrette();

$ fornavn = "Mary";
$ etternavn = "Moe";
$ e-post = "[Email protected]";
$ stmt->henrette();

$ fornavn = "Julie";
$ etternavn = "Dooley";
$ e-post = "[Email protected]";
$ stmt->henrette();

ekko "Nye poster ble opprettet";

$ stmt->Lukk();
$ conn->Lukk();
?>

Jeg vet at prosessen høres unødvendig kompleks ut hvis du er ny på forberedte utsagn, men konseptet er vel verdt innsatsen. her er en fin introduksjon til det.

For de som allerede er kjent med PHPs PDO-utvidelse og bruker den til å lage forberedte uttalelser, har jeg et lite råd.

Advarsel: Vær forsiktig når du setter opp PUD

Når vi bruker PUD for databasetilgang, kan vi bli sugd inn i en falsk følelse av sikkerhet. “Ah, vel, jeg bruker PDO. Nå trenger jeg ikke å tenke på noe annet ”- det er slik tankegangen generelt går. Det er sant at PUD (eller MySQLi-utarbeidede uttalelser) er nok til å forhindre alle slags SQL-injeksjonsangrep, men du må være forsiktig når du konfigurerer den. Det er vanlig å bare kopiere og lime inn kode fra opplæringsprogrammer eller fra tidligere prosjekter og gå videre, men denne innstillingen kan angre alt:

$ dbConnection->setAttribute (PDO :: ATTR_EMULATE_PREPARES, true);

Hva denne innstillingen gjør er å be PDO om å etterligne forberedte utsagn i stedet for å faktisk bruke den utarbeidede uttalelsesfunksjonen i databasen. Følgelig sender PHP enkle spørringsstrenger til databasen, selv om koden din ser ut som om den lager forberedte utsagn og angir parametere og alt dette. Med andre ord, du er like sårbar for SQL-injeksjon som før. ��

Løsningen er enkel: sørg for at denne emuleringen er satt til usann.

$ dbConnection->setAttribute (PDO :: ATTR_EMULATE_PREPARES, falsk);

Nå tvinges PHP-skriptet til å bruke forberedte uttalelser på et databasenivå, noe som forhindrer alle slags SQL-injeksjoner.

Forhindrer bruk av WAF

Vet du at du også kan beskytte webapplikasjoner mot SQL-injeksjon ved å bruke WAF (webapplikasjonsbrannmur)?

Vel, ikke bare SQL-injeksjon, men mange andre lag 7-sårbarheter som scripting på tvers av nettsteder, ødelagt autentisering, forfalskning på tvers av steder, dataeksponering, etc. Enten kan du bruke self-host som Mod Security eller skybasert som følgende.

SQL-injeksjon og moderne PHP-rammer

SQL-injeksjonen er så vanlig, så lett, så frustrerende og så farlig at alle moderne PHP-nettrammer er innebygd med mottiltak. I WordPress har vi for eksempel $ wpdb->forberede () -funksjon, mens hvis du bruker en MVC-rammeverk, gjør det alt det skitne arbeidet for deg, og du trenger ikke en gang å tenke på å forhindre SQL-injeksjon. Det er litt irriterende at du i WordPress må utarbeide uttalelser eksplisitt, men hei, det er WordPress vi snakker om. ��

Uansett, poenget mitt er at den moderne rasen av webutviklere ikke trenger å tenke på SQL-injeksjon, og som et resultat er de ikke engang klar over muligheten. Som sådan, selv om de lar en bakdør stå åpen i applikasjonen sin (kanskje det er en $ _GET-spørringsparameter og gamle vaner med å skyte av med et skittent spørrespark), kan resultatene være katastrofale. Så det er alltid bedre å ta seg tid til å dykke dypere i grunnlaget.

Konklusjon

SQL Injection er et veldig stygt angrep på en webapplikasjon, men unngås lett. Som vi så i denne artikkelen, å være forsiktig når du behandler brukerinndata (forresten, SQL Injection er ikke den eneste trusselen som håndtering av brukerinndata bringer) og spørring i databasen er alt det er for det. Når det er sagt, jobber vi ikke alltid med sikkerhet for en nettramme, så det er bedre å være klar over denne typen angrep og ikke falle for det.

Jeffrey Wilson Administrator
Sorry! The Author has not filled his profile.
follow me
    Комментариев нет, будьте первым кто его оставит

    Комментарии закрыты.

    Adblock
    detector