CORS, XSS és CSRF példákkal 10 percben
Ez a cikk legyen a belépési pont a meglévő webes biztonsági szabványokhoz, a leggyakoribb webes támadásokhoz és a megelőzésükhöz szükséges módszerekhez. A végén azt is megtudhatod, hogyan és miért volt Samy mindenki hőse (kivéve Rupert Murdochét, gondolom)
A Cross-origin resource sharing, azaz a CORS az IE10+, a Chrome 4+, a Firefox 3.5+, illetve az Opera Mini kivételével szinte minden 2012 után megjelent böngészőverzió biztonsági funkciója.
Ha a CORS olyan szerveren van beállítva, amely elérhető a website.com
tartományban, akkor a tartományból származó erőforrásokat, amelyeket AJAX-on keresztül kérnek, ugyanabból a tartományból kiszolgált eszközökről kell kezdeményezni.
Más szóval, ha engedélyezzük a CORS-t a domain-b.com
tartományon, és úgy konfiguráljuk, hogy csak GET
kéréseket engedélyezzen a domain-b.com
tartományból, akkor ha a https://domain-b.com/images/example.png
alatt elérhető képet akarjuk használni a vászonban a weboldalunkon, amely a domain-a.com
tartományban található, akkor ez a kép nem fog betöltődni a legtöbb látogató számára.
A CORS által védett erőforrásai továbbra is elérhetőek lesznek, ha olyan eszköz vagy böngésző kéri őket, amely nem tartja tiszteletben a CORS policy
-t.
CORS konfiguráció
A CORS alapértelmezés szerint le van tiltva, ami azt jelenti, hogy nincs megfelelő szerver kezelő, amely konfigurálja a CORS-t, ami azt jelenti, hogy nem tud hozzáférni a különböző eredetű erőforrásokhoz az XHR-ben. Alapvetően, ha nem tesz semmit, vagy kifejezetten csak bizonyos tartományok számára engedélyezi a CORS-t, akkor minden AJAX kérés, amely megpróbálja elérni az erőforrásait, elutasításra kerül, mivel a webböngészők tiszteletben tartják a CORS policy
.
Ez az oka annak, hogy CORS problémával találkozik, amikor VueJS és NodeJS használatával elkezdi az SPA fejlesztését. A VueJS alkalmazásod a http://localhost:8080
címen van hosztolva, és amikor megpróbálod elérni a NodeJS szerveralkalmazást a http://localhost:8000
címen, akkor “No Access-Control-Allow-Origin header is present
“-t kapsz, mert ezek két különböző ORIGINS
(PROTOCOL
, HOST
és PORT
kombinációja).
A VueJS fejlesztői üzemmódban a CORS probléma megoldása a devServer proxy beállítása a vue.config.js
fájlban a következőképpen:
module.exports = { ... devServer: { proxy: 'http://localhost:8000', }, ...}
A CORS beállításához a termelésben a OPTIONS
kéréshez megfelelő listenert kell hozzáadni. Ennek a figyelőnek 200
választ kell küldenie no body
-val, de Headers
-val, amely meghatározza a kívánt CORS házirendet:
Access-Control-Allow-Origin: https://domain-b.comAccess-Control-Allow-Methods: GET
A CORS beállításával kapcsolatos további információkért nézze meg a https://enable-cors.org/index.html, és ha mélyebbre szeretne merülni a CORS policy
vizsgálat https://livebook.manning.com/book/cors-in-action/part-1/
XSS
Az XSS a Cross Site Scripting rövidítése, és egy injekciós típusú támadás. Az OWASP által 2017-ben azonosított 10 legnagyobb sebezhetőség közül a 7. helyen szerepel. A Cross site scripting az a módszer, amikor a támadó rosszindulatú szkriptet injektál a megbízható weboldalba.(szakasz frissítve, köszönet Sándornak) Az ilyen támadásoknak 3 típusa van.
- Stored XSS – Védtelen és nem szanitizált felhasználói bemenetekből származó sebezhetőség, amelyek közvetlenül az adatbázisban tárolódnak és megjelennek más felhasználók számára
- Reflected XSS – Védtelen és nem szanitizált URL-ekből származó sebezhetőség, amelyek közvetlenül a weboldalakon kerülnek felhasználásra
- DOM alapú XSS – Hasonló a reflektált XSS-hez, nem védett és nem szanitizált értékek a weboldalakon közvetlenül használt URL-ekből, azzal a különbséggel, hogy a DOM alapú XSS nem is megy a szerveroldalra
Támadás
1. Tárolt XSS
Itt egy példa a támadásra. A támadó bejön a weboldaladra, és megtalálja a nem védett bemeneti mezőt, például a megjegyzés mezőt vagy a felhasználónév mezőt, és a várt érték helyett rosszindulatú szkriptet ír be. Ezt követően, amikor ezt az értéket más felhasználóknak kell megjeleníteni, rosszindulatú kódot hajt végre. A rosszindulatú szkript megpróbálhat hozzáférni a fiókjához más webhelyeken, részt vehet DDoS-támadásban vagy hasonlóban. Vizuális ábrázolás(forrás geeksforgeeks.org):
2. Reflektált XSS
A reflektált XSS olyan támadás, amely akkor történik, amikor a támadó felfedezi az ilyen sebezhetőséggel rendelkező oldalt, például:
várható URL: https://mywebpage.com/search?q=javascript
rosszindulatú URL: https://mywebpage.com/search?q=<script>alert('fortunately, this will not work!')</script>
<body>...<div> showing results for keyword <script> document.write(window.location.href.substr(window.location.href.indexOf('q=') + 2))</script></div>......JavaScript results......</body>
A felfedezés után a támadó arra csábítja a felhasználót, hogy kattintson az ilyen rosszindulatú URL-re, és voila. A felhasználó érzékeny adatait kihasználják.
A támadás életciklusa a geekforgeeks.com által megadott példán látható:
3. DOM alapú XSS
Ez a fajta támadás ugyanaz, mint a tükrözött, azzal a különbséggel, hogy a rosszindulatú URL
rész egyáltalán nem kerül továbbításra a szervernek. A fenti példa esetében:
várható URL: https://mywebpage.com/search?q=javascript
rosszindulatú URL (reflektált XSS): https://mywebpage.com/search?q=<script>alert('fortunately, this will not work!')</script>
rosszindulatú URL(DOM alapú XSS): https://mywebpage.com/search#q=<script>alert('fortunately, this will not work!')</script>
A különbség a ?
helyett a #
karakter használatában van. A böngészők nem küldik el az URL # utáni részét a szervernek, így azt közvetlenül az Ön kliens kódjának továbbítják.
Védelem
Minden értéket, amelyet a felhasználó megadhat és az alkalmazásban használ(akár a szerver oldalon, akár a kliens oldalon), nem megbízható adatnak kell kezelni, ezért használat előtt fel kell dolgozni! Biztonsági ellenőrzést kell végezned a szerver alkalmazásodban és a kliens alkalmazásodban is!
Mint a dokumentációban látható a VueJS önmagában escapeli a sztringet, mielőtt megkapja az értéket a változóból. Az Angular újabb verziói is implicit módon menekítik a stringeket, így ha Vanilla JS-t, JQuery-t vagy hasonlót használsz, akkor manuálisan kell implementálnod a string escape-et.
A nem megbízható adatok feldolgozásának három leggyakoribb megközelítése az alábbiakban van felsorolva, és az ideális módszer a mező aktuális típusától függ, amit fel kell dolgoznod.
1. Sztringérvényesítés
A hitelesítés az a módszer, ahol a felhasználó szabálykészletet határoz meg, és megköveteli, hogy a nem megbízható adatok megfeleljenek ezeknek a szabályoknak, mielőtt továbblépne. Ez a módszer jó számértékek, felhasználónév, e-mail, jelszó és hasonló, konkrét szintaxis szabályokkal rendelkező mezők esetében.
Nézze meg, hogy vannak-e már meglévő könyvtárak a keretrendszeréhez, mielőtt saját validátorok írását fontolgatná.
2. Validálás. String escape
Az escape módszer hasznos olyan esetekben, amikor lehetővé kell tennie a felhasználó számára az írásjelek használatát. Ez a módszer végigmegy a karakterláncon, és megkeresi a speciális karaktereket, például <
>
, és a megfelelő HTML karakteres entitásnévvel helyettesíti őket. Itt van egy alapfunkció, amit használhat:
function escapeText(text) { return text.replace(/&/g, '&') .replace(/</g, '<') .replace(/>/g, '>') .replace(/"/g, '"')}
Még egyszer, ellenőrizze a meglévő könyvtárakat, mielőtt megírja a sajátját.
3. Sztring szanálás
A sztring szanálását akkor használjuk, ha a felhasználónak megengedjük, hogy bizonyos HTML címkéket írjon be a kommentjeibe, cikkeibe vagy hasonlókba. A szanitizáló módszer végigmegy a szövegen, és megkeresi a megadott HTML címkéket, majd eltávolítja őket. Az egyik legnépszerűbb könyvtár, amely ezt a megközelítést használja, a Google Closure.
Ez a módszer erőforrásigényes és károsnak tekinthető, ezért végezzen több kutatást, mielőtt ezt választja.
A webböngészők (nincs elérhető forrás, melyik verzió óta, az IE 2014-ben javította ezt a problémát.) automatikusan kikerüli az URL-eket, mielőtt elküldi őket a szerveroldalra, és elérhetővé teszi őket a window.location
objektumban is, így a 2. és 3. típusú támadás itt csak azért van, hogy tisztában legyen velük, és hogy egyértelmű legyen, hogy az URL paramétereket is nem megbízható adatként kell kezelni.
Az XSS-ről és az alkalmazás megfelelő védelméről, ha sok nem megbízható adatot forgatsz, részletesebb információt az OWASP cheatsheet on XSS prevention című cikkében találsz.
CSRF
A Cross site request forgery vagy CSRF egy olyan típusú támadás, amely akkor következik be, amikor egy rosszindulatú weboldal, e-mail, blog, azonnali üzenet vagy program arra készteti a felhasználó webböngészőjét, hogy egy nem kívánt műveletet hajtson végre egy másik megbízható webhelyen, ahol a felhasználó hitelesített. Ez a sebezhetőség akkor lehetséges, ha a böngésző minden egyes kéréssel együtt automatikusan elküldi az engedélyezési erőforrást, például munkamenet-sütit, IP-címet vagy hasonlót.
ATTACK
Tegyük fel, hogy a felhasználó bejelentkezett a nem védett tőzsdei webes alkalmazásába, és a hitelesítéshez vagy munkamenet-sütit vagy JWT-sütit használ. A támadó is használja az Ön szolgáltatását, és képes ellenőrizni, hogyan működik az API-ja. A támadó ráveszi a felhasználót, hogy olyan szkriptet hajtson végre (az e-mailben található SPAM linkre vagy hasonlóra kattintva), amely kérést küld az Ön API-jának https://www.stockexchange.com/users/withdraw?how_much=all&address=MY_ADDRESS
(szörnyű API-dizájn, ne kérdezze). Mivel a kérést a böngészőből hajtják végre, amely minden kéréssel együtt elküldi a hitelesítési payloadot, a stockexchange webszerver sikeresen hitelesíti a felhasználót és végrehajtja a tranzakciót, a becsapott felhasználó pedig elveszíti az összes egyenlegét anélkül, hogy tudna róla, mert minden a háttérben történt. Vizuális ábrázolás(forrás miro.medium.com)
Védelem
Szerencsére vannak könnyen megvalósítható minták, amelyek megakadályozzák ezt a webes támadást. Az egyik leggyakoribb minta a CSRF token
használata. Alapvetően az eljárás a következő:
- Generáljunk egyedi tokent minden egyes felhasználói kéréshez, az úgynevezett
CSRF token
-t. - Tároljuk biztonságosan a szerveren, és küldjük vissza a felhasználónak a válasz payloadjaként.
- Tároljuk a
CSRF token
-t a kliens oldalon. - Amikor a felhasználó megpróbál bármilyen állapotváltoztató* kérést végrehajtani, küldje el a
CSRF token
-t a kéréssel együtt payloadként. - A kérés szerveroldali végrehajtása előtt ellenőrizze, hogy a
CSRF token
jelen van-e és érvényes-e.
Ez a legegyszerűbb módja a CSRF támadás megelőzésének minden felhasználó számára.
Ha csak modern böngészőket használó látogatókkal van dolga, akkor támaszkodhat a munkamenet süti SameSite
attribútumára.(Köszönöm Gergely)
Mivel a szerver válaszai az XHR válaszban feldolgozhatók, akkor nincs védelem a CSRF támadás ellen, ha a webalkalmazása XSS sebezhető!
Ha mélyebbre akarsz merülni, nézd meg az OWASP cheatsheet on CSRF.
BONUS
Rövid dokumentumfilm Samy-ről, a féreg szerzőjéről, aki 2005-ben a MySpace-t lekapcsolta az XSS sebezhetőséggel visszaélve, a MySpace CSRF védelmét kihasználva.
https://youtu.be/DtnuaHl378M
Bővebb információ Samy féregéről
https://samy.pl/myspace/tech.html