Reflected-XSS kwetsbaarheid gemeente Eindhoven

Jeremy Melis

11-11-2024

Introductie

Deze kwetsbaarheid werd gevonden tijdens het "Hack Me Please"-evenement dat door de gemeente Eindhoven georganiseerd werd voor studenten van de Fontys Hogeschool. Het evenement startte op 8 oktober 2024 en eindigde op 8 november 2024. Tijdens dit evenement heb ik een reflected XSS-kwetsbaarheid gevonden. Dit is de write-up van deze bevinding.

(Fixed) exploit

Werkende exploit:

https://werkenvooreindhoven.easycruit.com/career-center/login?iso=')%3b}vartest=alert()%3beval(test)%3b{//

Screenshot: Execution

Hoe het in de code ingeladen is: Executed in code

(Line 56, Column 661)

Notitie: Voor extra duidelijkheid is in de screenshot een payload met (URL-encoded) spaties gebruikt.


Hoe de kwetsbaarheid gevonden is

Burp Suite gaf aan dat er mogelijk XSS aanwezig was op de ?iso-parameter. Na het testen van deze claim kwam ik erachter dat de input werd gereflecteerd in de code, maar dat dit nog geen popup triggerde. Een popup wordt vaak gebruikt om de aanwezigheid van XSS te bewijzen.

  • Burp's payload: nl16952%27%3balert(1)%2f%2f393

Daarna heb ik het stuk code gevonden waarin deze payload werd gebruikt, door in de code te zoeken op alert. Dit leidde mij naar Line 56, Column 661 in de code. Executed in code - Burp

Waarom de popup niet werd getriggerd

De payload gaf geen popup zoals verwacht, dus ging ik kijken wat hiervan de oorzaak was. Na het verwijderen van de extra code uit de payload kwam ik erachter dat alleen een single quote (') nodig was om de mogelijke XSS te triggeren.

Ik testte vervolgens '<script>alert()</script>, maar dit werkte niet omdat de website de <- en >-karakters blokkeerde. Deze werden namelijk omgezet naar een HTML-entiteit (dus > werd &gt; en < werd &lt;). Dit is hier te zien: Blocked characters

Om alsnog een payload te laten triggeren probeerde ik daarna URL-encoding voor de speciale karakters. Zo gebruikte ik %3a voor >. Dit werkte ook niet, en daarnaast kwam ik erachter dat " ook geblokkeerd werd.

Lezen & fixen van de code

Na het lezen van de code kwam ik erachter dat het niet nodig was om <script> toe te voegen, omdat het gedeelte in de code waar ik toegang toe had al omringd was door <script>-tags. Zie afbeelding. Inside script already

Het rood gemarkeerde gedeelte laat zien dat we ons al in een <script>-tag bevinden. De rode pijl geeft de regel weer waar we toegang toe hebben via de XSS-kwetsbaarheid.

Ik probeerde daarna 'alert(). Executed in code Simple

Dit liet een error message zien. Na het hoveren over deze error met de muis stond er: Uncaught SyntaxError: missing ) after argument list

Ik kopieerde het gedeelte van de websitecode waarin ik de XSS-payload kon injecteren en plakte dit in een HTML-bestand in Visual Studio Code. Vervolgens experimenteerde ik met verschillende manieren om de syntaxfout te verhelpen, maar ik had geen toegang tot het laatste gedeelte van de regel code. Om ervoor te zorgen dat dit geen probleem vormde, heb ik het laatste gedeelte van deze regel uitgekommenteerd.

Dit zorgde ervoor dat de error werd verholpen en leidde tot een eerste succesvolle payload.

Payloads maken

Nadat ik alle syntaxfouten uit mijn HTML-testbestand had gehaald, kwam ik tot de volgende werkende payload: %27)%3b}%20var%20test%20=%20alert()%3b%20eval(test)%3b%20{//

Hier gebruik ik %20, dit is een URL-encoded spatie. Nadat ik dit gevonden had, probeerde ik een kortere payload te maken door alle spaties te verwijderen en de namen van de variabelen te verkorten. Dit gaf mij de volgende payload: ')%3b}vart=alert()%3beval(t)%3b{//


Oorzaken

Net zoals bij alle andere XSS-kwetsbaarheden komt deze kwetsbaarheid voort uit het onjuist saniteren van gebruikersinput. Het veld (?iso) had als functie om de taal van de website te veranderen. Er was echter geen knop op de website die gebruikmaakte van deze functionaliteit, waardoor ik ervan uitga dat deze functionaliteit vergeten was.

De HTML-code waarin de injectie plaatsvindt probeert ook het gehele JavaScript-gedeelte uit te commenteren, maar doet dit op een onjuiste manier. Zie de afbeelding hieronder.

Slechte comment

De highlight laat de onjuiste commentnotatie zien.

Deze comment gebruikt een HTML-comment en een JavaScript-comment door elkaar, wat ervoor zorgt dat geen van beide correct werkt. <!-- is een HTML-comment, // is een JavaScript-comment. Een HTML-comment werkt hier niet, omdat we ons al binnen een <script>-tag bevinden, terwijl de JavaScript-comment niet werkt omdat deze slechts één regel code uitcommentarieert. De regel code waarin de payload wordt getriggerd bevindt zich op een andere regel en kan dus gewoon uitgevoerd worden.

Impact

Na contact te hebben opgenomen met de gemeente Eindhoven over deze kwetsbaarheid, werd er contact met mij opgenomen. Mij werd gemeld dat er een intern onderzoek had plaatsgevonden, omdat iemand het domein online had gezet zonder de juiste stappen te doorlopen (zoals een pentest). De gemeente heeft haar stappenplan aangepast om te voorkomen dat soortgelijke incidenten zich opnieuw voordoen. Ook de maker van de software is gecontacteerd en heeft de kwetsbaarheid verholpen.

Hack Me Please-evenement

Ik heb deze kwetsbaarheid gevonden tijdens het "Hack Me Please"-evenement van de gemeente Eindhoven voor studenten van Fontys HBO ICT. Voor het vinden van deze kwetsbaarheid heb ik samen met mijn groep dit evenement gewonnen en heb ik persoonlijk ook een mooi schilderij gekregen van de TISO van de gemeente Eindhoven, zie foto.

Links: Rob Mellegers (CISO), rechts: Geert Bax (TISO) van de gemeente Eindhoven.