JWT's: een diepgaande blik op tokenbeveiliging, kwetsbaarheden en best practices

·

JSON Web Tokens (JWT’s) zijn de facto de standaard voor stateless authenticatie in moderne webapplicaties. Juist hun flexibiliteit leidt echter vaak tot fatale misconfiguraties. Wanneer pentesters een JWT zien, kijken wij niet naar een sessie-identifier - wij kijken naar een cryptografisch aanvalsoppervlak.

Het belangrijkste in het kort

  • Een JWT is gecodeerd, niet versleuteld - elke claim in de payload is leesbaar voor iedereen die het token in handen heeft.
  • Algorithm confusion (RS256 naar HS256) en het none-algoritme blijven de handtekeningfouten met de grootste impact die wij in maatwerk- en legacy-implementaties aantreffen.
  • HS256-secrets zijn wachtwoorden. Een onderschept token laat zich offline kraken met Hashcat, zonder ook maar één verdere interactie met het doelwit.
  • Door de client aangeleverde headerparameters als kid en jku maken van handtekeningverificatie een injectieoppervlak.
  • Een geldige handtekening zegt niets over de geldigheid van de claims - exp, iss en aud moeten bij elk verzoek worden afgedwongen.
  • Houd access tokens in het geheugen en refresh tokens in HttpOnly-, Secure- en SameSite-cookies - nooit in localStorage.

Anatomie van een JWT: header, payload en handtekening

Een JWT bestaat uit drie delen: een header, een payload en een handtekening, elk gescheiden door een punt (.). Voor een pentester ziet een onderschepte JWT eruit als een lange reeks schijnbaar willekeurige tekens. Hier is een voorbeeld uit de praktijk:

eyJraWQiOiI5MTM2ZGRiMy1jYjBhLTRhMTktYTA3ZS1lYWRmNWE0NGM4YjUiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJwb3J0c3dpZ2dlciIsImV4cCI6MTY0ODAzNzE2NCwibmFtZSI6IkNhcmxvcyBNb250b3lhIiwic3ViIjoiY2FybG9zIiwicm9sZSI6ImJsb2dfYXV0aG9yIiwiZW1haWwiOiJjYXJsb3NAY2FybG9zLW1vbnRveWEubmV0IiwiaWF0IjoxNTE2MjM5MDIyfQ.SYZBPIBg2CRjXAJ8vCER0LA_ENjII1JakvNQoP-Hw6GG1zfl4JyngsZReIfqRvIAEi5L4HV0q7_9qGhQZvy9ZdxEJbwTxRs_6Lb-fZTDpW6lKYNdMyjw45_alSCZ1fypsMWz_2mTpQzil0lOtps5Ei_z7mM7M8gCwe_AGpI53JxduQOaB5HkT5gVrv9cKu9CsW5MS6ZbqYXpGyOG5ehoxqm8DL5tFYaW3lB50ELxi0KsuTKEbD0t5BCl0aCR2MBJWAbN-xeLwEenaqBiwPVvKixYleeDQiBEIylFdNNIMviKRgXiYuAvMziVPbwSgkZVHeEdF5MQP1Oe2Spac-6IfA

De header en de payload zijn niet meer dan Base64Url-gecodeerde JSON-objecten. Ze zijn slechts gecodeerd, niet versleuteld. Iedereen met toegang tot het token kan deze gegevens decoderen en lezen.

Visualisatie van de JWT-structuur

Een JWT (technisch gezien een JWS - een JSON Web Token “wanneer ondertekend”) bestaat uit drie door punten gescheiden secties: Header.Payload.Signature.

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhbmRyZWoiLCJyb2xlIjoiaGFja2VyIn0.MmM0ZGMxM2Y1NWQ2YTY2YTE
Header · algoritme & tokentype
{ "alg": "HS256", "typ": "JWT" }
Payload · gegevens
{ "sub": "andrej", "role": "hacker" }
Handtekening
HMACSHA256(
    base64UrlEncode(header) + "." +
    base64UrlEncode(payload),
    "secret"
) = MmM0ZGMxM2Y1NWQ2YTY2YTE

De header

De header bevat metadata over het token zelf, in de eerste plaats het tokentype en het cryptografische algoritme waarmee het token is beveiligd. Het decoderen van het eerste deel van het token hierboven levert op:

{
    "kid": "9136ddb3-cb0a-4a19-a07e-eadf5a44c8b5",
    "alg": "RS256"
}

De payload

De payload bevat de eigenlijke “claims” over de gebruiker. Dit is tijdens een security assessment het belangrijkste doelwit voor manipulatie. Het decoderen van het middelste deel van ons voorbeeld levert op:

{
    "iss": "portswigger",
    "exp": 1648037164,
    "name": "Andrej Šebeň",
    "sub": "andrej",
    "role": "pentester",
    "email": "andrej@haxoris.com",
    "iat": 1516239022
}

De handtekening

Omdat de header en de payload door iedereen eenvoudig te lezen of te wijzigen zijn, leunt de beveiliging van elk JWT-gebaseerd mechanisme zwaar op de cryptografische handtekening.

De server die het token genereert, hasht de Base64Url-gecodeerde header en payload met een geheime ondertekeningssleutel. Dat mechanisme garandeert twee dingen:

  1. Omdat de handtekening rechtstreeks uit de rest van het token wordt afgeleid, leidt het wijzigen van één byte in de header of de payload tot een handtekening die niet meer klopt.
  2. Zonder de geheime ondertekeningssleutel van de server zou het niet mogelijk moeten zijn om de juiste handtekening voor een vervalste header of payload te genereren.

Waar hackers in een JWT naar zoeken

Omdat JWT’s van nature leesbaar zijn, behandelen aanvallers ze als een waardevolle bron voor verkenning in plaats van als versleutelde gegevens. Vanuit offensief perspectief zitten de logische fouten meestal in de payload. Dit zijn de kritieke claims die wij direct inspecteren:

ClaimDoelPentestcontrole
iss (Issuer)Geeft aan wie het token heeft uitgegeven.Valideert de backend dit daadwerkelijk? Een systeem dat tokens van een niet-geautoriseerde derde partij accepteert, is kwetsbaar voor token confusion.
sub (Subject)De gebruiker of entiteit die het token vertegenwoordigt, vaak een gebruikers-ID.Insecure Direct Object Reference (IDOR). Kunnen wij dit wijzigen in admin of user_id=1 en zo de autorisatie omzeilen?
aud (Audience)Geeft de bedoelde ontvanger aan.Kan een token dat voor de ene microservice is uitgegeven, worden hergebruikt tegen een heel andere, sterk geprivilegieerde microservice?
exp (Expiration Time)Het Unix-tijdstempel waarop het token vervalt.Dwingt de server dit werkelijk af? Wij treffen regelmatig API's aan die verlopen tokens onbeperkt blijven accepteren.
nbf (Not Before)Het tijdstip waarvóór het token niet mag worden geaccepteerd.Ontbreekt vaak volledig in de validatielogica.
iat (Issued At)Wanneer het token is aangemaakt.Nuttig om levensduren te berekenen en tokens op te sporen die nooit roteren.

Verkenning van de payload: een goudmijn aan informatielekken

Omdat de payload zichtbaar is voor iedereen die het token bezit, zouden ontwikkelaars die als openbare informatie moeten behandelen. Tijdens assessments vinden wij regelmatig overbodige interne details die via custom claims naar buiten komen:

  • Interne netwerkkaarten: custom claims als "node_ip": "10.0.4.12", "cluster": "prod-us-east-1a" of "db_host": "internal-db.local" verraden de interne netwerkarchitectuur en IP-reeksen.
  • Lekken over framework en identity provider: de naamgeving van claims verraadt de onderliggende techniek. Claims als http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name wijzen op een Microsoft .NET- / Entra ID-backend, waarna wij gericht op stackspecifieke kwetsbaarheden kunnen jagen.
  • Persoonsgegevens: onnodige blootstelling van e-mailadressen, telefoonnummers, volledige namen of woonadressen - meteen goed voor een overtreding van de AVG.
  • Enumeratie van tenants en rollen: claims als "tenant_id": "uuid", "is_god_mode": false of "permissions": ["read:profile"] leggen het autorisatieschema bloot en geven ons de exacte parameternamen om privilege-escalatie op te richten.

Een voorbeeld van een lekkende JWT-payload uit de praktijk:

{
  "iss": "auth.internal-corp.local",
  "sub": "usr_99812",
  "email": "andrej@haxoris.com",
  "role": "admin",
  "internal_ip": "10.240.12.88",
  "db_shard": "shard-04-eu",
  "is_admin": true,
  "exp": 1748037164
}

Zodra zulke persoonsgegevens in een token belanden dat door de browser wordt bewaard en met elk verzoek meegaat, is dit niet langer alleen een technisch probleem. Leidt een tokenlek tot een datalek, dan geldt de meldplicht van artikel 33 AVG: melden bij de Autoriteit Persoonsgegevens binnen 72 uur.

Bearer tokens versus refresh tokens: architectuur en opslag

Een veilige JWT-implementatie steunt op een systeem met twee tokens: kortlevende access tokens (bearer tokens) en langlevende refresh tokens. Die verkeerd opslaan is veruit de meest voorkomende kwetsbaarheid die wij rapporteren.

Bearer tokens (access tokens)

  • Access tokens autoriseren API-verzoeken en zijn bewust kortlevend, doorgaans tussen de 5 en 15 minuten.
  • Bewaar ze uitsluitend in het geheugen van de applicatie. Vermijd localStorage en sessionStorage, omdat elke geslaagde XSS-kwetsbaarheid ze aan een aanvaller kan prijsgeven.

Refresh tokens

  • Refresh tokens bestaan uitsluitend om na het verlopen nieuwe access tokens op te halen.
  • Zij horen te worden opgeslagen in HttpOnly-, Secure- en SameSite-cookies. Dat voorkomt toegang vanuit JavaScript, beperkt tokendiefstal via XSS aanzienlijk en helpt bovendien CSRF te beperken.

Het draaiboek van de pentester: veelvoorkomende JWT-exploits

Bij het beoordelen van een webapplicatie werken pentestteams doorgaans de volgende aanvalsvectoren af.

A. Fouten in handtekeningvalidatie

Veel JWT-kwetsbaarheden komen voort uit gebrekkige handtekeningverificatie en niet uit gebroken cryptografie. Historisch accepteerden sommige bibliotheken het none-algoritme, waardoor aanvallers de handtekening volledig konden weglaten en tegelijk claims als gebruikersrollen naar believen konden aanpassen. Alle grote moderne bibliotheken weigeren none standaard, maar de fout duikt nog steeds op in legacy-applicaties en zelfgebouwde JWT-implementaties - en het loont om erop te testen zodra u een niet-standaard stack tegenkomt.

Een ander klassiek probleem is algorithm confusion. Dit is een van de JWT-kwetsbaarheden met de grootste impact en het is de moeite waard om die precies te begrijpen.

  • RS256 is een asymmetrisch algoritme. De server ondertekent tokens met zijn private sleutel en verifieert ze met de bijbehorende publieke sleutel. Die publieke sleutel is vaak vrij beschikbaar - bijvoorbeeld via een /.well-known/jwks.json-endpoint.
  • HS256 is een symmetrisch algoritme. De server gebruikt één gedeeld secret om tokens zowel te ondertekenen als te verifiëren.

De aanval buit uit wat er gebeurt als een server beide algoritmen accepteert zonder expliciet vast te leggen welk algoritme hij verwacht:

  1. De aanvaller bemachtigt de publieke sleutel van de server, vaak triviaal, via het JWKS-endpoint.
  2. Hij past de payload van het token aan - bijvoorbeeld door "role": "user" te verhogen naar "role": "admin".
  3. Hij wijzigt de header van "alg": "RS256" naar "alg": "HS256".
  4. Hij ondertekent het volledige gewijzigde token (header en payload) opnieuw met de publieke sleutel als HS256-secret.
  5. De server ontvangt het token, ziet alg: HS256 en verifieert het met de publieke sleutel als HMAC-secret. Het klopt, en het vervalste token wordt geaccepteerd.
JWT algorithm confusion-aanval: de alg-header van RS256 naar HS256 wijzigen en het token opnieuw ondertekenen met de publieke sleutel van de server als HMAC-secret

De grondoorzaak is geen gebroken cryptografie - het is de server die blind vertrouwt op de door de client aangeleverde alg-header om te bepalen hoe het token wordt geverifieerd. Normaal gesproken zou het wijzigen van alg in de header de handtekening ongeldig maken, omdat de handtekening zowel de header als de payload afdekt. Maar de aanvaller ondertekent het volledige gewijzigde token opnieuw, waardoor de nieuwe handtekening onder het omgeschakelde algoritme perfect klopt.

