Articles

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.
CORS

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', }, ...}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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 policyvizsgá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.

  1. 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
  2. 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
  3. 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):

XSS example

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>
Belépés teljes képernyős módba Kilépés teljes képernyős módból

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ó:

Reflected XSS example

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, '&amp;') .replace(/</g, '&lt;') .replace(/>/g, '&gt;') .replace(/"/g, '&quot;')}
Teljes képernyős módba lépés Teljes képernyős módból kilépés

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)
CSRF attack

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ő:

  1. Generáljunk egyedi tokent minden egyes felhasználói kéréshez, az úgynevezett CSRF token-t.
  2. Tároljuk biztonságosan a szerveren, és küldjük vissza a felhasználónak a válasz payloadjaként.
  3. Tároljuk a CSRF token-t a kliens oldalon.
  4. 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.
  5. 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