SQL-injektion

Den aktuelle version af siden er endnu ikke blevet gennemgået af erfarne bidragydere og kan afvige væsentligt fra den version , der blev gennemgået den 19. december 2021; checks kræver 9 redigeringer .

SQL-injektion ( engelsk  SQL-injection /SQli ) er en af ​​de mest almindelige måder at hacke websteder og programmer på, der arbejder med databaser , baseret på introduktionen af ​​vilkårlig SQL -kode i en forespørgsel .

SQL-injektion, afhængigt af den anvendte type DBMS og betingelserne for injektion, kan gøre det muligt for en angriber at udføre en vilkårlig forespørgsel til databasen ( for eksempel læse indholdet af alle tabeller , slette, ændre eller tilføje data ), få ​​muligheden at læse og/eller skrive lokale filer og udføre vilkårlige kommandoer på den angrebne server.

Et angreb af typen SQL-injektion kan være muligt på grund af forkert behandling af inputdata, der bruges i SQL-forespørgsler.

En databaseapplikationsudvikler bør være opmærksom på sådanne sårbarheder og tage skridt til at imødegå SQL-injektion.

Typer af angreb såsom SQL-injektion

Der er tre hovedklasser af angreb baseret på SQL-injektion:

SQL Injection Attack Princip

Lad os sige, at serversoftwaren , efter at have modtaget id-inputparameteren, bruger den til at oprette en SQL-forespørgsel. Overvej følgende PHP -script:

$id = $_REQUEST [ 'id' ]; $res = mysqli_query ( "VÆLG * FRA nyheder WHERE id_news = " . $id );

