SQL injekcija yra paprastas atakos vektorius, kuris vis dar labai paplitęs ir šiandien. To priežastis yra ne kas kita, kaip ne pleistras kvailas. Kodėl taip sakote, paimkime JAVA kaip pavyzdį:
Tarkime, kad duomenų bazėje yra tokia lentelė:
Tada naudokite JDBC veiksmų lentelę:
Aukščiau pateiktą kodą dažnai naudoja kai kurie kūrėjai. Įsivaizduokite situaciją, kai gaunamas userId parametras yra "3; nuleisti lentelės vartotoją; Įvykdytas SQL sakinys yra toks:
Sukompiliavus ir paleidus duomenų bazę, vartotojo lentelė ištrinama. Voila, paprasta SQL injekcijos ataka įsigalioja! Taip yra todėl, kad aukščiau pateiktas kodas neatitinka programavimo specifikacijų.
Kai programuojame pagal specifikaciją, SQL injekcijos nėra. Taip yra irPirmasis būdas išvengti SQL injekcijos: iš anksto sukompiliuoti teiginiai, kodas yra toks:
Kodėl aukščiau pateiktame kode nėra SQL injekcijos? Kadangi naudojamas iš anksto sukompiliuotas sakinys, iš anksto sukompiliuotas sakinys nustatys "pasirinkti vardą iš vartotojo, kur id= ?" Pareiškimas yra sudarytas iš anksto, kad jį vykdant reikia pakeisti tik gaunamais parametrais? Vietos rezervavimo ženklai yra gerai. Pirmuoju neatitinkančiu atveju programa parašys SQL sakinį ir sukompiliuos jį su vartotojo perduotu turiniu, o tai yra būtent problema.
Be iš anksto sukompiliuotų teiginių naudojimo, yra ir antras variantasBūdai, kaip išvengti SQL injekcijos atakų: saugomos procedūros。 Saugoma procedūra yra SQL sakinių rinkinys, atliekantis tam tikrą funkciją, sukompiliuotas ir saugomas duomenų bazėje, ir vartotojas gali jį vykdyti iškviesdamas saugomą procedūrą ir pateikdamas parametrą (jei saugoma procedūra turi parametrus), o tai taip pat gali išvengti SQL injekcijos atakų
Atitinkama aukščiau pateiktame kode saugoma procedūra yra tokia:
Žinoma, vartotojai taip pat gali tikrinti simbolius priekinėje dalyje, o tai taip pat yra būdas išvengti SQL injekcijos: pavyzdžiui, aukščiau esančiame parametre userId vartotojas patikrins, ar nėra kabliataškio, ir bus rodoma klaida. Tačiau pagrindinė priežastis yra ta, kad SQL injekcijos atakos egzistuoja, nes programos nenaudoja mažiausių privilegijų pasiekdamos duomenų bazes. Atrodo, kad visi naudojo root paskyrą, kad pasiektų duomenų bazę.
Taigi, kaip MyBatis išvengti SQL injekcijos atakų? Arba paimkite aukščiau pateiktą lentelę kaip pavyzdį: Tarkime, susiejimo failas yra:
Atitinkami "Java" failai yra šie:
Galite pamatyti, kad įvesties parametras yra eilutės tipo userId, kai perduodame userId="34; nuleisti lentelės vartotoją; Po to spausdintame pareiškime rašoma:
Nepriklausomai nuo įvesto vartotojo ID, jo sql teiginys yra toks. Taip yra dėl to, kad mybatis naudoja iš anksto sukompiliuotus teiginius pagrindiniame įgyvendinime. Kai duomenų bazė vykdo šį sakinį, ji tiesiogiai naudoja iš anksto sukompiliuotą sakinį, o tada pakeičia vietos rezervavimo ženklą praeinančiu userId? Tiesiog eik bėk. Pirmiausia pakeisti vietos rezervavimo ženklus? Kompiliavimo procesas atliekamas, todėl SQL injekcijai nėra vietos išgyventi.
Taigi, kaip MyBatis atlieka SQL išankstinį kompiliavimą? Tiesą sakant, PreparedStatement klasė naudojama sistemos apačioje. Paruošta Staement klasė ne tik išvengia SQL injekcijos, bet ir taupo (N-1) kompiliavimo laiką, kai tas pats SQL sakinys vykdomas N kartų, taip padidinant efektyvumą.
Jei pakeisite aukščiau pateiktą teiginį į:
Kai įvedame userId="34; nuleisti lentelės vartotoją; Po to spausdintame pareiškime rašoma:
Šiuo metu mybatis nenaudoja iš anksto sukompiliuotų sakinių, pirmiausia susiuva eilutes, o tada atlieka kompiliavimą, būtent taip veikia SQL injekcija.
Todėl rašydami mybatis žemėlapių teiginius, pabandykite naudoti formatą "#{xxx}". Jei turite naudoti tokius parametrus kaip "${xxx}", turite juos rankiniu būdu filtruoti, kad išvengtumėte SQL injekcijos atakų.
|