Az SQL injekció egy egyszerű támadási vektor, amely ma is nagyon gyakori. Ennek oka nem más, mint hogy nincs javítás a hülyeségnek. Miért mondod ezt, vegyük példaként a JAVA-t, hogy szemléltessen:
Tegyük fel, hogy létezik egy ilyen táblázat az adatbázisban:
Ezután használd a JDBC akciótáblát:
A fenti kódot gyakran használják néhány fejlesztő. Képzelj el egy olyan helyzetet, ahol a bejövő userId paraméter "3; Drop table felhasználó; Az SQL utasítás a következő:
Az adatbázis fordítása és végrehajtása után a felhasználói tábla törlődik. Voilá, egy egyszerű SQL injekciós támadás lép életbe! Ennek oka, hogy a fenti kód nem felel meg a programozási specifikációknak.
Ha a specifikáció szerint programozunk, az SQL injekció nem létezik. Ez is így vanAz SQL injekciójának elkerülésének első módja: előre fordított utasítások, a kód a következő:
Miért nincs SQL injekció a fenti kódban? Mivel az előre fordított utasítást használják, az előre fordított utasítás beállítja: "select name from user where id= ?" Az utasítást előre fordították, így csak a bejövő paraméterekkel kell helyettesíteni, amikor végrehajtják? A helykitöltők rendben vannak. Az első, nem kompatibilis esetben a program SQL utasítást ír, majd azt a felhasználó által átadott tartalommal fordítja le, ami pontosan a probléma.
Az előre fordított állítások mellett van egy második lehetőség isSQL injekciós támadások elkerülésének módjai: Tárolt eljárások。 A tárolt eljárás egy SQL utasításokból álló halmaz, amelyek egy adott funkciót hajtanak végre, lefordítva és adatbázisban tárolva, és a felhasználó végrehajthatja azt egy tárolt eljárás meghívásával, valamint paramétert megadva (ha a tárolt eljárásnak vannak paraméterei), ami szintén elkerülheti az SQL injekciós támadásokat
A fenti kódban a megfelelő tárolt eljárás a következő:
Természetesen a felhasználók karakterellenőrzést is végezhetnek a frontenden, ami szintén egy módja az SQL befecskendezés elkerülésének: például a fent említett userId paraméternél a felhasználó szempillült néz, és hiba jelenik meg. Azonban a legalapvetőbb ok az, hogy SQL injekciós támadások azért léteznek, mert az alkalmazások nem használnak a legkisebb jogosultságot az adatbázisokhoz való hozzáféréskor. Úgy tűnik, mindenki a root fiókot használja az adatbázishoz való hozzáféréshez.
Hogyan kerüli el a MyBatis az SQL injekciós támadásokat? Vagy vegyük példaként a fenti táblázathasználót: Tegyük fel, hogy a mapper fájl a következő:
A megfelelő java fájlok a következők:
Láthatod, hogy a bemeneti paraméter userId típusú, a String típus, amikor passzolunk userId="34; Drop table felhasználó; Ezután a nyomtatott nyilatkozat így szól:
Függetlenül attól, hogy milyen felhasználóazonosítót adtál be, a sql nyilatkozata ilyen. Ennek oka, hogy a mybatis előre fordított utasításokat használ az alapimplementációban. Amikor az adatbázis végrehajtja ezt az utasítást, közvetlenül az előre fordított utasítást használja, majd a helykitöltőt a passzoló userId-re cseréli? Csak fuss. Először cserélni a helykitöltőket? A fordítási folyamat zajlik, így nincs helye az SQL injekciónak túlélésére.
Hogyan végezi a MyBatis SQL előfordítást? Valójában a PreparedStatement osztályt használják a keretrendszer alján. Az PreparedStaement osztály nemcsak az SQL befecskendezését kerüli el, hanem (N-1) fordítási időt is megtakarít, amikor ugyanazt az SQL utasítást N alkalommal hajtják végre, így növelve a hatékonyságot.
Ha a fenti állítást így változtatod:
Amikor belépünk a userId="34; Drop table felhasználó; Ezután a nyomtatott nyilatkozat így szól:
Jelenleg a mybatis nem használ előre lefordított utasításokat, először a húrokat köti össze, majd majd a fordítást végzi, ami pontosan így működik az SQL injekció.
Ezért mybatis leképezési állítások írásakor próbáld meg a "#{xxx}" formátumot használni. Ha olyan paramétereket kell használnod, mint a "${xxx}", akkor manuálisan kell szűrned őket, hogy elkerüld az SQL injekciós támadásokat.
|