Hvis en id-parameter lig med 5 sendes til serveren (for eksempel: http://example.org/script.php?id=5 ), vil følgende SQL - forespørgsel blive udført:

VÆLG * FRA nyheder WHERE id_news = 5

Men hvis en angriber sender strengen -1 ELLER 1=1 som id-parameteren (f.eks. sådan: http://example.org/script.php?id=-1+OR+1=1 ), så anmodning vil blive udført:

VÆLG * FRA nyheder HVOR id_news = - 1 ELLER 1 = 1

Ændring af inputparametrene ved at tilføje SQL-sprogkonstruktioner til dem forårsager således en ændring i SQL-forespørgselsudførelseslogikken (i dette eksempel vil alle nyheder i databasen blive valgt i stedet for nyheder med en given identifikator, da udtrykket 1=1 er altid sand - beregninger udføres ved hjælp af den korteste kontur i diagrammet ).

Injektion i strengparametre

Antag, at serversoftwaren, efter at have modtaget en anmodning om at søge efter data i nyhederne med parameteren search_text, bruger den i følgende SQL-forespørgsel (her er parametrene escaped med anførselstegn):

$search_text = $_REQUEST [ 'søgetekst' ]; $res = mysqli_query ( "SELECT id_news, news_date, news_caption, news_text, news_id_author FROM news WHERE news_caption LIKE('% $search_text %')" );

Ved at lave en forespørgsel som http://example.org/script.php?search_text=Test , får vi følgende SQL-forespørgsel, der skal udføres:

SELECT id_news , news_date , news_caption , news_text , news_id_author FROM news WHERE news_caption LIKE ( '%Test%' )

Men ved at indlejre et anførselstegn (som bruges i forespørgslen) i parameteren search_text, kan vi drastisk ændre adfærden for SQL-forespørgslen. For eksempel, ved at overføre værdien ' )+and+(news_id_author='1 ) som search_text-parameteren kalder vi forespørgslen, der skal udføres:

SELECT id_news , news_date , news_caption , news_text , news_id_author FROM news WHERE news_caption LIKE ( '%' ) og ( news_id_author = '1%' )

Brug af UNION

SQL-sproget giver dig mulighed for at kombinere resultaterne af flere forespørgsler ved hjælp af UNION -operatoren . Dette giver en angriber mulighed for at få uautoriseret adgang til data.

Lad os overveje nyhedsvisningsscriptet ( identifikationen af ​​de nyheder, der skal vises, sendes i id-parameteren ):

$res = mysqli_query ( "SELECT id_news, header, body, author FROM news WHERE id_news = " . $_REQUEST [ 'id' ]);

Hvis en angriber sender -1 UNION SELECT 4 brugernavn, adgangskode,1 FROM admin som id-parameteren , vil dette få SQL-forespørgslen til at blive udført

SELECT id_news , header , body , author FROM news WHERE id_news = - 1 UNION SELECT 1 , brugernavn , adgangskode , 1 FROM admin

Da nyheder med identifikator -1 bestemt ikke eksisterer, vil der ikke blive valgt poster fra nyhedstabellen, men resultatet vil inkludere poster, der er ulovligt valgt fra admin-tabellen som følge af SQL-injektion.

Brug af UNION + group_concat()

I nogle tilfælde kan en hacker angribe, men kan ikke se mere end én kolonne. I tilfælde af MySQL kan en angriber bruge funktionen:

gruppe_konkat ( col , symbol , col )

som kombinerer flere kolonner til én. For eksempel vil funktionskaldet for eksemplet ovenfor være:

- 1 UNION SELECT group_concat ( brugernavn , 0 x3a , adgangskode ) FRA admin

Forespørgselshale undslipper

Ofte har SQL-forespørgslen, der er påvirket af denne sårbarhed, en struktur, der gør det vanskeligt eller umuligt at bruge union. For eksempel script:

$res = mysqli_query ( "VÆLG forfatter FRA nyheder WHERE id=" . $_REQUEST [ 'id' ] . " OG forfatter LIKE ('a%')" );

viser kun nyhedsforfatterens navn med det beståede id-id, hvis navnet starter med bogstavet a, og kodeindsprøjtning ved hjælp af UNION-operatøren er vanskelig.

I sådanne tilfælde bruger angribere metoden til at undslippe en del af anmodningen ved hjælp af kommentartegn ( /* eller -- afhængigt af typen af ​​DBMS).

I dette eksempel kan en angriber videregive id-parameteren med værdien -1 UNION SELECT password FROM admin/* til scriptet og dermed udføre forespørgslen

VÆLG forfatter FRA nyheder WHERE id =- 1 UNION VÆLG adgangskode FRA admin /* OG forfatter LIKE ('a%')

hvor en del af forespørgslen ( OG forfatter LIKE ('a%') ) er markeret som en kommentar og ikke påvirker udførelsen.

Opdeling af en SQL-forespørgsel

Symbolet; bruges til at adskille kommandoer i SQL-sproget ; ( semikolon ) ved at indlejre dette tegn i en forespørgsel, er en angriber i stand til at udføre flere kommandoer i en enkelt forespørgsel, men ikke alle SQL-dialekter understøtter denne funktion.

For eksempel, hvis i script-parametrene

$id = $_REQUEST [ 'id' ]; $res = mysqli_query ( "VÆLG * FRA nyheder WHERE id_news = $id " );

angriberen sender en konstruktion, der indeholder et semikolon, for eksempel 12;INSERT INTO admin (brugernavn, adgangskode) VALUES ('HaCkEr', 'foo'); derefter vil 2 kommandoer blive udført i én forespørgsel

VÆLG * FRA nyheder WHERE id_news = 12 ; INSERT INTO admin ( brugernavn , adgangskode ) VÆRDIER ( 'HackEr' , 'foo' );

og en uautoriseret HackEr-post vil blive tilføjet til admin-tabellen.

SQL Injection Attack Techniques

Finder scripts sårbare over for angreb

På dette stadium undersøger angriberen serverscripts adfærd, når han manipulerer inputparametre for at opdage deres unormale adfærd. Manipulation sker med alle mulige parametre:

  • Data passeret gennem POST- og GET-metoderne
  • [HTTP Cookie] værdier
  • HTTP_REFERER (til scripts)
  • AUTH_USER og AUTH_PASSWORD (når du bruger godkendelse)

Som regel kommer manipulation ned til at erstatte et enkelt (sjældent dobbelt eller tilbage) citat i karakterparametrene.

Unormal adfærd er enhver adfærd, hvor siderne, der hentes før og efter citatsubstitutionen, er forskellige (og ikke viser siden med ugyldigt parameterformat).

De mest almindelige eksempler på unormal adfærd er:

  • forskellige fejlmeddelelser vises;
  • når der anmodes om data (f.eks. nyheder eller en liste over produkter), vises de anmodede data slet ikke, selvom siden vises

osv. Man skal huske på, at der er tilfælde, hvor fejlmeddelelser på grund af sidemarkeringens specifikationer ikke er synlige i browseren, selvom de er til stede i dens HTML-kode.

Design Kommenterer resten af ​​linjen Hent version Sammenkædning af strenge
MySQL -- ..., /* ..., eller# ... version() concat (string1, string2)
MS SQL -- ... @@version string1 + string2
Oracle -- ...eller/* ... select banner
from v$version
string1 || string2
ellerconcat (string1, string2)
MS Access Injicere en NULL-byte i en anmodning:%00...
PostgreSQL -- ... SELECT version() string1 || string2,CONCAT('a','b')
Sybase -- ... @@version string1 + string2
IBM DB2 -- ... select versionnumber from sysibm.sysversions string1 || string2ellerstring1 concat string2
Ingres -- ... dbmsinfo('_version') string1 || string2

Beskyttelse mod angreb såsom SQL-injektion

For at beskytte mod denne type angreb er det nødvendigt at omhyggeligt filtrere inputparametrene, hvis værdier vil blive brugt til at bygge SQL-forespørgslen.

Filtrering af strengparametre

Lad os antage, at koden, der genererer anmodningen (i Pascal -programmeringssproget ) ser sådan ud:

statement := 'SELECT * FROM users WHERE name = "' + brugernavn + '";' ;

For at lave kodeinjektion (lukning af en streng, der starter med et citat med et andet citat, før det slutter med det aktuelle afsluttende citat for at opdele forespørgslen i to dele) var det umuligt, for nogle DBMS , inklusive MySQL , er det påkrævet at citere alle strengparametre . I selve parameteren skal du erstatte anførselstegnene med \", apostrof med \', omvendt skråstreg med \\ (dette kaldes " escaped special characters "). Dette kan gøres med følgende kode:

statement := 'SELECT * FROM users WHERE name = ' + QuoteParam ( brugernavn ) + ';' ; funktion QuoteParam ( s : streng ) : streng ; { ved input - en streng; outputtet er en streng i anførselstegn og med specialtegn erstattet } var i : heltal ; dest : streng _ start Dest := '"' ; for i := 1 til længde ( r ) gør tilfælde s [ i ] af ' '' ' : Dest := Dest + '\ '' ' ; '"' : Dest := Dest + '\"' ; '\' : Dest := Dest + '\\' ; else Dest := Dest + s [ i ] ; end ; QuoteParam := Dest + '"' ; ende ;

For PHP kan filtrering være sådan:

$query = "VÆLG * FRA brugere WHERE user='" . mysqli_real_escape_string ( $user ) . "';" ;

Filtrering af heltalsparametre

Lad os tage en anden forespørgsel:

statement := 'SELECT * FROM users WHERE id = ' + id + ';' ;

I dette tilfælde har feltet iden numerisk type, og det er oftest ikke citeret. Derfor virker det ikke at "citere" og erstatte specialtegn med escape-sekvenser. I dette tilfælde hjælper typekontrol; hvis variablen idikke er et tal, bør forespørgslen slet ikke køre.

For eksempel i Delphi hjælper følgende kode med at modvirke sådanne injektioner:

hvis TryStrToInt ( id , id_int ) then statement := Format ( 'SELECT * FROM users WHERE id =%0:d;' , [ id_int ]) ;

For PHP vil denne metode se sådan ud:

$query = 'VÆLG * FRA brugere WHERE id = ' . ( int ) $id ;

Trunkering af inputparametre

For at foretage ændringer i logikken i at udføre en SQL-forespørgsel kræves indsprøjtning af tilstrækkeligt lange strenge. Så minimumslængden af ​​den indlejrede streng i ovenstående eksempler er 8 tegn (" 1 ELLER 1=1 "). Hvis den maksimale længde af en gyldig parameterværdi er lille, kan en af ​​beskyttelsesmetoderne være den maksimale trunkering af inputparameterværdier.

For eksempel, hvis det er kendt, at feltet idi ovenstående eksempler ikke kan have værdier på mere end 9999, kan du "skære de ekstra" tegn fra og ikke efterlade mere end fire:

statement := 'SELECT * FROM users WHERE id = ' + LeftStr ( id , 4 ) + ';' ;

Brug af parametriserede forespørgsler

Mange databaseservere understøtter muligheden for at sende parametriserede forespørgsler (forberedte udsagn). I dette tilfælde sendes parametre af ekstern oprindelse til serveren separat fra selve anmodningen, eller de undslippes automatisk af klientbiblioteket. Til dette bruges de

  • i Delphi  - ejendom TQuery.Params;

For eksempel

var sql , param : streng start sql := 'vælg :tekst som værdi fra dual' ; param := 'alpha' ; Forespørgsel 1 . SQL . Tekst : = sql Forespørgsel 1 . ParamByName ( 'tekst' ) . AsString := param ; Forespørgsel 1 . åben ; ShowMessage ( Query1 [ 'værdi' ]) ; ende ;
  • i Perl  - gennem DBI::quoteeller DBI::prepare;
  • i Java  , gennem klassen PreparedStatement;
  • i C#  - egenskab SqlCommand.Parameters;
  • i PHP  - MySQLi (når du arbejder med MySQL ), PDO.

Se også

Links