Kas teid rünnatakse? Võtke ühendust intsidentidele reageerimise meeskonnaga

Veebiturvalisus

Leidke ja asendage stringina ehitatud SQL-päringud parameetritega

Kuidas leida rakenduskoodist ja talletatud protseduuridest liidetud SQL, asendada see seotud parameetritega ja piirata andmebaasi õigusi.

Saadaval ka:EnglishTürkçeDeutschFrançaisEspañolItalianoPolskiNederlands

Illustratsioon: Leidke ja asendage stringina ehitatud SQL-päringud parameetritega

Iga SQL-lause, mis on ehitatud stringide liitmisega ja sisaldab ebausaldusväärseid väärtusi, on süstitav ning parandus on igas keeles sama: hoidke SQL muutumatuna ja siduge väärtused parameetritena. OWASP Query Parameterization Cheat Sheet paigutab SQL injection'i kategooriasse A05:2025-Injection dokumendis OWASP Top 10:2025 ja nimetab seda üheks ohtlikumaks veebinõrkuseks.

Miks liitmine ei toimi

SQL ei erista tegelikult juhtimistasandit ja andmetasandit. Ründaja paneb sisendisse metamärgi ning SQL-käsud ilmuvad sinna, kus neid varem polnud. OWASP kogukonna leht SQL injection'i kohta näitab liitmisega ehitatud C#-päringut:

string query = "SELECT * FROM items WHERE owner = '"
    + userName + "' AND itemname = '"
    + ItemName.Text + "'";

Kui ründaja sisestab eseme nimeks name' OR 'a'='a, on tingimus alati tõene. Päring tagastab kõik items-tabeli read, olenemata nende omanikust. Sõltuvalt andmebaasi võimalustest ja õigustest võib sama nõrkus lubada ka andmeid muuta, mõjutada faile või käivitada operatsioonisüsteemi käske.

Väärtuse päritolul pole tähtsust. Kontrollid kehtivad ka siis, kui andmed tulevad HTTP-päringust, teisest teenusest või varem salvestatud andmetest.

Leidke stringina ehitatud päringud

Alustage grep'iga SQL-i märksõnade järgi, mis asuvad liitmise või vormindamise läheduses. Need mustrid on ligikaudne esmane läbivaatus, mitte skanner. Need annavad palju müra ja jätavad märkamata päringud, mis on jaotatud mitmele reale.

# concatenation (Java, C#, JavaScript, PHP uses "." instead of "+")
grep -rnEi "(select|insert into|update|delete from)[^;]*[\"'] *\+" src/
# Python f-strings and .format()
grep -rnEi "f[\"'](select|insert|update|delete)|(select|insert|update|delete).*\.format\(" .
# JavaScript template literals
grep -rnEi '`(select|insert|update|delete)[^`]*\$\{' src/
# sprintf-style formatting
grep -rnEi "sprintf\(.*(select|insert|update|delete)" .

Lugege läbi iga tabamus ja kontrollige, et ebausaldusväärsed väärtused on seotud, mitte liidetud. Seejärel vaadake kohti, mille grep sageli vahele jätab:

  • ORM-i päringustringid. Hibernate'i päringud võivad olla haavatavad, kui väärtused liidetakse päringustringi, selle asemel et neid siduda.
  • Talletatud protseduurid. Need hoiavad SQL-i andmebaasis, kuid pole automaatselt turvalised. OWASP näitab PL/SQL-protseduuri, mis liidab usr ja itm päringustringiks ning on tema sõnul "vulnerable to the same SQL injection attack shown in the first example". Väljakutse argumentide sidumine kaitseb väljakutset, mitte protseduuri sees ehitatud dünaamilist SQL-i.
  • Kliendipoolne parametriseerimine. Paljud kliendipoolsed teegid ehitavad päringud stringide liitmisega ja saadavad serverile toorpäringu. Veenduge, et parametriseerimine toimub serveri poolel.
  • Dünaamilised identifikaatorid ja sorteerimissuunad. Neid ei saa siduda, seetõttu püsib liitmine just neis ka pärast parametriseerimise läbivaatust.

Seejärel testige. OWASP Web Security Testing Guide sisaldab SQL injection'i teste käsitsi ja automatiseeritud testimiseks, sealhulgas blind- ja out-of-band-tehnikaid. Väline kontroll selle kohta, mille teie läbivaatus märkamata jättis, on penetratsioonitesti ülesanne.

Asendage need parameetritega

Määrake SQL-i struktuur andmeväärtustest eraldi ning siduge väärtused andmebaasi API kaudu. See on näide dokumendist OWASP SQL Injection Prevention Cheat Sheet, kus ressursside vabastamine ja veahaldus on välja jäetud:

String query = "SELECT account_balance FROM user_data WHERE user_name = ?";
PreparedStatement statement = connection.prepareStatement(query);
statement.setString(1, customerName);
ResultSet results = statement.executeQuery();

Väärtust, näiteks tom' or '1'='1, käsitletakse nüüd sobitatava kasutajanimena sõna-sõnalt. Kui liidate ebausaldusväärse väärtuse päringusse enne selle ettevalmistamist, kaotab kaitse mõju.

ORM-i puhul siduge väärtused samuti päringustringis. OWASP-i näited kasutavad HQL-is nimega parameetrit FROM Inventory i WHERE i.productDescription = :productDescription ja annavad väärtuse edasi meetodiga setParameter.

Talletatud protseduuride sees oleva dünaamilise SQL-i jaoks kasutage bind-muutujaid. Oracle PL/SQL-is tähendab see EXECUTE IMMEDIATE koos USING-iga. SQL Serveris tähendab see sp_executesql-i koos deklareeritud parameetriloendiga. Protseduurid, milles pole dünaamilist SQL-i, ei vaja midagi erilist, sest nende parameetrid on juba seotud.

