Kaip veikia „SQL“ injekcija iš „XBCD Bobby Tables“ komiksų?

Tiesiog žiūrėkite:

2019

1019
02 дек. nustatė Blankman 02 Dec 2008-12-02 00:50 '08 ne 0:50 2008-12-02 00:50
@ 12 atsakymų

Išmeta studentų lentelę.

Mokyklos mokymo programos šaltinis, atrodo, atrodo panašus

 q = "INSERT INTO Students VALUES ('" + FNMName.Text + "', '" + LName.Text + "')"; 

Tai naivus būdas pridėti teksto įvestį į užklausą ir yra labai blogas, kaip matysite.

Po reikšmių iš pirmojo vardo, teksto laukelis yra vidurinis pavadinimas FNMName.Text (kuris yra lygus Robert'); DROP TABLE STUDENTS; -- Robert'); DROP TABLE STUDENTS; -- Robert'); DROP TABLE STUDENTS; -- ) ir pavardės LName.Text teksto laukas (leiskite jį pavadinti „ Derper ) derinamas su likusia užklausos dalimi, rezultatas dabar susideda iš dviejų užklausų, atskirtų terminatoriumi (kabliataškiu). Antrasis prašymas buvo įrašytas į pirmąjį. Kai kodas atlieka šią užklausą duomenų bazėje, jis atrodys taip:

 INSERT INTO Students VALUES ('Robert'); DROP TABLE Students; --', 'Derper') 

kuris paprastu anglų kalba sudaro maždaug du prašymus:

Pridėti naują įrašą į lentelę „Studentai“ su pavadinimu „Robert“

ir

Ištrinti lentelę „Studentai“

Visas antrojo užklausos praeitis pažymėtas kaip komentaras : --', 'Derper')

' studento vardu nėra komentaras, tai yra uždarymo linijos ribotuvas . Kadangi studento vardas yra eilutė, jis turi sintaksiškai užbaigti hipotetinį užklausą. Įpurškimo atakos veikia tik tada, kai SQL užklausa įveda rezultatus galiojančiame SQL.

Redaguotas dar kartą pagal dan04 įžvalgus komentarą

1046
02 дек. Atsakymas pateiktas Will 02 Dec. 2008-12-02 00:50 '08 ne 0:50 2008-12-02 00:50

Sakykime, kad pavadinimas buvo naudojamas kintamajame $Name . Tada paleisite šį užklausą:

 INSERT INTO Students VALUES ( '$Name' ) 

Kodas klaidingai nurodo viską, ką naudotojas nustatė kaip kintamąjį. Jūs norėjote, kad SQL būtų:

INSERT INTO studentams VERTĖS („ Robert Tables “)

Tačiau protingas vartotojas gali suteikti viską, ką nori:

INSERT INTO studentams VERTĖS („ Robert“); DROP LENTELĖ Studentai; - ')

Ką gausite:

 INSERT INTO Students VALUES ( 'Robert' ); DROP TABLE STUDENTS; --' ) 

" -- komentarai dėl likusios linijos dalies.

565
02 дек. atsakymas yra duotas 02 dec. 2008-12-02 00:55 '08 at 0:55 2008-12-02 00:55

Kaip jau minėjo visi kiti, '); baigia pirminį pareiškimą, o po to seka antrasis teiginys. Dauguma sistemų, įskaitant tokias kalbas kaip PHP, yra numatytos pagal nutylėjimą nustatytų saugumo numatytųjų reikšmių, kurios neleidžia naudoti kelių ataskaitų vienoje SQL eilutėje. Pvz., PHP galite paleisti kelis pareiškimus tik vienoje SQL eilutėje, naudodami funkciją mysqli_multi_query .

Tačiau, naudodami SQL injekciją, galite manipuliuoti esama SQL informacija, nepridėję antrojo pareiškimo. Tarkime, jūs turite prisijungimo sistemą, kuri patikrina jūsų vartotojo vardą ir slaptažodį šiuo paprastu pasirinkimu:

 $query="SELECT * FROM users WHERE username='" . $_REQUEST['user'] . "' and (password='".$_REQUEST['pass']."')"; $result=mysql_query($query); 