Moderne bibliotheken hebben deze fouten grotendeels uitgebannen, maar ze duiken nog steeds op in legacy-applicaties en zelfgebouwde JWT-implementaties.

B. Zwakke ondertekeningssecrets

Applicaties die symmetrische algoritmen als HS256 gebruiken, zijn niet veiliger dan het secret waarmee het token wordt ondertekend.

Tijdens een pentest kan een onderschepte JWT volledig offline worden aangevallen met tools als Hashcat of John the Ripper. Zwakke secrets zoals bedrijfsnamen, woordenboekwoorden of voorspelbare zinnen worden vaak binnen enkele minuten gekraakt, waarna aanvallers geldige tokens voor elke gebruiker kunnen aanmaken zonder ooit nog met de doelapplicatie te communiceren.

C. Injectie via headerparameters

JWT-headers kunnen optionele parameters bevatten zoals kid (Key ID) en jku (JWK Set URL), die de server helpen bepalen welke ondertekeningssleutel bij de verificatie moet worden gebruikt. Omdat die waarden door de client worden aangeleverd, levert het vertrouwen erop zonder goede validatie ernstige kwetsbaarheden op.

Veelvoorkomende aanvalsvectoren zijn:

  • het manipuleren van de jku-parameter zodat die naar een JWKS-endpoint van de aanvaller verwijst;
  • het misbruiken van directory traversal via de kid-parameter wanneer sleutels rechtstreeks van het bestandssysteem worden geladen;
  • het uitbuiten van SQL-injectie waar de waarde van kid in databasequery’s wordt samengevoegd.

Volwassen JWT-bibliotheken gaan veilig met deze scenario’s om, maar zelfgebouwde verificatielogica levert nog altijd bevindingen op tijdens security assessments.

D. Fouten in claimvalidatie

Een geldige handtekening betekent niet automatisch dat een token te vertrouwen is. Elke beveiligingsrelevante claim moet ook door de applicatie worden gevalideerd.

Tijdens pentests komen wij regelmatig API’s tegen die:

  • verlopen tokens accepteren doordat de exp-claim wordt genegeerd;
  • de bedoelde ontvanger (aud) niet valideren, waardoor tokens tussen verschillende diensten kunnen worden hergebruikt;
  • willekeurige waarden voor de uitgever (iss) vertrouwen;
  • uitsluitend leunen op door de client bestuurde claims als role, tenant of permissions zonder de autorisatie server-side af te dwingen.

Deze logische fouten hebben in de praktijk vaak meer impact dan cryptografische zwakheden, omdat ze legitieme tokens op onbedoelde manieren bruikbaar maken.

Moderne tooling voor het testen van JWT-beveiliging

Handmatig Base64 decoderen en handtekeningen manipuleren is inefficiënt. Pentesters gebruiken gespecialiseerde tools om deze aanvallen te automatiseren:

  • JWTAuditor: een uitstekend, volledig client-side testplatform dat op pentesters is toegesneden. Het maakt snelle inspectie, geautomatiseerde detectie van kwetsbaarheden (zoals het testen op none-algoritmen of headerinjecties) en offline brute-forcing mogelijk, zonder gevoelige klanttokens aan telemetrie van derden bloot te stellen.
  • Burp Suite (JWT Editor-extensie): veelgebruikt tijdens dynamisch webtesten om tokens direct in de HTTP-proxy te manipuleren.
  • JWT.io: onderhouden door Auth0 en de standaardtool om tokens snel handmatig te decoderen en tokenstructuren en handtekeningen tijdens de eerste verkenning te controleren.
  • JWTLens: een licht, privacygericht alternatief voor tokeninspectie. Het decodeert en verifieert tokens volledig in de browser via de native Web Crypto API, waardoor uw tokens en sleutels uw machine nooit verlaten. Omdat er tijdens de verificatie geen netwerkverzoeken worden gedaan, is het ideaal om algoritmen en handtekeningen veilig te valideren.

Praktische best practices voor verdediging

