SQL-injektio

Kokeneet kirjoittajat eivät ole vielä tarkistaneet sivun nykyistä versiota, ja se voi poiketa merkittävästi 19. joulukuuta 2021 tarkistetusta versiosta . tarkastukset vaativat 9 muokkausta .

SQL-injektio ( englanniksi  SQL-injektio / SQLi ) on yksi yleisimmistä tavoista hakkeroida tietokantoja käyttäviä sivustoja ja ohjelmia , mikä perustuu mielivaltaisen SQL -koodin lisäämiseen kyselyyn .

SQL-injektio, riippuen käytetyn DBMS -järjestelmän tyypistä ja lisäysolosuhteista , voi antaa hyökkääjälle mahdollisuuden suorittaa mielivaltaisen kyselyn tietokantaan ( esimerkiksi lukea minkä tahansa taulukon sisältöä , poistaa, muokata tai lisätä tietoja ), saada mahdollisuuden lukea ja/tai kirjoittaa paikallisia tiedostoja ja suorittaa mielivaltaisia ​​komentoja hyökkäyksen kohteena olevassa palvelimessa.

SQL-injektiotyyppinen hyökkäys voi olla mahdollinen SQL-kyselyissä käytetyn syöttötietojen virheellisen käsittelyn vuoksi.

Tietokantasovelluskehittäjän tulee olla tietoinen tällaisista haavoittuvuuksista ja ryhtyä toimiin torjuakseen SQL-injektointia.

Hyökkäystyypit, kuten SQL-injektio

SQL-injektioon perustuvia hyökkäyksiä on kolme pääluokkaa:

SQL-injektiohyökkäyksen periaate

Oletetaan, että palvelinohjelmisto , joka on saanut id-syöttöparametrin, käyttää sitä SQL-kyselyn luomiseen. Harkitse seuraavaa PHP - skriptiä:

$id = $_REQUEST [ 'id' ]; $res = mysqli_query ( "SELECT * FROM news WHERE id_news = " . $id );

