Articles

CORS, XSS en CSRF met voorbeelden in 10 minuten

Dit artikel zou uw startpunt moeten zijn voor bestaande webbeveiligingsnormen, de meest voorkomende webaanvallen en de methoden om deze te voorkomen. Aan het eind kom je er ook achter hoe en waarom Samy ieders held was (behalve die van Rupert Murdoch, denk ik)

Cross-origin resource sharing, of CORS, is een beveiligingsfunctie van IE10+, Chrome 4+, Firefox 3.5+ of bijna elke browserversie die na 2012 is uitgebracht, behalve Opera Mini.

Wanneer CORS is geconfigureerd op een server die beschikbaar is op domein website.com, dan moeten bronnen uit dat domein die via AJAX worden opgevraagd, worden gestart vanaf assets die vanuit datzelfde domein worden geserveerd.
CORS

Met andere woorden, als we CORS inschakelen op domain-b.com en deze zo configureren dat alleen GET verzoeken van domein domain-b.com zijn toegestaan, dan zal, als u een afbeelding wilt gebruiken die beschikbaar is onder https://domain-b.com/images/example.png in canvas op uw website die wordt gehost op domain-a.com, die afbeelding niet worden geladen voor de meeste bezoekers.
Uw door CORS beschermde bronnen zullen nog steeds beschikbaar zijn wanneer ze worden opgevraagd door een tool of browser die CORS policy niet respecteert.

CORS configuratie

CORS zijn standaard uitgeschakeld, wat betekent dat er geen adequate server handler is die CORS configureert, wat betekent dat u geen toegang kunt krijgen tot bronnen van verschillende oorsprong in uw XHR. In principe, als je niets doet of specifiek CORS alleen voor specifieke domeinen inschakelt, dan zal elk AJAX-verzoek dat probeert toegang te krijgen tot je bronnen worden afgewezen omdat webbrowsers de CORS policy respecteren.
Dit is de reden waarom je CORS-probleem tegenkomt als je begint met het ontwikkelen van SPA met behulp van VueJS en NodeJS. Uw VueJS applicatie wordt gehost op http://localhost:8080 en wanneer u probeert toegang te krijgen tot NodeJS server applicatie op http://localhost:8000 krijgt u “No Access-Control-Allow-Origin header is present” omdat dat twee verschillende ORIGINS zijn (combinatie van PROTOCOL, HOST en PORT).

Coole oplossing voor CORS probleem in VueJS ontwikkelingsmodus is om devServer proxy in uw vue.config.js bestand als volgt in te stellen:

module.exports = { ... devServer: { proxy: 'http://localhost:8000', }, ...}
Enter fullscreen mode Exit fullscreen mode

Om CORS in productie op te zetten moet u de juiste listener voor OPTIONS verzoek toevoegen. Die luisteraar moet antwoord 200 sturen met no body maar met Headers dat uw gewenste CORS-beleid zal definiëren:

Access-Control-Allow-Origin: https://domain-b.comAccess-Control-Allow-Methods: GET
Enter fullscreen mode Exit fullscreen mode

Voor meer info over hoe CORS te configureren check https://enable-cors.org/index.html, en om dieper in CORS policy te duiken check https://livebook.manning.com/book/cors-in-action/part-1/

XSS

XSS staat voor Cross Site Scripting en het is een type injectie aanval. Het staat op de 7e plaats in de top 10 van kwetsbaarheden die in 2017 door OWASP zijn geïdentificeerd. Cross site scripting is de methode waarbij de aanvaller kwaadaardig script injecteert in vertrouwde website.(sectie bijgewerkt, bedankt Sandor) Er zijn 3 soorten van dergelijke aanvallen.

  1. Stored XSS – Kwetsbaarheid afkomstig van onbeschermde en niet gesanitiseerde gebruikersinputs die direct in database worden opgeslagen en aan andere gebruikers worden getoond
  2. Reflected XSS – Kwetsbaarheid afkomstig van onbeschermde en niet gesanitiseerde waarden uit URL’s die direct in webpagina’s worden gebruikt
  3. DOM based XSS – Vergelijkbaar met reflected XSS, onbeschermde en niet opgeschoonde waarden van URL’s die direct in webpagina’s worden gebruikt, met dit verschil dat DOM gebaseerde XSS niet eens naar de serverzijde gaat