Jei pateikiate peter kaip naudotojo vardą ir secret kaip slaptažodį, gauta SQL eilutė atrodys taip:

 SELECT * FROM users WHERE username='peter' and (password='secret') 

Viskas yra puiki. Įsivaizduokite, kad pateikiate šią eilutę kaip slaptažodį:

 ' OR '1'='1 

Tada gauta SQL eilutė bus tokia:

 SELECT * FROM users WHERE username='peter' and (password='' OR '1'='1') 

Tai leis jums prisijungti prie bet kurios paskyros nežinodami slaptažodžio. Taigi, jums nereikia naudoti dviejų pareiškimų, kad galėtumėte naudoti SQL injekciją, nors galite padaryti daugiau destruktyvių dalykų, jei galite pateikti kelis pareiškimus.

150
14 сент. atsakymą pateikė Johannes Fahrenkrug 14 Sep. 2011-09-14 13:12 '11, 13:12 pm 2011-09-14 13:12

Ne, ' nėra komentaras SQL, bet ribotuvas.

Mama pasiūlė, kad duomenų bazės programuotojas atliktų užklausą, panašią į:

 INSERT INTO 'students' ('first_name', 'last_name') VALUES ('$firstName', '$lastName'); 

(pvz.) pridėti naują studentą, kur $xxx kintamojo turinys buvo paimtas tiesiai iš HTML formos, nekontroliuojant formato arba neišvengiant specialių simbolių.

Taigi, jei $firstName yra Robert'); DROP TABLE students; -- Robert'); DROP TABLE students; -- Robert'); DROP TABLE students; -- , duomenų bazės programa vykdys šią užklausą tiesiogiai duomenų bazėje:

 INSERT INTO 'students' ('first_name', 'last_name') VALUES ('Robert'); DROP TABLE students; --', 'XKCD'); 

t. ji sulaužys ankstyvą įterpimo instrukciją, atliks bet kokį kenkėjiško kodo, kurį nori krekingo įrenginys, ir tada pakomentuokite bet kokį galimą kodo likutį.

Mmm, aš per lėtas, aš jau matau 8 atsakymus prieš mano oranžinę grupę ... :-) Atrodo populiari tema.

69
02 дек. Atsakymą pateikė PhiLho 02 gruodis. 2008-12-02 01:01 '08 ne 1:01 2008-12-02 01:01

Tl; DR

 mokykla => CREATE TABLE studentai (pavadinimas TEXT PRIMARY KEY); PRANEŠIMAS: CREATE TABLE / PRIMARY KEY bus sukurtas netiesioginis indeksas „students_pkey“ lentelės „studentams“ CREATE TABLE mokykla => INSERT INTO studentams VERTYS („Jonas“); ĮRAŠYTI 0 1

Tarkime, kad taikomoji programa naudoja šiuos SQL duomenis į lentelę:

 - Įvestis: Nancy mokykla => INSERT INTO studentams VALUES („Nancy“); ĮRAŠYTI 0 1

Kai prašome lentelės, mes gauname:

 - Įvestis: Robert ');  DROP LENTELĖS studentai;  - mokykla => INSERT INTO studentams VERTĖS („Robertas“);  DROP LENTELĖS studentai;  - '); ĮRAŠYTI 0 1 DROP LENTELĖ

SQL injekcija - tai studento, baigiančio pareiškimą, pavadinimo ir atskiros DROP TABLE komandos rezultatas; du įtrūkimai įvesties pabaigoje skirti komentuoti bet kokį likusį kodą, kuris kitu atveju sukeltų klaidą. Paskutinė išvesties eilutė patvirtina, kad duomenų bazės serveris sumažėjo.

