I to je sveobuhvatan vodič za skriptiranje na više lokacija.
Prvi dio: pregled
Šta je XSS?
Skriptiranje na više lokacija ( engleski Cross-site scripting) Je napad ubrizgavanjem koda koji omogućava napadaču da izvrši zlonamjerni JavaScript u pretraživaču drugog korisnika.
Napadač ne napada direktno svoju žrtvu. Umjesto toga, iskorištava ranjivost na web stranici koju žrtva posjećuje i ubacuje zlonamjerni JavaScript kod. Pregledač žrtve prikazuje zlonamjerni JavaScript kao legitimni dio web stranice, a sama web stranica djeluje kao direktni saučesnik napadača.
Ubacivanje zlonamjernog JavaScript koda
Jedini način da napadač pokrene zlonamjerni JavaScript u pretraživaču žrtve je da ga ubaci u jednu od stranica koje žrtva preuzima sa web stranice. To je moguće ako web stranica dozvoljava korisnicima da unose podatke na svoje stranice, a napadač može ubaciti red koji će biti otkriven kao dio koda u pretraživaču žrtve.
Primjer ispod prikazuje jednostavnu skriptu na strani servera koja se koristi za prikaz posljednjeg komentara na web stranici:
print " "
print "Posljednji komentar:"
print database.latestComment
print ""
Skripta pretpostavlja da se komentar sastoji samo od teksta. Međutim, pošto je direktan korisnički unos omogućen, napadač bi mogao ostaviti ovaj komentar: "". Svaki korisnik koji posjeti stranicu sada će dobiti sljedeći odgovor:
zadnji komentar:
Kada korisnikov pretraživač učita stranicu, on će izvršiti sve, uključujući JavaScript sadržan u oznakama ... Ovo ukazuje da je samo prisustvo napadača koji ubacuje skriptu problem, bez obzira na to koji se određeni kod skripte zapravo izvršava.
Drugi dio: XSS napad
Učesnici XSS napada
Prije nego što detaljno opišemo kako XSS napad funkcionira, moramo identificirati aktere uključene u XSS napad. Generalno, postoje tri učesnika u XSS napadu: Web stranica, žrtva, i kreker.
- Web stranica proizvodi HTML stranice za korisnike koji ih zatraže. U našim primjerima, nalazi se na http://website /.
- Baza podataka web stranica je baza podataka koja pohranjuje neke od podataka koje su korisnici unijeli na stranicama stranice.
- Žrtva Je običan korisnik web stranice koji od njega traži stranice koristeći svoj pretraživač.
- Napada Je napadač koji namjerava pokrenuti napad na žrtvu iskorištavanjem XSS ranjivosti na stranici.
- Cracker server Je web server pod kontrolom napadača s jedinom svrhom krađe povjerljivih informacija žrtve. U našim primjerima, nalazi se na http: // napadač /.
Primjer scenarija napada
Ova skripta će kreirati HTTP zahtjev na drugi URL koji će preusmjeriti pretraživač korisnika na server napadača. URL uključuje kolačiće žrtve kao parametar zahtjeva, kada HTTP zahtjev stigne na server napadača, napadač može izdvojiti ove kolačiće iz zahtjeva. Nakon što je napadač primio kolačiće, može ih koristiti za lažno predstavljanje žrtve i pokretanje naknadnog napada.
Od sada će se pozivati gornji HTML kod zlonamjerni niz ili zlonamjerna skripta... Važno je shvatiti da je niz sam po sebi zlonamjeran samo ako se na kraju obrađuje kao HTML u pretraživaču žrtve, što se može dogoditi samo ako postoji XSS ranjivost na web stranici.
Kako ovaj primjer napada funkcionira
Dijagram ispod prikazuje primjer napadača koji izvodi napad:
- Napadač koristi jedan od obrazaca web stranice da ubaci zlonamjerni niz u bazu podataka web stranice.
- Žrtva traži stranicu sa web stranice.
- Stranica uključuje zlonamjerni niz iz baze podataka u odgovoru i šalje ga žrtvi.
- Žrtvin pretraživač pokreće zlonamernu skriptu unutar odgovora, šaljući žrtvin kolačić na server napadača.
XSS tipovi
Cilj XSS napada je uvek da se izvrši zlonamerna JavaScript skripta u pretraživaču žrtve. Postoji nekoliko fundamentalno različitih načina za postizanje ovog cilja. XSS napadi se često kategoriziraju u tri tipa:
- Pohranjeni (trajni) XSS gdje zlonamjerni niz potiče iz baze podataka web stranice.
- Odraženi (nestabilan) XSS gdje se zlonamjerni niz stvara iz zahtjeva žrtve.
- DOMs XSS gdje se ranjivost javlja u kodu na strani klijenta, a ne u kodu na strani servera.
Prethodni primjer prikazuje pohranjeni XSS napad. Sada ćemo opisati još dva tipa XSS napada: Reflected XSS i DOM XSS.
Reflected XSS
U reflektiranom XSS napadu, zlonamjerni niz je dio zahtjeva žrtve upućene web stranici. Stranica prihvata i ubacuje ovaj zlonamjerni niz u odgovor koji šalje nazad korisniku. Dijagram ispod ilustruje ovaj scenario:
- Napadač prevari žrtvu da pošalje URL zahtjev web stranici.
- Stranica uključuje zlonamjerni niz iz URL-a zahtjeva u odgovoru žrtve.
- Žrtvin pretraživač izvršava zlonamernu skriptu sadržanu u odgovoru, šaljući žrtvin kolačić na server napadača.
Kako se uspješno odbraniti od XSS napada?
Odraženi XSS napad može izgledati bezopasno, jer zahtijeva od žrtve da pošalje zahtjev u njihovo ime koji sadrži zlonamjerni niz. Pošto niko neće dobrovoljno napasti sam sebe, čini se da ne postoji način da se napad izvede.
Kako se ispostavilo, postoje najmanje dva uobičajena načina da navedete žrtvu da pokrene reflektirani XSS napad na sebe:
- Ako je korisnik određena osoba, napadač može poslati zlonamjerni URL žrtvi (na primjer, putem e-pošte ili instant messengera) i prevariti ih da otvore vezu za posjetu web stranici.
- Ako je meta velika grupa korisnika, napadač bi mogao postaviti link na zlonamjerni URL (na primjer, na vlastitu web stranicu ili društvenu mrežu) i čekati da posjetitelji kliknu na vezu.
Obje ove metode su slične i obje mogu biti uspješnije korištenjem usluga skraćivanja URL-a za maskiranje zlonamjernog niza od korisnika koji bi ga mogli identificirati.
XSS u DOM-u
DOM XSS je varijanta i pohranjenog i reflektovanog XSS napada. U ovom XSS napadu, žrtvin pretraživač ne obrađuje zlonamjerni niz sve dok se stvarni JavaScript web stranice ne izvrši. Dijagram ispod ilustruje ovaj scenario za reflektovani XSS napad:
- Napadač kreira URL koji sadrži zlonamjerni niz i šalje ga žrtvi.
- Napadač prevari žrtvu da pošalje URL zahtjev web stranici.
- Stranica prihvaća zahtjev, ali ne uključuje zlonamjerni niz u odgovoru.
- Pregledač žrtve izvršava legitimnu skriptu sadržanu u odgovoru, zbog čega će zlonamjerna skripta biti umetnuta na stranicu.
- Pregledač žrtve izvršava zlonamjernu skriptu umetnutu na stranicu, šaljući žrtvin kolačić na server napadača.
Koja je razlika između XSS-a u DOM-u?
U prethodnim primjerima pohranjenih i reflektiranih XSS napada, server ubacuje zlonamjerni skript na stranicu, koji se zatim prosljeđuje kao odgovor žrtvi. Kada pretraživač žrtve primi odgovor, pretpostavlja da je zlonamjerna skripta dio legitimnog sadržaja stranice i automatski je izvršava u vrijeme učitavanja stranice, baš kao i svaki drugi skript.
U primjeru DOM XSS napada, zlonamjerna skripta nije umetnuta kao dio stranice; jedina skripta koja se automatski izvršava tokom učitavanja stranice je legitimni dio stranice. Problem je u tome što ova legitimna skripta direktno koristi korisnički unos za dodavanje HTML-a na stranicu. Pošto je zlonamjerni niz umetnut u stranicu pomoću innerHTML-a, on se analizira kao HTML, uzrokujući izvršavanje zlonamjerne skripte.
Ova razlika je mala, ali veoma važna:
- U tradicionalnom XSS-u, zlonamjerni JavaScript se izvršava pri učitavanju stranice kao dio HTML-a koji šalje server.
- U slučaju XSS-a u DOM-u, zlonamjerni JavaScript se izvršava nakon što se stranica učita, uzrokujući da ta legitimna JavaScript stranica pristupi korisničkom unosu (koji sadrži zlonamjerni niz) na nesiguran način.
Kako XSS radi u DOM-u?
U prethodnom primjeru JavaScript nije potreban; server može sam generirati sav HTML. Kada bi kod na strani servera bio bez ranjivosti, web stranica ne bi bila ranjiva na XSS ranjivost.
Međutim, kako web aplikacije postaju naprednije, sve više i više HTML stranica se generiše pomoću JavaScripta na strani klijenta, a ne na serveru. U svakom trenutku, sadržaj se mora promijeniti bez osvježavanja cijele stranice, to je moguće pomoću JavaScripta. Konkretno, ovo je slučaj kada se stranica osvježi nakon AJAX zahtjeva.
To znači da XSS ranjivosti mogu biti prisutne ne samo na serverskoj strani koda vaše web lokacije, već i na JavaScript strani klijenta vaše stranice. Stoga, čak i sa potpuno sigurnim kodom na strani servera, klijentski kod možda i dalje nije siguran da uključi korisnički unos kada se DOM ažurira nakon što se stranica učita. Ako se to dogodi, tada će kod na strani klijenta dozvoliti XSS napad bez greške koda na strani servera.
XSS zasnovan na DOM-u možda neće biti vidljiv serveru
Postoji poseban slučaj DOM XSS napada u kojem se zlonamjerni niz nikada ne šalje serveru web stranice: to se događa kada je zlonamjerni niz sadržan u komadu identifikatora URL-a (bilo što nakon znaka #). Pretraživači ne šalju ovaj dio URL-a serveru, tako da se web stranici ne može pristupiti putem serverskog koda. Kod klijenta, međutim, ima pristup njemu, pa je moguće izvršiti XSS napad nesigurnom obradom.
Ovaj slučaj nije ograničen na identifikator fragmenta. Postoji i drugi korisnički unos koji je nevidljiv serveru, kao što su nove HTML5 funkcije kao što su LocalStorage i IndexedDB.
treći dio:
Sprečavanje XSS
Tehnike prevencije XSS
Podsjećamo, XSS je napad ubrizgavanjem koda: korisnički unos se pogrešno tumači kao zlonamjerni kod. Sigurno rukovanje unosom je potrebno da bi se spriječila ova vrsta ubacivanja koda. Za web programera, postoje dva fundamentalno različita načina za obavljanje sigurne obrade unosa:
- Kodiranje je način koji omogućava korisniku da unese podatke samo kao podatke i ne dozvoljava da se pretraživač obrađuje kao kod.
- Validacija je način filtriranja unosa korisnika tako da ga pretraživač tumači kao kod bez zlonamjernih naredbi.
Iako su ovo fundamentalno različite metode prevencije XSS-a, one imaju nekoliko zajedničkih stvari koje je važno razumjeti kada koristite bilo koju od njih:
Kontekst Sigurno rukovanje unosom treba da se radi drugačije u zavisnosti od toga gde se na stranici koristi korisnički unos. ulazni/odlazni Sigurna obrada unosa može se izvršiti ili kada vaša stranica primi ulaz (ulazni promet) ili neposredno prije nego što stranica umetne korisnički unos u sadržaj stranice (izlazni). Klijent/server Sigurna obrada unosa može se obaviti ili na strani klijenta ili na strani servera, od kojih je svaki potreban pod različitim okolnostima.
Prije nego što detaljno objasnimo kako funkcionira kodiranje i validacija, opisujemo svaku od ovih tačaka.
Rukovanje korisničkim unosom u kontekstu
Postoji mnogo konteksta na web stranici u kojima se može primijeniti korisnički unos. Za svaki od njih moraju se poštovati posebna pravila kako korisnički unos ne bi mogao "pobjeći" iz konteksta i ne bi se mogao protumačiti kao zlonamjerni kod. Sljedeći su najčešći konteksti:
Koliko su važni konteksti?
U svim opisanim kontekstima, XSS ranjivost može nastati ako je korisnički unos umetnut prije prvog kodiranja ili validacije. Napadač bi mogao ubaciti zlonamjerni kod jednostavnim umetanjem zatvarača za ovaj kontekst nakon kojeg slijedi zlonamjerni kod.
Na primjer, ako u nekom trenutku web stranica uključuje korisnički unos direktno u HTML atribut, napadač bi mogao ubaciti zlonamjernu skriptu započinjući njihov unos znakom navoda, kao što je prikazano u nastavku:
Ovo se moglo spriječiti jednostavnim uklanjanjem svih navodnika u korisničkom unosu i bilo bi u redu, ali samo u ovom kontekstu. Ako je unos umetnut u drugi kontekst, završni graničnik će biti drugačiji i ubacivanje će biti moguće. Iz tog razloga, sigurno rukovanje unosom mora uvijek biti prilagođeno kontekstu u koji će korisnički unos biti umetnut.
Rukovanje dolaznim/odlaznim korisničkim unosom
Instinktivno se može činiti da se XSS može spriječiti kodiranjem ili provjeravanjem svih korisničkih unosa čim ga naša stranica primi. Na ovaj način, svi zlonamjerni nizovi će već biti neutralizirani kad god su uključeni na stranicu, a skripte za generiranje HTML-a neće morati brinuti o sigurnom rukovanju korisničkim unosom.
Problem je u tome što, kao što je ranije opisano, korisnički unos može biti umetnut u više konteksta na stranici. I ne postoji jednostavan način da se odredi kada korisnički unos dolazi u kontekst – kako će na kraju biti umetnut, a isti korisnički unos često treba da se ubaci u različite kontekste. Oslanjajući se na rukovanje dolaznim unosom kako bismo spriječili XSS, stvaramo vrlo krhko rješenje koje će biti sklono greškama. (Naslijeđeni PHP magični citati su primjer takvog rješenja.)
Umjesto toga, rukovanje izlaznim unosom bi trebalo da bude vaša glavna linija odbrane od XSS-a jer može uzeti u obzir specifičan kontekst unosa korisnika koji će biti umetnuti. U određenoj mjeri, ulazna validacija se može koristiti za dodavanje sekundarnog sloja zaštite, ali o tome kasnije.
Gdje je moguće bezbedno rukovati korisničkim unosom
U većini modernih web aplikacija, korisničkim unosom se rukuje i na kodu na strani servera i na kodu na strani klijenta. Kako bi se zaštitili od svih tipova XSS-a, sigurna obrada unosa mora biti obavljena u kodu na strani servera i kodu na strani klijenta.
- Kako bi se zaštitili od tradicionalnog XSS-a, sigurno rukovanje unosom mora se obaviti u kodu na strani servera. Ovo se radi pomoću nekog jezika koji server podržava.
- Da bi se zaštitili od XSS napada u DOM-u, gdje server nikada ne prima zlonamjerni niz (kao što je napad fragmenta ID-a opisan ranije), sigurno rukovanje unosom mora se obaviti u kodu na strani klijenta. Ovo se radi pomoću JavaScripta.
Sada kada smo objasnili zašto je kontekst bitan, zašto je važna razlika između ulazne i izlazne obrade unosa i zašto se sigurna obrada unosa mora obaviti i na strani klijenta i na strani servera, možemo nastaviti s objašnjavanjem kako dvije vrste sigurne obrade obrada ulaza (kodiranje i validacija) se zapravo obavlja.
Kodiranje
Kodiranje je izlaz iz situacije u kojoj je neophodno da pretraživač tumači korisnički unos samo kao podatak, a ne kao kod. Najpopularnija vrsta kodiranja u web razvoju je HTML maskiranje, koje pretvara znakove kao što su npr < i > v < i > respektivno.
Sljedeći pseudokod je primjer kako se korisnički unos (korisnički unos) može kodirati korištenjem HTML maskiranja, a zatim umetnuti na stranicu pomoću skripte na strani servera:
print " "
print "Posljednji komentar:"
print encodeHtml (userInput)
print ""
Ako korisnik unese sljedeći red, rezultirajući HTML će izgledati ovako:
zadnji komentar:
Budući da su svi znakovi sa posebnim značenjem maskirani, pretraživač neće analizirati nijedan dio korisničkog unosa poput HTML-a.
Kodiranje na strani klijenta i servera
Prilikom izvršavanja kodiranja na strani klijenta uvijek se koristi JavaScript, koji ima ugrađene funkcije koje kodiraju podatke za različite kontekste.
Kada radite kodiranje u kodu na strani servera, oslanjate se na funkcije dostupne u vašem jeziku ili okviru. Zbog velikog broja dostupnih jezika i okvira, ovaj vodič neće pokriti detalje kodiranja na bilo kojem određenom serverskom ili framework jeziku. Međutim, karakteristike JavaScript kodiranja na strani klijenta se također koriste prilikom pisanja koda na strani servera.
Kodiranje na strani klijenta
Kada kodirate korisnički unos na strani klijenta pomoću JavaScript-a, postoji nekoliko ugrađenih metoda i svojstava koja automatski kodiraju sve podatke u stil osjetljiv na kontekst:
Posljednji gore spomenuti kontekst (vrijednosti u JavaScriptu) nije uključen u ovu listu jer JavaScript ne pruža ugrađeni način za kodiranje podataka koji bi bili uključeni u JavaScript izvorni kod.
Ograničenja kodiranja
Čak i kada se kodira, moguće je koristiti zlonamjerne nizove u nekim kontekstima. Najbolji primjer ovoga je kada se korisnički unos koristi za pružanje URL-a, kao u primjeru ispod:
document.querySelector ("a"). href = userInput
Iako navedena vrijednost u svojstvu href elementa automatski ga kodira tako da postaje ništa drugo do vrijednost atributa, to samo po sebi ne sprječava napadača da ubaci URL koji počinje sa "javascript:". Kada se klikne na vezu, bez obzira na konstrukciju, ugrađeni JavaScript unutar URL-a će se izvršiti.
Kodiranje također nije efikasno rješenje kada želite da korisnici mogu koristiti neke od HTML kodova na stranici. Primjer bi bila stranica korisničkog profila na kojoj korisnik može koristiti prilagođeni HTML. Ako je ovaj obični HTML kodiran, stranica profila može se sastojati samo od običnog teksta.
U ovakvim situacijama kodiranje mora biti dopunjeno validacijom, o čemu ćemo se u nastavku upoznati.
Validacija
Validacija je čin filtriranja korisničkog unosa tako da se uklone svi zlonamjerni dijelovi bez potrebe za uklanjanjem cijelog koda u njemu. Jedna od najčešće korištenih vrsta provjere valjanosti u web razvoju omogućava vam korištenje nekih HTML elemenata (npr. i ), ali zabranjujući druge (npr.