Om uw applicatie van de lijst met kritieke bevindingen in een pentestrapport te houden, doen ontwikkelteams er goed aan deze kernmaatregelen af te dwingen:

  • Leg verwachte algoritmen vast in code: laat het binnenkomende token nooit bepalen hoe het moet worden geverifieerd. Configureer uw validatieroutine expliciet op één specifiek algoritme (bijvoorbeeld RS256) en weiger het none-algoritme onvoorwaardelijk.
  • Dwing volledige claimvalidatie af: een geldige handtekening bewijst alleen dat het token niet is gemanipuleerd, niet dat het op dit moment geldig is voor deze gebruiker. Valideer exp (vervaltijd), iss (uitgever) en aud (ontvanger) expliciet bij elk afzonderlijk verzoek.
  • Behandel symmetrische secrets als wachtwoorden: vereist uw architectuur symmetrische ondertekening (HS256), dan is uw geheime sleutel feitelijk een rootwachtwoord. Zorg voor minimaal 256 bits entropie, genereer de sleutel met een cryptografisch veilige randomgenerator en bewaar hem veilig in omgevingsvariabelen of een secrets manager - nooit hardcoded in de broncode.
  • Onthoud: coderen is geen versleutelen. Bewaar nooit gevoelige gegevens, persoonsgegevens of wachtwoorden in de JWT-payload. Wie het token onderschept, kan het onmiddellijk Base64-decoderen.
  • Isoleer tokenopslag: bewaar kortlevende access tokens nooit in localStorage of sessionStorage, waar een enkele XSS-kwetsbaarheid ze kan buitmaken. Houd access tokens strikt in het geheugen van de client en plaats langlevende refresh tokens in veilige HttpOnly- en SameSite-cookies.

Het periodiek toetsen van deze maatregelen is geen vrijblijvende luxe. AVG artikel 32 lid 1 sub d verlangt, waar passend, “een procedure voor het op gezette tijdstippen testen, beoordelen en evalueren van de doeltreffendheid” van technische en organisatorische beveiligingsmaatregelen. Authenticatie- en autorisatielogica is precies het onderdeel waar zo’n toets zijn geld opbrengt: een JWT-implementatie die vandaag klopt, kan na één bibliotheekupgrade of één nieuw microservice-endpoint alweer een gat vertonen. Wilt u weten hoe zo’n toets in de praktijk verloopt, lees dan wat een pentest precies is of hoe die zich verhoudt tot een kwetsbaarheidsscan.

Geavanceerde hardening: het phantom token-patroon

Voor omgevingen met hoge beveiligingseisen is de effectiefste verdediging tegen diefstal aan clientzijde om de JWT helemaal niet aan de frontend prijs te geven. Moderne enterprise-architecturen implementeren daarvoor vaak het “phantom token”-patroon, met deze stappen:

  1. De autorisatieserver geeft een willekeurige, ondoorzichtige sessiestring (in plaats van een JWT) uit aan de clientapplicatie.
  2. Wanneer de client een API-verzoek doet, stuurt hij deze ondoorzichtige string mee.
  3. De API-gateway onderschept het verzoek, valideert het ondoorzichtige token bij de autorisatieserver (of de sessieopslag) en wisselt het om voor een volledig gevulde, ondertekende JWT.
  4. De API-gateway stuurt de daadwerkelijke JWT door naar de interne microservices.

Veelgestelde vragen over JWT-beveiliging

01

Is een JWT versleuteld?

Nee. De header en de payload van een standaard ondertekende JWT (een JWS) zijn alleen Base64Url-gecodeerd, niet versleuteld. Iedereen die het token in handen heeft, kan elke claim erin decoderen en lezen. De handtekening beschermt de integriteit, niet de vertrouwelijkheid. Gevoelige gegevens of persoonsgegevens horen dus niet thuis in een JWT-payload.

02

Wat is JWT algorithm confusion?

Algorithm confusion ontstaat wanneer een server de alg-header van het token zelf laat bepalen hoe de handtekening wordt geverifieerd. Een aanvaller neemt de publieke RSA-sleutel van de server, wijzigt de header van RS256 naar HS256, past de payload aan en ondertekent het hele token opnieuw met die publieke sleutel als HMAC-secret. Een server die beide algoritmen accepteert, verifieert de vervalsing met succes. De oplossing is het verwachte algoritme vast in de servercode te leggen.