Svarbu pažymėti, kad INSERT operacijos metu programa nekontroliuoja jokių specialių simbolių įvesties ir todėl leidžia įvesti savavališką įvestį į SQL komandą. Tai reiškia, kad užpuolikas gali į lauką įterpti specialius simbolius, pvz., Kabutes, ir savavališką SQL kodą, paprastai skirtas vartotojo įvesties duomenims, norint priversti duomenų bazės sistemą ją vykdyti, o tada - SQL injekciją .

Rezultatas?

savavališko kodo vykdymo pažeidžiamumo duomenų bazės, esančios operacinėje sistemoje ar programoje, ekvivalentas.  Galimas sėkmingo SQL įpurškimo atakos poveikis negali būti nepakankamai įvertintas - priklausomai nuo duomenų bazės konfigūracijos ir taikomųjų programų konfigūracijos, užpuolikas gali naudoti duomenų praradimą (kaip ir šiuo atveju), gauti neteisėtą prieigą prie duomenų arba patį savavališką kodą. 

Kaip pažymėjo komiksas „XKCD“, vienas iš būdų apsaugoti nuo SQL injekcijos atakų yra dezinfekuoti duomenų bazės įrašus, pvz., Pabėgti specialius simbolius, kad jie negalėtų keisti pagrindinės SQL komandos ir todėl negali paleisti savavališko SQL kodo. Jei naudojate parametruotas užklausas, pvz., Naudojant „ SqlParameter “ ADO.NET sistemoje, įvestis bus automatiškai dezinfekuojama, siekiant apsaugoti nuo SQL injekcijos.

Tačiau dezinfekuojant įvesties duomenis taikomųjų programų lygmeniu, negalima sustabdyti sudėtingesnių SQL injekcijos metodų. Pavyzdžiui, yra būdų, kaip patekti į mysql_real_escape_string PHP mysql_real_escape_string . Dėl papildomos apsaugos daugelis duomenų bazių sistemų palaiko parengtus pareiškimus . Jei jie yra teisingai įgyvendinti backend, paruošti pareiškimai gali padaryti SQL injekciją neįmanomą apdorojant duomenų įvedimus kaip semantiškai atskirtus nuo likusios komandos.

35
26 сент. atsakymas pateikiamas bwDraco 26 sep . 2011-09-26 23:20 '11, 23:20, 2011-09-26 23:20

Pasakykite, kad naiviai parašėte studentų kūrimo metodą taip:

 void createStudent(String name) { database.execute("INSERT INTO students (name) VALUES ('" + name + "')"); } 

Ir kažkas įeina į Robert'); DROP TABLE STUDENTS; -- vardą Robert'); DROP TABLE STUDENTS; -- Robert'); DROP TABLE STUDENTS; --

Kas vyksta duomenų bazėje, ši užklausa:

 INSERT INTO students (name) VALUES ('Robert'); DROP TABLE STUDENTS --') 

Semikolis užbaigia įterpimo komandą ir pradeda kitą; - pastabas dėl likusios linijos dalies. „DROP TABLE“ komandos valdymas ...

Todėl privalomi parametrai yra geras dalykas.

27
02 дек. atsakymas duotas Danui Vintonui 02 d. 2008-12-02 00:56 '08 0:56 2008-12-02 00:56

Viena citata yra eilutės pradžia ir pabaiga. Semikolas yra nurodymo pabaiga. Todėl, jei jie pasirinko:

 Select * From Students Where (Name = '<NameGetsInsertedHere>') 

SQL taptų:

 Select * From Students Where (Name = 'Robert'); DROP TABLE STUDENTS; --') -- ^-------------------------------^ 

Kai kuriose sistemose pirmiausia select pradžią ir tada drop ! Šis pranešimas: DONT EMBED VERTĖS JŪSŲ SQL. Vietoj to naudokite parinktis!

24
02 дек. Atsakymas duotas CodeAndCats 02 Dec. 2008-12-02 01:03 '08 at 1:03 2008-12-02 01:03

'); užbaigia užklausą, ji nepradeda komentaro. Tada jis atsisako studentų stalo ir komentarų apie likusią užklausos dalį, kuri turėjo būti įvykdyta.