Aanval

1. Opgeslagen XSS

Hier volgt een voorbeeld van een aanval. De aanvaller komt op uw website en vindt een onbeschermd invoerveld zoals een commentaarveld of een gebruikersnaamveld en voert een kwaadaardig script in in plaats van de verwachte waarde. Daarna, wanneer die waarde moet worden weergegeven aan andere gebruikers zal het kwaadaardige code uitvoeren. Kwaadaardig script kan proberen om toegang te krijgen tot uw account op andere websites, kan betrokken zijn bij DDoS-aanval of iets dergelijks. Visuele weergave (bron geeksforgeeks.org):

XSS example

2. Reflected XSS

Reflected XSS is een aanval die plaatsvindt wanneer een aanvaller een pagina met een dergelijke kwetsbaarheid ontdekt, bijvoorbeeld:

verwachtte URL: https://mywebpage.com/search?q=javascript
schadelijke 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>
Invoeren fullscreen-modusVerlaten fullscreen-modus

Na ontdekking lokt de aanvaller de gebruiker uit om op een dergelijke schadelijke URL te klikken en voila. Gevoelige gegevens van de gebruiker worden misbruikt.

De levenscyclus van de aanval wordt geïllustreerd in een voorbeeld van geekforgeeks.com:

Reflected XSS example

3. XSS op basis van DOM

Deze soort aanval is hetzelfde als de gereflecteerde aanval, maar met het verschil dat het schadelijke URL-gedeelte helemaal niet naar de server wordt gestuurd. Voor bovenstaand voorbeeld:

verwachtte URL: https://mywebpage.com/search?q=javascript
kwaadaardige URL (gereflecteerde XSS): https://mywebpage.com/search?q=<script>alert('fortunately, this will not work!')</script>
kwaadaardige URL(DOM-gebaseerde XSS): https://mywebpage.com/search#q=<script>alert('fortunately, this will not work!')</script>

Het verschil zit hem in het teken # dat wordt gebruikt in plaats van ?. De browsers sturen het deel van de URL na # niet naar de server, maar geven het direct door aan de client code.

Bescherming

Elke waarde die door de gebruiker kan worden ingevoerd en in uw app wordt gebruikt (hetzij aan de serverzijde hetzij aan de clientzijde) moet worden behandeld als onvertrouwde gegevens en moet daarom worden verwerkt voordat deze wordt gebruikt! Je moet de veiligheid te controleren in uw server app en uw client app, as well!
Zoals blijkt uit de documentatie VueJS door zichzelf string escapes voordat het verkrijgen van de waarde van de variabele. Nieuwere versies van Angular ook ontsnappen strings impliciet, dus als u Vanilla JS, JQuery of soortgelijke moet je implementeren string escape handmatig.

Er zijn drie meest voorkomende benaderingen van de verwerking van niet-vertrouwde gegevens zijn hieronder opgesomd en de ideale methode is afhankelijk van het werkelijke type van het veld dat u nodig hebt om te verwerken.

1. String validatie

Validatie is de methode waarbij de gebruiker definieert set van regels, en eisen onvertrouwde gegevens aan die regels te voldoen alvorens verder te gaan. Deze methode is goed voor nummer waarden, gebruikersnaam, e-mail, wachtwoord en soortgelijke velden met concrete set van syntax regels.

Check voor bestaande bibliotheken voor uw kader alvorens te overwegen om validators schrijven door uw eigen.

2. String escape

Escape methode is nuttig voor gevallen waarin u de gebruiker in staat moet stellen leestekens te gebruiken. Deze methode gaat door de string en zoekt naar speciale tekens, zoals < > en vervangt ze door de juiste HTML teken entiteit naam. Hier is een basisfunctie die u zou kunnen gebruiken:

function escapeText(text) { return text.replace(/&/g, '&amp;') .replace(/</g, '&lt;') .replace(/>/g, '&gt;') .replace(/"/g, '&quot;')}
Enter fullscreen mode Exit fullscreen mode

Overnieuw, controleer of er bestaande bibliotheken zijn voordat u uw eigen bibliotheken schrijft.

3. String sanitization

Sanitizing string wordt gebruikt wanneer de gebruiker sommige HTML-tags in zijn commentaar, artikelen of iets dergelijks mag invoeren. De sanitize methode gaat door de tekst en zoekt naar HTML tags die je opgeeft en verwijdert ze. Een van de meest populaire bibliotheken die deze aanpak gebruikt is Google Closure.
Deze methode is resource duur en wordt beschouwd als schadelijk, dus doe meer onderzoek voordat je het kiest.

Web browsers (geen beschikbare bronnen sinds welke versie, IE dit probleem opgelost in 2014.) automatisch ontsnappen URL’s voordat ze naar de server kant en waardoor ze beschikbaar in window.location object ook, dus 2e en 3e type aanval zijn hier alleen maar om bewust te zijn van hen en om duidelijk te maken dat URL params ook moeten worden behandeld als niet-vertrouwde gegevens.

Voor meer gedetailleerde info over XSS en hoe je je applicatie goed kunt beschermen als je veel onvertrouwde data draait, kijk op OWASP cheatsheet on XSS prevention.

CSRF

Cross site request forgery of CSRF is een type aanval die optreedt wanneer een kwaadaardige website, e-mail, blog, instant message of programma de webbrowser van een gebruiker ertoe brengt een ongewenste actie uit te voeren op een andere vertrouwde site waar de gebruiker is geauthenticeerd. Deze kwetsbaarheid is mogelijk wanneer de browser automatisch autorisatiebronnen, zoals sessiecookies, IP-adres of iets dergelijks meestuurt met elk verzoek.

ATTACK

Stel dat de gebruiker is ingelogd op uw onbeveiligde beurs webapplicatie en dat u ofwel sessiecookies ofwel JWT-cookies gebruikt voor authenticatie. Aanvaller maakt ook gebruik van uw service en is in staat om te controleren hoe uw API werkt. Aanvaller truc gebruiker uit te voeren script (door te klikken op SPAM link in e-mail of iets dergelijks) dat verzoek zal sturen naar uw API https://www.stockexchange.com/users/withdraw?how_much=all&address=MY_ADDRESS (verschrikkelijke API ontwerp, vraag het niet). Omdat het verzoek wordt uitgevoerd vanuit een browser die authenticatie payload stuurt met elk verzoek, zal uw aandelenbeurs web server de gebruiker succesvol authenticeren en transactie uitvoeren en de misleide gebruiker zal al zijn saldo verliezen zonder zich er zelfs maar bewust van te zijn omdat alles op de achtergrond gebeurde. Visuele weergave (bron miro.medium.com)
CSRF attack

BESCHERMING

Gelukkig zijn er eenvoudig te implementeren patronen die deze webaanvallen voorkomen. Een van de meest voorkomende patronen is het gebruik van CSRF token. In principe is de procedure als volgt:

  1. Genereer een uniek token voor elk verzoek van de gebruiker, de zogenaamde CSRF token.
  2. Bewaar het veilig op de server en stuur het terug naar de gebruiker als payload van het antwoord.
  3. Bewaar CSRF token aan de kant van de client.
  4. Wanneer de gebruiker probeert om een state-changing * verzoek uit te voeren stuur dat CSRF token met verzoek als een payload.
  5. Voordat het uitvoeren van dat verzoek op de server controleren of CSRF token aanwezig is en het is geldig.

Dit is de makkelijkste manier om CSRF aanval te voorkomen voor alle gebruikers.

Als je alleen te maken hebt met bezoekers die moderne browsers gebruiken, dan kun je vertrouwen op SameSite attribuut van session cookie.(bedankt Gergely)

Since server’s responses are processable in XHR response, then there is no protection on CSRF attack if your web application is XSS vulnerable!

Voor meer informatie zie de OWASP cheatsheet over CSRF.

BONUS

Korte documentaire over Samy, de auteur van de worm die in 2005 MySpace platlegde door misbruik te maken van het XSS-lek, en die MySpace’s CSRF-verdediging passeerde.
https://youtu.be/DtnuaHl378M

Meer informatie over Samy’s worm
https://samy.pl/myspace/tech.html