03

Waar horen access tokens en refresh tokens in een browser te worden opgeslagen?

Bewaar kortlevende access tokens uitsluitend in het geheugen van de applicatie. Sla langlevende refresh tokens op in HttpOnly-, Secure- en SameSite-cookies, zodat JavaScript ze niet kan lezen. Plaats geen van beide tokens in localStorage of sessionStorage, waar een enkele XSS-kwetsbaarheid ze kan buitmaken.

04

Hoe kraken aanvallers HS256-signing secrets?

Een onderschept HS256-token kan volledig offline worden aangevallen met tools als Hashcat of John the Ripper, zonder verdere interactie met de doelapplicatie. Zwakke secrets zoals bedrijfsnamen, woordenboekwoorden of voorspelbare zinnen vallen vaak binnen enkele minuten, waarna de aanvaller geldige tokens voor elke gebruiker kan aanmaken. Symmetrische secrets hebben minimaal 256 bits entropie uit een cryptografisch veilige generator nodig.

05

Betekent een geldige handtekening dat een JWT te vertrouwen is?

Nee. Een geldige handtekening bewijst alleen dat het token niet is gemanipuleerd. De applicatie moet nog steeds elke beveiligingsrelevante claim valideren: exp voor de vervaltijd, iss voor de uitgever, aud voor de bedoelde ontvanger - en zij mag nooit vertrouwen op door de client aangeleverde claims als role of permissions zonder de autorisatie server-side af te dwingen.

Hoe Haxoris u kan helpen

Tokenbeveiliging sneuvelt zelden op cryptografie - zij sneuvelt op configuratie. Haxoris helpt u die gaten te vinden voordat een aanvaller dat doet:

  • Pentest van webapplicaties en API’s, met bijzondere aandacht voor authenticatie- en autorisatiestromen.
  • Review van de logica voor uitgifte, verificatie en sleutelbeheer van JWT’s, inclusief JWKS-afhandeling en sleutelrotatie.
  • Offline sterktebeoordeling van symmetrische ondertekeningssecrets.
  • Ontwerpreview van tokenopslag, sessielevensduren en de architectuur rond refresh tokens.

Elke opdracht start met een schriftelijke opdrachtbevestiging waarin scope, tijdvenster en contactpersonen zijn vastgelegd. Die schriftelijke toestemming is wat een geautoriseerde test onderscheidt van computervredebreuk (artikel 138ab Wetboek van Strafrecht); een Nederlands register of vergunningstelsel voor pentesters bestaat niet. Na het oplossen van de bevindingen voeren wij een hertest uit, zodat u zwart-op-wit hebt dat de gaten dicht zijn.

Conclusie

JWT’s zijn niet onveilig van ontwerp. Zij worden onveilig op het moment dat een applicatie het token laat bepalen hoe het gevalideerd moet worden, of een geldige handtekening als vervanging voor autorisatie behandelt. Leg het algoritme vast in code, valideer elke claim, behandel secrets als rootwachtwoorden en houd tokens buiten de browseropslag - dan verdwijnt het merendeel van de bevindingen uit dit artikel uit uw volgende pentestrapport.

Bronnen en aanbevolen literatuur

De methodieken en technische details in dit artikel zijn geïnspireerd op en overgenomen uit de volgende gezaghebbende beveiligingsbronnen:

  1. PortSwigger Web Security Academy. JWT Security Vulnerabilities. Een gedetailleerde uiteenzetting over fouten in handtekeningverificatie en headerinjecties. portswigger.net/web-security/jwt
  2. InfoSec Writeups. JWT Pentesting: A Journey from Token to Takeover. Praktijkcasussen over het uitbuiten van tokenconfiguraties. infosecwriteups.com
  3. Auth0 / JWT.io. Introduction to JSON Web Tokens. Fundamentele standaarddocumentatie over tokenstructuren en RFC 7519. jwt.io/introduction
  4. JWTAuditor. Security Testing Tool. Gebruikt voor payloadmanipulatie en geautomatiseerde vulnerability assessments. jwtauditor.com
Pavol Litauszki

Auteur

Pavol Litauszki

Wacht niet op aanvallers - breng uw zwakste plek nu in kaart met een pentest!

Gratis adviesgesprek