Sidumine takistab väärtusel SQL-i süntaksit muuta. See ei otsusta, kas päringu tegijal on õigus vastavale kontole juurde pääseda, seega jäävad teie autoriseerimiskontrollid paigale.

Mida parameetrid katta ei saa

Parameetrimärgid tähistavad andmeväärtusi. Need ei saa tähistada tabelinimesid, veerunimesid ega märksõnu nagu ASC ja DESC. Kui kasutajad peavad valima, seostage valik väikese hulga rakenduse enda tokenitega ja lükake tundmatu tagasi. Enne:

String query = "SELECT id, name FROM items ORDER BY name " + sortParam;

Pärast:

Map<String, String> directions = Map.of("asc", "ASC", "desc", "DESC");
String direction = directions.get(sortParam);
if (direction == null) {
    throw new IllegalArgumentException("Unknown sort direction");
}
String query = "SELECT id, name FROM items ORDER BY name " + direction;

Päringule lisatav tekst on nüüd alati üks kahest literaalist, mitte see, mille kasutaja saatis. Siduge samas päringus jätkuvalt iga andmeväärtus, isegi kui see läbib tüübi-, pikkuse- või vormingukontrolli.

Ärge toetuge käsitsi escape'imisele. See sõltub SQL-i murdest ja konfiguratsioonist: näiteks MySQL-i režiim NO_BACKSLASH_ESCAPES lülitab kaldkriipsuga escape'imise välja. OWASP märgib escape'imise tungivalt mittesoovitatavaks ja kirjeldab deny list'e kui auke täis.

Piirake kahju

Vähimate õiguste printsiip ei hoia SQL injection'it ära. See piirab, mida ründaja saab andmebaasikonto kaudu teha, seega rakendage seda parameetritega koos.

  • Alustage nullist ja lisage õigused, mida iga rakenduse konto vajab. Laiast õigustekogumist ära võetava väljaselgitamine on just see, kuidas õigusi kahe silma vahele jääb.
  • Rakenduse konto jaoks DBA- või admin-ligipääsu andmine on tavaline otsetee, sest kõik "lihtsalt töötab". OWASP nimetab seda väga ohtlikuks.
  • Sisselogimislehele piisab kasutajanime ja parooli väljade lugemisõigusest ning kirjutusõigust pole vaja. Registreerumisleht vajab insert-õigust. Seda eristust saab jõustada ainult siis, kui need kasutavad eri andmebaasikasutajaid, seega andke igale veebirakendusele oma kasutaja.
  • Ründajatel ei ole üledimensioneeritud konto kuritarvitamiseks injection'it vaja. Nad võivad muuta parameetri lubatud väärtuse mõneks teiseks, millele neil luba pole, kuid rakendusel on, mistõttu aitavad kitsad õigused ka siis, kui päringud on korras.
  • Vaade (view) võib avaldada ainult need väljad, mida konto vajab, kusjuures SELECT antakse vaatele, mitte tabelile. Kontrollige enne oma andmebaasi reegleid: PostgreSQL kontrollib aluseks oleva tabeli ligipääsu tavaliselt vaate omaniku õiguste alusel. Vaadete vastu tehtavad päringud vajavad samuti parameetreid.
  • Oluline on ka operatsioonisüsteemi konto. Ärge käivitage DBMS-i root- või system-kasutajana. OWASP märgib, et MySQL töötab Windowsis vaikimisi system-kasutajana.

Kust alustada

  1. Koostage loend kõigist kohtadest, kus SQL-i ehitatakse: rakenduskood, ORM-i päringustringid ja talletatud protseduurid, mis kasutavad dünaamilist SQL-i. Käivitage esmaseks läbivaatuseks ülaltoodud grep-mustrid.
  2. Asendage liidetud väärtused seotud parameetritega, serveri poolel, ning ehitage protseduuride sees olev dünaamiline SQL ümber bind-muutujatega.
  3. Asendage dünaamilised tabeli-, veeru- ja sorteerimisvalikud fikseeritud vastendustega, mis lükkavad tundmatu sisendi tagasi.
  4. Auditeerige andmebaasikontosid. Eemaldage rakenduse kontodelt DBA- ja admin-õigused, andke igale rakendusele oma kasutaja ning viige ainult lugemisõigus kitsastele õigustele või vaadetele.
  5. Käivitage tulemuse vastu Web Security Testing Guide'i SQL injection'i testid või paluge muudatused üle vaadata meie turvalise tarkvaraarenduse meeskonnal.

Kuidas saame aidata

Läbistustestimine

Ründame teie võrke, rakendusi ja inimesi nagu päris vastane ning näitame, kuidas iga turvaauk sulgeda.

Kirjutage meile
AngelForce’i meeskond

Kirjutanud AngelForce’i meeskond: CEH-, LPT Masteri ja CISA-sertifikaadiga turvakonsultandid, kes testivad, jälgivad ja kaitsevad organisatsioonide süsteeme kogu Euroopas.

Artikkel on kirjutatud tehisintellekti abil allpool loetletud avalike allikate põhjal ning AngelForce’i meeskond vaatas selle enne avaldamist üle.

Allikad

  1. cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html
  2. cheatsheetseries.owasp.org/cheatsheets/Query_Parameterization_Cheat_Sheet.html
  3. community.owasp.org/attacks/SQL_Injection

Artiklid teemal „Veebiturvalisus“

Rääkige meile, mida soovite kaitsta

Kirjeldage oma keskkonda ja seda, mida soovite saavutada. Vastame e-posti teel.

Kirjutage meile
info@angelforce.eu +372 5705 2044

AngelForce OÜ · Tallinn, Eesti