16
02 дек. Atsakymas pateiktas Jorn 02 Dec. 2008-12-02 00:53 '08 ne 0:53 2008-12-02 00:53

Šiuo atveju „nėra komentaro pobūdžio. Jis naudojamas eilutės raštams atskirti. Komiksinis menininkas prisiima mintį, kad atitinkama mokykla turi dinamišką SQL failą, kuris atrodo taip:

 $sql = "INSERT INTO `Students` (FirstName, LastName) VALUES ('" . $fname . "', '" . $lname . "')"; 

Taigi dabar, kai programuotojas tikisi, simbolis baigia eilutę. Kartu su; užbaigti pareiškimą, užpuolikas dabar gali pridėti viską, ką nori. Pabaigoje pateiktas komentaras yra įsitikinti, kad bet kuris likęs SQL dokumento originalas netrukdo serveriui pakenkti užklausai.

FWIW, aš taip pat manau, kad šis komiksas turi svarbią detalę neteisingai: jei manote, kad jūsų duomenų bazės įrašai bus dezinfekuojami, kaip rodo komiksas, vis dar darote tai neteisingai. Vietoj to, turėtumėte pagalvoti apie tai, kaip karantino savo duomenų bazės įrašus, ir teisingas būdas tai padaryti yra su parametruojamomis užklausomis.

15
02 дек. Atsakymas, kurį pateikė Joel Coehoorn Dec 02 2008-12-02 00:56 '08 0:56 2008-12-02 00:56

Tikriausiai duomenų bazės rašytojas

 sql = "SELECT * FROM STUDENTS WHERE (STUDENT_NAME = '" + student_name + "') AND other stuff"; execute(sql); 

Jei jutiklio pavadinimas yra nurodytas, jis atrenka pavadinimą „Robert“ ir ištrina lentelę. „-“ dalis pakeičia likusius šio komentaro prašymus.

15
02 дек. Atsakymas, kurį pateikė Paul Tomblin 02 Dec 2008-12-02 00:55 '08 at 0:55 2008-12-02 00:55

Simbolis ' SQL“ naudojamas styginių konstantoms. Tokiu atveju jis naudojamas eilutės konstantai užbaigti, o ne komentuoti.

14
02 дек. Atsakymas duotas Rockcoder 02 Dec. 2008-12-02 00:54 '08 at 0:54 2008-12-02 00:54

Štai kaip tai veikia: Tarkime, kad administratorius ieško studentų įrašų

 Robert'); DROP TABLE STUDENTS; -- 

Kadangi administratoriaus paskyroje yra didelių privilegijų, galite pašalinti lentelę iš šios paskyros.

Kodas, kuriuo galima gauti naudotojo vardą iš užklausos

Dabar užklausa bus kažkas panašaus (ieškant studentų stalo)

 String query="Select * from student where username='"+student_name+"'"; statement.executeQuery(query); //Rest of the code follows 

Gauta užklausa bus

 Select * from student where username='Robert'); DROP TABLE STUDENTS; -- 

Kadangi vartotojo įvestis nėra dezinfekuota, pirmiau pateikta užklausa apdorojama 2 dalimis

 Select * from student where username='Robert'); DROP TABLE STUDENTS; -- 

Dvigubos brūkšnelės (-) tiesiog komentuoja likusį užklausą.

Tai yra pavojinga, nes ji gali panaikinti slaptažodžio autentiškumą, jei toks yra.

Pirmoji atliks įprastą paiešką.

Antruoju atveju, jei paskyroje yra pakankamai privilegijų, ištrinsite lentelės studentą (paprastai mokyklos administratoriaus paskyra pradės tokį prašymą ir turės pirmiau nurodytas teises).

5
02 дек. atsakymas duotas vivek 02 Dec. 2013-12-02 13:17 '13, 13:17, 2013-12-02 13:17

Kiti klausimai apie žymas arba Užduoti klausimą