SQL-Injektio

(MySQL) ORDER BY ja Virhepohjainen Tekniikka

Keskitaso
45 min

ORDER BY

SQL:n ORDER BY -lauseke, kuten olet jo UNION-tekniikkaan tutustuessa oppinut, lajittelee tietokannasta palautuneet rivit joko sarakkeen nimen tai järjestysnumeron (ordinal) perusteella. ORDER BY ottaa lisäksi suuntaparametrin, jonka arvo voi olla ASC (ascending = nouseva) tai DESC (descending = laskeva).

Esimerkiksi tällainen kysely hakisi kaikki rivit tuotteet-taulusta ja lajittelisi ne hinnan mukaan nousevassa (halvin ensin) järjestyksessä:

SELECT * FROM tuotteet ORDER BY hinta ASC

Injektio

Mutta entäs jos SQL injektio onkin ORDER BY -lausekkeessa? Tällaista haavoittuvuutta esiintyy melko usein, kun sovellukset esimerkiksi antavat käyttäjän järjestää taulukon tietyn sarakkeen mukaan.

Otetaan käytännön esimerkki tutusta verkkopankista. Kontaktilistauksen voi lajitella etunimen, sukunimen, sähköpostin tai tilinumeron perusteella.

Sovellus ottaa lajitteluparametrin query-parametrina (URL-osoitteesta) ja käyttää parametria rakentamaan SQL-kyselyn.

SELECT * FROM user ORDER BY email ASC

Mitä tapahtuu jos sovellus on haavoittuva SQL -injektiohyökkäyksille ja hyökkääjä antaakin sort-parametrin arvoksi "email UNION SELECT username, password FROM users-- "?

Hyvä idea! Valitettavasti kuitenkaan...

UNION ei toimi

SQL-syntaksi ei salli UNION-lausekkeita enää ORDER BY jälkeen. Toisin sanoen, injektiopiste on liian myöhään SQL-kyselyn rakenteessa, jotta voisimme enää käyttää UNION-tekniikkaa. Voit toki kokeilla! Mutta näin siinä käy:

Joudumme siis turvautumaan hieman luovempaan, niin kutsuttuun virhepohjaiseen tekniikkaan.

Virhepohjainen tekniikka

Virhepohjaisen tekniikan perusidea on seuraavanlainen:

  • Rakennetaan tahallaan SQL-kysely, joka aiheuttaa virheen.
  • Huolehditaan, että virhe sisältää tiedot, joita halutaan tietokannasta viedä.
  • Tuodaan virhe meidän (hyökkääjän) näkyville.

Onnistuakseen virhepohjainen tekniikka vaatii siis että sovellus palauttaa tekniset virheilmoitukset sellaisenaan palvelimelta selaimelle meidän nähtäväksi. Tämä on yksi syy, miksi tietoturvatarkastajat muistavat aina huomauttaa sovelluksen virheidenhallinnan tärkeydestä. Virheiden vuotaminen tekee haavoittuvuuksien löytämisestä ja hyväksikäyttämisestä merkittävästi helpompaa, ja tässä tapauksessa ylipäätään mahdollista.

SQL-syntaksi sisältää monenlaisia funktioita. Olemme tähän mennessä tutustuneet vain concat-funktioon joka yhdistelee tekstiä. Nyt tutustumme toiseen funktioon, nimeltä ExtractValue, joka liittyy XML-käsittelyyn. Funktion "oikea" käyttötarkoitus ei ole tärkeä, mutta tässä on kuitenkin esimerkki siitä miten sitä olisi tarkoitus käyttää:

EXTRACTVALUE('<autot><auto>Lada</auto></autot>', '/autot/auto')
-> Lada

Funktio siis ottaa ensimmäisenä parametrina XML:ää, ja toisena parametrina XPATH-valitsimen, jolla poimitaan tietoja XML:stä. Ei haittaa, jos et tiedä mitä XML ja XPATH ovat, opit niistä toisella kurssilla. Oleellista on, että ExtractValue-funktio aiheuttaa epäonnistuessaan virheen, joka tulostaa XPATH-valitsimen.

SELECT EXTRACTVALUE(0, "<VIRHEELLINEN")

Miten siis saisimme XPATH-valitsimen arvon sisältämään sekä < -merkin (joka aiheuttaa tarvittavan virheen) että mitä tahansa mitä tietokannasta halutaan nähdä? Tietysti CONCAT-funktiolla, yhdistämällä < -merkin ja alikyselyn! Molempien (concat ja alikyselyt) pitäisi olla sinulle jo tuttuja.

EXTRACTVALUE(0, CONCAT("<", (SELECT @@version)))

Mutta mihin kohtaan ExtractValue tulee?

Yksi helppo vaihtoehto on tehdä ORDER BY -kyselylle toinen lajitteluparametri. ORDER BY -syntaksi tukee useampaa parametria, esimerkiksi näin: Kysely listaisi tuotteet hinnan mukaan järjesteltynä, ja niistä, joiden hinta on sama, näytettäisiin ensin ne, jotka ovat varastossa.

SELECT * FROM tuotteet ORDER BY hinta, varastossa

Voimme laittaa alikyselyn toiseksi järjestysparametriksi, näin:

SELECT * FROM tuotteet ORDER BY hinta, (SELECT ExtractValue(...))

Summaus

  • Lisää kyselyyn uusi ORDER BY -lajitteluparametri (eli pilkku edellisen perään), ja laita sen arvoksi uusi alikysely.
  • Kommentoi loput kyselystä ulos (-- ).
  • Muodosta alikysely niin, että se käyttää ExtractValue-funktiota, ensimmäisenä parametrina vaikka numeroa 0 (tällä ei ole juurikaan väliä), ja toisena parametrina CONCAT-funktiokutsua, joka puolestaan ottaa ensimmäisenä parametrina < -merkin ja toisena parametrina alikyselyn, joka hakee tiedot joita haluat nähdä.
  • Tiedot, jotka haluat nähdä, ovat CONCAT(email, ":", password) FROM user WHERE admin=True LIMIT 1 eli sähköposti ja salasana ensimmäiseltä admin-käyttäjältä, varmistaen LIMIT-lausekkeella ettei alikysely palauta ylimääräisiä rivejä, joka pilaisi hyökkäyksen.
  • Sovelluksen pitäisi palauttaa virheilmoitus, jossa on tieto, jonka haluat nähdä.

MySQLi ORDER BY Virhepohjainen Tekniikka

Tässä labrassa tutustut syvemmin ORDER BY -lausekkeeseen, saat lisää harjoitusta alikyselyiden käytöstä, ja ennen kaikkea pääset harjoittelemaan virhepohjaista SQL-injektiotekniikkaa.

Tavoite

Kirjaudu järjestelmänvalvojana sisään.

Tehtävät

Flag

Löydä lippu (flag) labraympäristöstä ja syötä se alle.

hakatemia pro

Valmis ryhtymään eettiseksi hakkeriksi?
Aloita jo tänään.

Hakatemian jäsenenä saat rajoittamattoman pääsyn Hakatemian moduuleihin, harjoituksiin ja työkaluihin, sekä pääset discord-kanavalle jossa voit pyytää apua sekä ohjaajilta että muilta Hakatemian jäseniltä.