Jos id-parametri, joka on yhtä suuri kuin 5, välitetään palvelimelle (esimerkiksi: http://example.org/script.php?id=5 ), suoritetaan seuraava SQL - kysely:

SELECT * FROM news WHERE id_news = 5

Mutta jos hyökkääjä välittää merkkijonon -1 OR 1=1 id-parametriksi (esimerkiksi näin: http://example.org/script.php?id=-1+OR+1=1 ), pyyntö suoritetaan:

SELECT * FROM news WHERE id_news = - 1 TAI 1 = 1

Siten syöttöparametrien muuttaminen lisäämällä niihin SQL-kielikonstruktioita aiheuttaa muutoksen SQL-kyselyn suorituslogiikassa (tässä esimerkissä valitaan tietyllä tunnisteella olevien uutisten sijaan kaikki tietokannan uutiset, koska lauseke 1=1 on aina totta - laskelmat suoritetaan käyttämällä kaavion lyhintä ääriviivaa ).

Injektio merkkijonoparametreihin

Oletetaan, että palvelinohjelmisto, saatuaan pyynnön etsiä tietoja uutisista hakuteksti-parametrilla, käyttää sitä seuraavassa SQL-kyselyssä (tässä parametrit on ohitettu lainausmerkeillä):

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

Tekemällä kyselyn, kuten http://example.org/script.php?search_text=Test , saamme suoritettavan seuraavan SQL-kyselyn:

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

Mutta upottamalla lainausmerkin (jota käytetään kyselyssä) search_text-parametriin, voimme muuttaa SQL-kyselyn toimintaa huomattavasti. Esimerkiksi välittämällä arvon ' )+ja+(news_id_author='1 ) hakutekstiparametriksi kutsumme suoritettavaa kyselyä:

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

UNIONin käyttö

SQL-kielen avulla voit yhdistää useiden kyselyiden tulokset UNION -operaattorilla . Tämä antaa hyökkääjälle mahdollisuuden päästä luvatta käsiksi tietoihin.

Tarkastellaan uutisten näyttöskriptiä ( näytettävän uutisen tunniste välitetään id -parametrissa ):

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

Jos hyökkääjä antaa id-parametriksi -1 UNION SELECT 4 käyttäjänimen, salasanan,1 FROM admin , tämä aiheuttaa SQL-kyselyn suorittamisen.

SELECT id_news , header , body , author FROM news WHERE id_news = - 1 UNION SELECT 1 , käyttäjätunnus , salasana , 1 FROM admin

Koska uutisia tunnisteella -1 ei varmasti ole olemassa, uutistaulukosta ei valita tietueita, vaan tulokseen tulee tietueita, jotka on valittu laittomasti admin-taulukosta SQL-injektion seurauksena.

Käyttämällä UNION + group_concat()

Joissakin tapauksissa hakkeri voi hyökätä, mutta ei voi nähdä useampaa kuin yhtä saraketta. MySQL : n tapauksessa hyökkääjä voi käyttää toimintoa:

group_concat ( sarake , symboli , sarake )

joka yhdistää useita sarakkeita yhdeksi. Esimerkiksi yllä annetussa esimerkissä funktiokutsu olisi:

- 1 UNION SELECT group_concat ( käyttäjätunnus , 0 x3a , salasana ) järjestelmänvalvojalta _

Kyselyn hännän pakeneminen

Usein SQL-kyselyllä, johon tämä haavoittuvuus vaikuttaa, on rakenne, joka tekee liiton käyttämisen vaikeaksi tai mahdottomaksi. Esimerkiksi skripti:

$res = mysqli_query ( "VALITSE kirjoittaja uutisista WHERE id=" . $_REQUEST [ 'id' ] . " JA kirjoittaja LIKE ('a%')" );

näyttää uutisen kirjoittajan nimen välitetyn id-tunnisteen yhteydessä vain, jos nimi alkaa kirjaimella a ja koodin lisääminen UNION-operaattorilla on vaikeaa.

Tällaisissa tapauksissa hyökkääjät käyttävät menetelmää, jolla osa pyynnöstä pakenee käyttämällä kommenttimerkkejä ( /* tai -- DBMS:n tyypistä riippuen).

Tässä esimerkissä hyökkääjä voi välittää id-parametrin arvolla -1 UNION SELECT -salasana FROM admin/* komentosarjalle ja suorittaa näin kyselyn.

SELECT kirjoittaja FROM news WHERE id =- 1 UNIONIN VALITSE salasana FROM admin /* JA kirjoittaja LIKE ('a%')

jossa osa kyselystä ( AND author LIKE ('a%') ) on merkitty kommentiksi eikä vaikuta suoritukseen.

SQL-kyselyn jakaminen

Symbolia ; käytetään erottamaan komentoja SQL-kielessä ; ( puolipiste ) upottamalla tämän merkin kyselyyn, hyökkääjä voi suorittaa useita komentoja yhdessä kyselyssä, mutta kaikki SQL-murteet eivät tue tätä ominaisuutta.

Esimerkiksi jos skriptiparametreissa

$id = $_REQUEST [ 'id' ]; $res = mysqli_query ( "VALITSE * Uutisista WHERE id_news = $id " );

hyökkääjä välittää rakenteen, joka sisältää puolipisteen, esimerkiksi 12;INSERT INTO admin (käyttäjänimi, salasana) VALUES ('HaCkEr', 'foo'); silloin 2 komentoa suoritetaan yhdessä kyselyssä

SELECT * FROM news WHERE id_news = 12 ; INSERT INTO admin ( käyttäjätunnus , salasana ) VALUES ( 'HaCkEr' , 'foo' );

ja luvaton HaCkEr-tietue lisätään järjestelmänvalvojan taulukkoon.

SQL Injection Attack Techniques

Hyökkäyksille alttiiden komentosarjojen etsiminen

Tässä vaiheessa hyökkääjä tutkii palvelimen komentosarjojen käyttäytymistä manipuloidessaan syöttöparametreja havaitakseen niiden poikkeavan toiminnan. Manipulointi tapahtuu kaikilla mahdollisilla parametreilla:

  • Tiedot kuljetettiin POST- ja GET-menetelmien kautta
  • [HTTP Cookie] -arvot
  • HTTP_REFERER (skripteille)
  • AUTH_USER ja AUTH_PASSWORD (käytettäessä todennusta)

Yleensä manipulointi tarkoittaa yhden (harvoin kaksois- tai taaksepäin) lainauksen korvaamista merkkiparametreissa.

Poikkeava toiminta on mitä tahansa toimintaa, jossa ennen lainauksen korvaamista ja sen jälkeen haetut sivut ovat erilaisia ​​(eikä näytä virheellistä parametrimuotosivua).

Yleisimmät esimerkit poikkeavasta käyttäytymisestä ovat:

  • erilaisia ​​virheilmoituksia näytetään;
  • pyydettäessä tietoja (esimerkiksi uutisia tai tuoteluetteloa) pyydetty tieto ei näy ollenkaan, vaikka sivu näkyy

jne. On syytä muistaa, että on tapauksia, joissa virheilmoitukset sivun merkinnän erityispiirteiden vuoksi eivät näy selaimessa, vaikka ne ovat sen HTML-koodissa.

Design Kommentoi loput rivistä Hanki versio Merkkijonojen ketjutus
MySQL -- ..., /* ..., tai# ... version() concat (string1, string2)
MS SQL -- ... @@version string1 + string2
Oraakkeli -- ...tai/* ... select banner
from v$version
string1 || string2
taiconcat (string1, string2)
MS Access NULL-tavun lisääminen pyyntöön:%00...
PostgreSQL -- ... SELECT version() string1 || string2,CONCAT('a','b')
Sybase -- ... @@version string1 + string2
IBM DB2 -- ... select versionnumber from sysibm.sysversions string1 || string2taistring1 concat string2
Ingres -- ... dbmsinfo('_version') string1 || string2

Suojaus hyökkäyksiltä, ​​kuten SQL-injektio

Tämän tyyppisiltä hyökkäyksiltä suojaamiseksi on tarpeen suodattaa huolellisesti syöttöparametrit, joiden arvoja käytetään SQL-kyselyn rakentamiseen.

Merkkijonoparametrien suodatus

Oletetaan, että pyynnön luova koodi ( Pascal -ohjelmointikielellä ) näyttää tältä:

lauseke := 'SELECT * FROM users WHERE name = "' + userName + '";' ;

Koodin lisäyksen tekeminen (lainausmerkillä alkavan merkkijonon sulkeminen toisella lainauksella ennen kuin se päättyy nykyiseen sulkevaan lainaukseen kyselyn jakamiseksi kahteen osaan) oli mahdotonta, koska joissakin DBMS -järjestelmissä , mukaan lukien MySQL , on lainattava kaikki merkkijonoparametrit . Korvaa itse parametrissa lainausmerkit kirjaimella \, heittomerkki merkillä \', kenoviiva merkillä \\ (tätä kutsutaan " ecaping-erikoismerkeiksi "). Tämä voidaan tehdä seuraavalla koodilla:

lauseke := 'SELECT * FROM users WHERE name = ' + QuoteParam ( userName ) + ';' ; function QuoteParam ( s : string ) : merkkijono ; { syötteessä - merkkijono; tulos on merkkijono lainausmerkeissä ja erikoismerkit korvattu } var i : kokonaisluku ; kohde : merkkijono _ begin Dest := '"' ; for i := 1 pituuteen ( t ) do case s [ i ] of ' ' ' : Kohde := Kohde + '\ '' ' ; ' " ' : Kohde := Kohde + '\"' ; '\' : Kohde := Kohde + '\\' ; else Kohde := Kohde + s [ i ] ; end ; QuoteParam := Kohde + '"' ; loppu ;

PHP:ssä suodatus voi olla seuraava:

$query = "VALITSE * FROM käyttäjiltä WHERE user='" . mysqli_real_escape_string ( $user ) . "';" ;

Suodatetaan kokonaislukuparametreja

Otetaan toinen pyyntö:

lauseke := 'VALITSE * FROM käyttäjiltä WHERE id = ' + id + ';' ;

Tässä tapauksessa kentällä idon numeerinen tyyppi, eikä sitä useimmiten lainata. Siksi "lainaaminen" ja erikoismerkkien korvaaminen escape-sarjoilla ei toimi. Tässä tapauksessa tyypin tarkistus auttaa; jos muuttuja idei ole numero, kyselyä ei pitäisi suorittaa ollenkaan.

Esimerkiksi Delphissä seuraava koodi auttaa estämään tällaisia ​​injektioita:

if TryStrToInt ( id , id_int ) then lauseke := Muoto ( 'SELECT * FROM users WHERE id =%0:d;' , [ id_int ]) ;

PHP:lle tämä menetelmä näyttäisi tältä:

$query = 'VALITSE * FROM käyttäjiltä WHERE id =' . ( int ) $id ;

Syöttöparametrien katkaisu

Jotta SQL-kyselyn suorituslogiikkaa voidaan muuttaa, tarvitaan riittävän pitkiä merkkijonoja. Upotetun merkkijonon vähimmäispituus yllä olevissa esimerkeissä on siis 8 merkkiä (“ 1 TAI 1=1 ”). Jos kelvollisen parametriarvon maksimipituus on pieni, yksi suojausmenetelmistä voi olla syöteparametrien arvojen maksimileikkaus.

Jos esimerkiksi tiedetään, että idyllä olevien esimerkkien kenttä voi ottaa arvoja enintään 9999, voit "leikaista ylimääräiset" merkit jättäen enintään neljä:

lauseke := 'VALITSE * FROM käyttäjiltä WHERE id = ' + LeftStr ( id , 4 ) + ';' ;

Parametrisoitujen kyselyjen käyttäminen

Monet tietokantapalvelimet tukevat parametroitujen kyselyjen (valmiiden lausekkeiden) lähettämistä. Tässä tapauksessa ulkoisen alkuperän parametrit lähetetään palvelimelle erillään itse pyynnöstä tai asiakaskirjasto poistaa ne automaattisesti. Tätä varten niitä käytetään

  • Delphi  - omaisuus TQuery.Params;

Esimerkiksi

var sql , param : merkkijono begin sql := 'valitse :teksti arvoksi dualista' ; param := 'alpha' ; Kysely1 . sql . Teksti : = sql Kysely1 . ParamByName ( 'teksti' ) . AsString := param ; Kysely1 . auki ; ShowMessage ( Query1 [ 'arvo' ]) ; loppu ;
  • Perlissä -  kautta DBI::quotetai DBI::prepare;
  • Javassa  luokan kautta PreparedStatement;
  • in C#  - ominaisuus SqlCommand.Parameters;
  • PHP  - MySQLi (kun työskentelet MySQL : n kanssa ), PDO.

Katso myös

Linkit