SQL Injection on tietoturvavirhe verkkosovelluksissa, joihin hyökkääjät lisäävät haitallista SQL-koodia käyttäjän syöttämällä. Tämä voi antaa heille mahdollisuuden käyttää arkaluonteisia tietoja muuttaa tietokannan sisältöä tai jopa ottaa järjestelmän hallintaansa. SQL Injectionin tunteminen on tärkeää, jotta verkkosovellukset pysyvät turvassa.
SQL-injektio (SQLi) on tietoturvahaavoittuvuus, joka syntyy, kun hyökkääjä voi manipuloida verkkosovelluksen tietokantakyselyitä lisäämällä haitallista SQL-koodia käyttäjän syöttökenttiin. Nämä lisätyt kyselyt voivat manipuloida taustalla olevaa tietokantaa noutaakseen muokata tai poistaa arkaluontoisia tietoja. Joissakin tapauksissa hyökkääjät voivat jopa laajentaa oikeuksiaan saadakseen täyden hallinnan tietokannasta tai palvelimesta.

Esimerkki tosielämästä:
Vuonna 2019 Capital One Data Breach johtui väärin määritetystä verkkosovelluksesta, jonka ansiosta hyökkääjä pystyi hyödyntämään SQL-lisäyksen haavoittuvuutta. Tämä johti yli 100 miljoonan asiakkaan henkilötietojen vuotamiseen, mukaan lukien nimet, osoitteet ja luottotiedot.
SQL-injektion suojaustaso
DVWA tarjoaa neljä suojaustasoa SQL Injectionille, jotta oppilaat näkevät, kuinka erilaiset suojaukset vaikuttavat hyökkäyksiin:
1. Matala turvallisuus
Sovellus ottaa syötteesi ja laittaa sen suoraan SQL-kyselyyn ilman suodatusta.
$id = $_GET['id'];$query = 'SELECT first_name last_name FROM users WHERE user_id = '$id';';- Sisääntulo
':Katkaisee kyselyn ja saa tietokannan antamaan virheilmoituksen, joka paljastaa sen olevan haavoittuvainen. - Sisääntulo
1' OR '1'='1:Huijaa kyselyn olemaan aina totta, jotta kaikki käyttäjät palautetaan. - Sisääntulo
1' UNION SELECT user password FROM users--:Liittyy toiseen kyselyyn piilotettujen tietojen, kuten käyttäjänimien ja salasanojen, hakemiseksi.
2. Keskitasoinen turvallisuus
Sovellus suorittaa perussyötteiden desinfioinnin käyttämällä toimintoja, kutenaddslashes()paeta'.
$id = addslashes($_GET['id']);$query = 'SELECT first_name last_name FROM users WHERE user_id = '$id';';Kuinka hyökkäys voi olla:
Yksinkertainen'injektio ei toimi enää (koska siitä tulee').
Mutta hyökkääjät voivat silti ohittaa käyttämällä numeroinjektiota (koska numerot eivät tarvitse lainausmerkkejä).
Esimerkki:
tietokoneen keksimisvuosi
1 OR 1=1Tämä palauttaa silti kaikki tietueet.
3. Korkea turvallisuus
Sovellus käyttää valmiita lausuntoja (parametrisoituja kyselyitä) käsitelläkseen käyttäjän syötteitä turvallisesti.
$stmt = $pdo->prepare('SELECT first_name last_name FROM users WHERE user_id = ?');$stmt->execute([$id]);Hyökkäys:
Yrittää kuten' OR 1=1taiUNION SELECTei enää toimi.
Kysely käsittelee kaikkia syötteitä tietoina, ei SQL-koodina.
SQL-injektion tyypit
SQL-injektiotyyppejä on erilaisia
1. Virhepohjainen SQL-injektio
Virhepohjainen SQL-injektio on eräänlainen kaistan sisäinen SQL-lisäys, jossa hyökkääjä saa tietokannan tarkoituksella luomaan virhesanoman. Hyökkääjä analysoi tämän virhesanoman saadakseen arvokasta tietoa tietokannan rakenteesta, kuten taulukoiden ja sarakkeiden nimistä, joita voidaan käyttää tarkempien hyökkäysten tekemiseen.
Miten se toimii
Tämä hyökkäys kohdistuu sovelluksiin, jotka paljastavat raakatietokantavirheet yleisten viestien sijaan. Lisäämällä haitallista syötettä, joka rikkoo SQL-syntaksin, hyökkääjät laukaisevat nämä virheet ja saavat arvokkaita vihjeitä tietokannan rakenteesta.
kat timpf nettovarallisuus
- Tunnista haavoittuva syöte: Hyökkääjä löytää syöttökentän, kuten hakupalkin tai URL-parametrin, joka on suoraan vuorovaikutuksessa tietokannan kanssa ilman asianmukaista syötteen puhdistusta.
- Lisää haitallinen hyötykuorma: Hyökkääjä syöttää erikoismerkin (kuten yhden lainauksen
') tai toiminto, jonka tiedetään aiheuttavan tietokantavirheen. - Analysoi virhe: Tietokanta, joka ei pysty käsittelemään väärin muotoiltua kyselyä, palauttaa yksityiskohtaisen virhesanoman. Tämä viesti voi paljastaa tärkeitä tietoja, kuten:
- Tietokantajärjestelmä (esim. MySQL Oracle SQL Server).
- Tietokannan versio.
- Täysi SQL-kysely suoritetaan.
- Tietyt syntaksivirheet, joita voidaan käyttää taulukoiden tai sarakkeiden nimien ymmärtämiseen.
- Tarkenna hyökkäystä: Virheilmoituksesta kerättyjen tietojen avulla hyökkääjä voi tarkentaa hyötykuormaa ja poimia lisää tietoja, kuten käyttäjätunnuksia ja salasanoja.
Esimerkki:
Vaihe 1: Määritä ympäristösi
- Käynnistä DVWA. Sitä käytetään yleensä siirtymällä URL-osoitteeseen, kuten
http://localhost/dvwaselaimessasi.
- Kirjaudu DVWA:han oletustunnuksilla:
admin/password.
- Siirry DVWA Security -välilehdelle ja aseta suojaustaso alhaiseksi. Tämä varmistaa, että haavoittuvuuksia on helppo hyödyntää.
Vaihe 2: Tunnista haavoittuvuus
SQL Injection -sivulla on yksinkertainen syöttöruutu, johon voit syöttää käyttäjätunnuksen. Taustakysely on todennäköisesti jotain tällaistaSELECT * FROM users WHERE id = 'user_input'
- Anna kelvollinen tunnus, kuten
1syöttöruutuun ja napsauta Lähetä. Sinun pitäisi nähdä tiedot käyttäjästä, jolla on tunnus 1.
SQL-injektiolähde
PHP $id = $_REQUEST[ 'id' ]; switch ($_DVWA['SQLI_DB']) { case MYSQL: // Check database $query = 'SELECT first_name last_name FROM users WHERE user_id = '$id';'; $result = mysqli_query($GLOBALS['___mysqli_ston'] $query ) or die( ''
. ((is_object($GLOBALS['___mysqli_ston'])) ? mysqli_error($GLOBALS['___mysqli_ston']) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '' ); // Get results while( $row = mysqli_fetch_assoc( $result ) ) { // Get values $first = $row['first_name']; $last = $row['last_name']; // Feedback for end user echo 'ID:
{$id}
First name: {$first}
Surname: {$last}'; } mysqli_close($GLOBALS['___mysqli_ston']); break; case SQLITE: global $sqlite_db_connection; #$sqlite_db_connection = new SQLite3($_DVWA['SQLITE_DB']); #$sqlite_db_connection->enableExceptions(true); $query = 'SELECT first_name last_name FROM users WHERE user_id = '$id';'; #print $query; try { $results = $sqlite_db_connection->query($query); } catch (Exception $e) { echo 'Caught exception: ' . $e->getMessage(); exit(); } if ($results) { while ($row = $results->fetchArray()) { // Get values $first = $row['first_name']; $last = $row['last_name']; // Feedback for end user echo 'ID:
{$id}
First name: {$first}
Surname: {$last}'; } } else { echo 'Error in fetch '.$sqlite_db->lastErrorMsg(); } break; } } ode ?> - Yritä nyt katkaista kysely. Kirjoita yksi lainaus
'syöttökenttään ja lähetä.
Kyselystä tulee:
SELECT * FROM users WHERE id = ''';Tässä tietokanta näkee ylimääräisen lainauksen eikä tiedä kuinka kyselyä täytetään.
kapselointi java
Sen sijaan, että sovellus näyttäisi sinulle käyttäjätiedot, se palauttaa SQL-virheen (kuten "SQL-syntaksissasi on virhe...")
Tätä kutsutaan virhepohjaiseksi SQL-injektioksi, koska:
- Hyökkääjä lähettää virheellisen syötteen (
') - Tietokanta antaa virheen
- Tämä virhe vuotaa hyödyllistä tietoa tietokannasta (kuten DB:n sarakkeiden lukumäärän rakenteen tyyppi jne.)
2. Union-pohjainen SQL-injektio
Unioniin perustuva SQL Injection on tekniikka, jossa hyökkääjät käyttävätUNIONoperaattori yhdistää kahden tai useamman tuloksetSELECTlausunnot yhdeksi tulosjoukoksi. Tämä voi antaa heille mahdollisuuden poimia tietoja muista tietokannan taulukoista. TheUNIONoperaattoria voidaan käyttää vain, jos:
- Molemmissa kyselyissä on sama määrä sarakkeita
- Sarakkeissa on samanlaisia tietotyyppejä
- Sarakkeet ovat samassa järjestyksessä
UNION-operaattori :UNION-operaattoria käytetään kahden tai useamman tulosjoukon yhdistämiseenSELECTlausunnot.
- Jokainen
SELECTlausunto sisälläUNIONon oltava sama määrä sarakkeita - Sarakkeissa on oltava samanlaiset tietotyypit
- Sarakkeiden on oltava samassa järjestyksessä
SELECT column_name(s) FROM table1UNIONSELECT column_name(s) FROM table2Esimerkki:
Vaihe 1: Ensinnäkin meidän on löydettävä verkkosivustolla olevan taulukon sarakkeiden lukumäärä UNION-pohjaisen SQL-injektion syöttämiseksi:
SQL Injection -sivulla on yksinkertainen syöttöruutu, johon voit syöttää käyttäjätunnuksen. Taustakysely on todennäköisesti jotain tällaista
SELECT * FROM users WHERE id = 'user_input'Yritä nyt katkaista kysely. Kirjoita yksi lainaus'syöttökenttään ja lähetä.
Jos sovellus on haavoittuvainen, saat yksityiskohtaisen virheilmoituksen. Se voi näyttää tältä:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''' at line 1
Vaihe 2: KäytäUNIONAvainsana sarakkeiden määrän selvittämiseen
KäyttääksesiUNIONavainsana (yleinen seuraava vaihe), sinun on tiedettävä alkuperäisen kyselyn sarakkeiden määrä. Voit selvittää tämän käyttämälläORDER BYlauseke
komento arp-a
- Yritä lajitella tulokset sarakkeen mukaan
1:1 ORDER BY 1.
- Lähetä. Sen pitäisi toimia.
SQL-injektiolähde
PHP if( isset( $_REQUEST[ 'Submit' ] ) ) { // Get input $id = $_REQUEST[ 'id' ]; switch ($_DVWA['SQLI_DB']) { case MYSQL: // Check database $query = 'SELECT first_name last_name FROM users WHERE user_id = '$id';'; $result = mysqli_query($GLOBALS['___mysqli_ston'] $query ) or die( ''
. ((is_object($GLOBALS['___mysqli_ston'])) ? mysqli_error($GLOBALS['___mysqli_ston']) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '' ); // Get results while( $row = mysqli_fetch_assoc( $result ) ) { // Get values $first = $row['first_name']; $last = $row['last_name']; // Feedback for end user echo 'ID:
{$id}
First name: {$first}
Surname: {$last}'; } mysqli_close($GLOBALS['___mysqli_ston']); break; case SQLITE: global $sqlite_db_connection; #$sqlite_db_connection = new SQLite3($_DVWA['SQLITE_DB']); #$sqlite_db_connection->enableExceptions(true); $query = 'SELECT first_name last_name FROM users WHERE user_id = '$id';'; #print $query; try { $results = $sqlite_db_connection->query($query); } catch (Exception $e) { echo 'Caught exception: ' . $e->getMessage(); exit(); } if ($results) { while ($row = $results->fetchArray()) { // Get values $first = $row['first_name']; $last = $row['last_name']; // Feedback for end user echo 'ID:
{$id}
First name: {$first}
Surname: {$last}'; } } else { echo 'Error in fetch '.$sqlite_db->lastErrorMsg(); } break; } } ?> - Kasvata numeroa:
1 ORDER BY 2. Lähetä. Sen pitäisi toimia.
- Jatka lisäämistä, kunnes saat virheilmoituksen. Esimerkiksi
1 ORDER BY 4voi antaa sinulle:Unknown column '4' in 'order clause' - Tämä tarkoittaa, että kyselyssä on 3 saraketta.
3. Sokeapohjainen SQL-injektio
Sokea SQL-injektio tapahtuu, kun hyökkääjät eivät näe kyselyn tuloksia suoraan verkkosivulla. Sen sijaan ne päättelevät tietoja sovelluksen käyttäytymisen tai vasteajan pienistä muutoksista. Vaikka hitaampi ja tylsempi kuin klassinen SQLi, se voi olla yhtä tehokas.
Tietojen takaisin saamisen sijaan hyökkääjä päättelee tiedot tarkkailemalla verkkosivun toimintaa. Tämä tehdään yleensä kahdella tavalla:
- Boolean-pohjainen sokea SQLi: Hyökkääjä syöttää SQL-kyselyn, joka palauttaa a totta tai väärä tulos. Verkkosovelluksen vastaus muuttuu sen mukaan, onko kysely tosi vai epätosi. Sivu voi esimerkiksi näyttää erilaisen viestin tai näyttää erilaisen asettelun.
- Aikaperusteinen sokea SQLi: Hyökkääjä syöttää SQL-kyselyn, joka saa tietokannan suorittamaan aikaa vievän toiminnon (kuten
SLEEP()toiminto), jos ehto täyttyy. Hyökkääjä tarkkailee sivun latautumiseen kuluvaa aikaa määrittääkseen, oliko lisätty ehto tosi vai epätosi.
Esimerkki:
Kuvittele kirjautumissivu, jolle annat käyttäjätunnuksen ja salasanan. Sovellus rakentaa SQL-kyselyn seuraavasti:
SELECT * FROM users WHERE username = 'user_input' AND password = 'password_input'Sokea SQL-injektio sisältäisi tiedoston manipuloinninuser_inputkenttään kysyäksesi tietokannasta kysymyksen.
Suoran vastauksen sijaan hyökkääjä voi kokeilla jotain tällaista:
user_input = 'admin' AND 1=1; --Jos sivu latautuu normaalisti, hyökkääjä tietää sen1=1on a totta lausunto.
user_input = 'admin' AND 1=2; --Jos sivulla näkyy virhe tai se käyttäytyy eri tavalla, hyökkääjä tietää sen1=2on a väärä lausunto.
Käyttämällä sarjaa näitä tosi/epätosi kysymyksiä hyökkääjä voi systemaattisesti arvata ja poimia tietoja merkin kerrallaan. Prosessi voidaan automatisoida arvaamaan kaiken taulukoiden nimistä käyttäjien salasanoihin.
SQL-injektiohyökkäysten vaikutus
- Luvaton pääsy arkaluontoisiin tietoihin : Hyökkääjät voivat hakea tietokantaan tallennettuja henkilökohtaisia taloudellisia tai luottamuksellisia tietoja.
- Tietojen eheysongelmat : Hyökkääjät voivat muokata poistaa tai vioittaa tärkeitä tietoja, jotka vaikuttavat sovelluksen toimintaan.
- Etuoikeuksien eskaloituminen : Hyökkääjät voivat ohittaa todennusmekanismit ja saada järjestelmänvalvojan oikeudet.
- Palveluseisokki : SQL-injektio voi ylikuormittaa palvelinta aiheuttaen suorituskyvyn heikkenemistä tai järjestelmän kaatumista.
- Mainevaurioita : Onnistunut hyökkäys voi vahingoittaa vakavasti organisaation mainetta ja johtaa asiakkaiden luottamuksen menettämiseen.
SQL-injektiohyökkäysten estäminen
On olemassa useita parhaita käytäntöjä SQL-injektiohyökkäysten estämiseksi:
1. Käytä valmiita lausuntoja ja parametroituja kyselyitä
Valmistetut lauseet ja parametroidut kyselyt varmistavat, että käyttäjän syötteitä käsitellään tietoina eikä osana SQL-kyselyä. Tämä lähestymistapa eliminoi SQL-lisäyksen riskin.
Esimerkki PHP:ssä (käyttäen MySQLiä):
$stmt = $conn->prepare('SELECT * FROM users WHERE username = ? AND password = ?'); $stmt->bind_param('ss' $username $password); $stmt->execute();2. Käytä tallennettuja toimenpiteitä
Tallennetut toimintosarjat ovat ennalta määritettyjä SQL-kyselyitä, jotka on tallennettu tietokantaan. Nämä toimenpiteet voivat auttaa estämään SQL-lisäyksen, koska ne eivät rakenna SQL-kyselyitä dynaamisesti.
piilotetut sovellukset
Esimerkki:
CREATE PROCEDURE GetUserByUsername (IN username VARCHAR(50)) BEGIN SELECT * FROM users WHERE username = username; END;3. Valkoisen listan syötteen vahvistus
Varmista, että käyttäjän syötteet on tarkistettu ennen kuin niitä käytetään SQL-kyselyissä. Salli vain tietyt merkit ja kuviot, kuten aakkosnumeerinen syöttö kenttiin, kuten käyttäjänimiin tai sähköpostiosoitteisiin.
4. Käytä ORM-kehyksiä
Object-Relational Mapping (ORM) -kehykset, kuten Lepotila tai Entity Framework voi auttaa estämään SQL-injektoinnin käsittelemällä automaattisesti kyselyn luomisen estämällä dynaamisen kyselyn rakentamisen.
5. Rajoita tietokannan käyttöoikeuksia
Myönnä käyttäjille vaadittavat vähimmäistietokantaoikeudet. Varmista, että sovellukset voivat suorittaa vain tarpeellisia toimintoja (esim. SELECT INSERT) ja rajoittaa käyttöoikeuksia, kuten DROP TABLE tai ALTER.
6. Virheiden käsittely
Määritä tietokanta ja sovellus niin, että ne eivät näytä yksityiskohtaisia virheilmoituksia käyttäjälle. Sen sijaan kirjaa virheet sisäisesti ja näytä yleisiä virheilmoituksia loppukäyttäjille.