SQL injekcija je preprost napadalni vektor, ki je še danes zelo pogost. Razlog za to ni nič drugega kot da ni popravka za neumnost. Zakaj to praviš? Vzemimo JAVA kot primer, da ponazorimo:
Predpostavimo, da takšna tabela obstaja v podatkovni bazi:
Nato uporabite akcijsko tabelo JDBC:
Zgornjo kodo pogosto uporabljajo nekateri razvijalci. Predstavljajte si situacijo, kjer je vhodni parameter userId "3; uporabnik tabele za izpustitev; SQL stavek, ki se izvede, je naslednji:
Po prevajanju in izvajanju baze podatkov se uporabniška tabela izbriše. Voila, preprost SQL injekcijski napad začne delovati! To je zato, ker zgornja koda ne ustreza programskim specifikacijam.
Ko programiramo po specifikaciji, SQL injekcije ni. Tudi to veljaPrvi način, da se izognete SQL injekciji: predkompilirani stavki, koda je naslednja:
Zakaj SQL injection ne obstaja v zgornji kodi? Ker se uporablja predkompajlirani stavek, bo predkompilirani stavek nastavil "izberi ime uporabnika, kjer id= ?" Stavek je vnaprej preveden, tako da ga je treba ob izvedbi zamenjati le z vhodnimi parametri? Nadomestki so v redu. V prvem primeru neskladnosti program napiše SQL ukaz in ga nato prevede z vsebino, ki jo je uporabnik poslal, kar je pravzaprav problem.
Poleg uporabe predkompiliranih stavkov obstaja še druga možnostNačini za izogibanje SQL injekcijskim napadom: shranjene procedure。 Shranjena procedura je niz SQL stavkov, ki izvajajo določeno funkcijo, prevedene in shranjene v podatkovni bazi, uporabnik pa jo lahko izvede tako, da pokliče shranjeno proceduro in določi parameter (če ima shranjena procedura parametre), kar prav tako prepreči SQL injekcijske napade
Ustrezna shranjena procedura v zgornji kodi je naslednja:
Seveda lahko uporabniki izvajajo preverjanje znakov tudi na frontendu, kar je tudi način, da se izognejo SQL injekciji: na primer, za parameter userId zgoraj uporabnik preveri podpičje in prikaže se napaka. Vendar pa je najosnovnejši razlog ta, da SQL injection napadi obstajajo, ker aplikacije ne uporabljajo načela najmanjših privilegijev pri dostopu do baz podatkov. Zdi se, da vsi uporabljajo root račun za dostop do baze podatkov.
Kako torej MyBatis prepreči napade z SQL injekcijami? Ali pa vzemimo zgornjega uporabnika tabele kot primer: Recimo, da je mapper datoteka:
Ustrezne java datoteke so:
Lahko vidite, da je vhodni parameter userId tipa String, ko posredujemo userId="34; uporabnik tabele za izpustitev; Nato tiskano izjavo glasi:
Ne glede na vnesen uporabniški ID je njegova SQL izjava takšna. To je posledica dejstva, da mybatis v osnovni implementaciji uporablja vnaprej prevedene stavke. Ko baza podatkov izvede ta stavek, neposredno uporabi predkompiliran stavek in nato nadomesti začasni ukaz z uporabnikom userId? Samo pojdi teči. Najprej zamenjati nadomestne oznake? Postopek prevajanja je izveden, zato ni prostora za SQL injekcijo.
Kako torej MyBatis izvaja SQL predkompilacijo? Pravzaprav se razred PreparedStatement uporablja na dnu okvira. Razred PreparedStaement ne le da se izogne SQL injekciji, ampak tudi prihrani (N-1) časa prevajanja, ko se isti SQL stavek izvede N-krat, s čimer se izboljša učinkovitost.
Če zgornjo izjavo spremenite v:
Ko vnesemo userId="34; uporabnik tabele za izpustitev; Nato tiskano izjavo glasi:
Trenutno mybatis ne uporablja vnaprej prevedenih stavkov, najprej poveže nize in nato izvede prevajanje, kar je točno način, kako SQL injection deluje.
Zato pri pisanju stavkov za preslikavo mybatis poskusite uporabiti format "#{xxx}". Če morate uporabljati parametre, kot je "${xxx}", jih morate ročno filtrirati, da preprečite napade z SQL injekcijami.
|