Broken authentication
CWE-287OWASP A07:2021Bijgewerkt 29 augustus 20265 min leestijd
Broken authentication is een verzamelnaam voor fouten in inloggen en sessiebeheer waardoor een aanvaller zich als een andere gebruiker kan voordoen. Denk aan brute force zonder limiet, onveilige wachtwoordopslag of voorspelbare sessietokens. De oplossing combineert MFA, sterke wachtwoordhashing en degelijk sessiebeheer.
Het inlogscherm is de voordeur van uw applicatie, en juist die voordeur blijkt in de praktijk vaak de zwakste plek. Broken authentication staat als Identification and Authentication Failures in de OWASP Top 10 en omvat alle manieren waarop aanvallers de identiteitscontrole omzeilen, van brute force tot vervalste sessies. Hieronder leest u hoe zulke aanvallen verlopen en hoe u inloggen en sessiebeheer wél op orde krijgt.
Wat is broken authentication?
Broken authentication is de verzamelnaam voor kwetsbaarheden in de manier waarop een applicatie vaststelt wie er inlogt én hoe zij die ingelogde status daarna bewaakt. Het gaat dus niet om één specifieke fout, maar om een familie: zwakke wachtwoordeisen, onveilige wachtwoordopslag, inlogformulieren zonder rem op het aantal pogingen, voorspelbare sessietokens en slordige herstelflows voor vergeten wachtwoorden. In alle varianten is de uitkomst gelijk: iemand krijgt toegang tot een account dat niet van hem is.
Een alledaagse vergelijking: een hotel waar de receptionist een kamersleutel meegeeft aan iedereen die een kamernummer noemt, zonder ooit legitimatie te vragen. Of een hotel dat wél controleert, maar sleutelkaarten uitgeeft met opeenvolgende nummers: wie kaart 214 heeft, weet hoe 215 eruitziet. In beide gevallen is niet het slot kapot, maar het proces eromheen.
Belangrijk om te beseffen: authenticatie is breder dan het inlogformulier alleen. Ook wachtwoordopslag, sessiebeheer, onthoud-mij-cookies, API-sleutels en de wachtwoord-reset horen bij dezelfde keten, en een aanvaller zoekt altijd de zwakste schakel.
Hoe werkt een aanval op authenticatie?
Aanvallers hoeven zelden iets te kraken; meestal gebruiken ze de voordeur zoals hij is gebouwd. Bij credential stuffing proberen ze gelekte e-mail-wachtwoordcombinaties uit eerdere datalekken geautomatiseerd uit. Bij brute force laten ze een script duizenden wachtwoorden per minuut afvuren. En als de applicatie zelf zwakke tokens uitdeelt, slaan ze het raden zelfs over. Het voorbeeld hieronder is een login-endpoint dat drie klassieke fouten combineert.
Kwetsbaar:
// Wachtwoord in platte tekst, pratende foutmeldingen, voorspelbaar token
app.post("/login", async (req, res) => {
const user = await db.findUserByEmail(req.body.email);
if (!user) {
return res.status(401).send("Onbekend e-mailadres");
}
if (user.password !== req.body.password) {
return res.status(401).send("Wachtwoord onjuist");
}
// "Sessietoken": Base64 van het gebruikers-id
const token = Buffer.from("user:" + user.id).toString("base64");
res.cookie("session", token);
res.send("Ingelogd");
});
Er gaat hier van alles mis tegelijk. De twee verschillende foutmeldingen verraden of een e-mailadres bestaat (user enumeration), waardoor een aanvaller eerst een lijst geldige accounts opbouwt en daarna gericht gelekte wachtwoorden test. Een limiet op het aantal pogingen ontbreekt, dus dat testen mag eindeloos doorgaan. Het wachtwoord staat bovendien in platte tekst in de database. Eén datalek en elk wachtwoord ligt op straat. De ernstigste fout is echter het sessietoken: Base64 is geen encryptie maar een codering die iedereen kan omkeren. Een aanvaller codeert zelf de tekst user:1, plakt de uitkomst dXNlcjox in zijn cookie en is ingelogd als gebruiker 1, vaak een beheerder, zonder ooit een wachtwoord te hoeven kennen.
De veilige variant repareert alle drie de zwaktes: wachtwoorden worden als hash vergeleken, de foutmelding verklapt niets, het aantal pogingen is begrensd en het sessietoken komt uit een cryptografisch veilige generator.
Veilig:
// Hash-vergelijking, generieke foutmelding, limiet, willekeurig token
app.post("/login", loginRateLimiter, async (req, res) => {
const user = await db.findUserByEmail(req.body.email);
const hash = user ? user.passwordHash : DUMMY_HASH;
const valid = await bcrypt.compare(req.body.password, hash);
if (!user || !valid) {
return res.status(401).send("Ongeldige inloggegevens");
}
// Sessietoken: 32 willekeurige bytes, server-side opgeslagen
const sessionId = crypto.randomBytes(32).toString("hex");
await sessions.create(sessionId, user.id);
res.cookie("session", sessionId, {
httpOnly: true,
secure: true,
sameSite: "lax",
});
res.send("Ingelogd");
});
Let op het detail met DUMMY_HASH: ook als het account niet bestaat, voert de code een hash-vergelijking uit. Zo duurt elke inlogpoging even lang en valt uit de reactietijd niet af te leiden welke e-mailadressen bestaan. Het sessietoken is nu 256 bits toeval dat alleen server-side aan een gebruiker gekoppeld is; raden of terugrekenen is kansloos. De cookie-vlaggen zorgen er ten slotte voor dat scripts en afluisteraars niet bij het token kunnen.
Wat is de impact van broken authentication?
De directe schade is accountovername. Een aanvaller die als klant inlogt, ziet persoonsgegevens, bestelhistorie en opgeslagen betaalmethoden, en kan namens het slachtoffer handelen. Gaat het om een beheerdersaccount, dan verschuift de impact van één account naar de hele applicatie: alle gebruikersgegevens, alle instellingen, vaak ook een opstap naar de onderliggende infrastructuur.
Op schaal wordt het een bedrijfsrisico. Credential stuffing is goedkoop te automatiseren, dus één zwak inlogformulier kan binnen dagen duizenden overgenomen accounts opleveren, met fraude, chargebacks en een meldplichtig datalek onder de AVG als gevolg. Reputatieschade komt daar nog bovenop: gebruikers vergeven een gehackt account zelden.
Extra verraderlijk is dat deze aanvallen nauwelijks opvallen. Een gekaapte sessie of een geslaagde credential-stuffing-login ziet er in de logs uit als een gewone gebruiker die inlogt. Omdat de gevolgen uiteenlopen van één overgenomen account tot volledige compromittering van de applicatie, loopt de ernst van hoog tot kritiek.
Hoe spoort u broken authentication op?
Testers beginnen bij wat de applicatie prijsgeeft: verschillen in foutmeldingen of reactietijden die verraden welke accounts bestaan. Daarna volgt de rem op pogingen: accepteert het formulier honderden wachtwoorden achter elkaar zonder blokkade of vertraging? Ook sessietokens worden onderzocht: door er tientallen te verzamelen en te analyseren op patronen, lengte en voorspelbaarheid. Tot slot de levenscyclus: blijft een sessie geldig na uitloggen of na een wachtwoordwijziging, en hoe streng is de herstelflow?
Geautomatiseerde scanners vangen hooguit de oppervlakkige signalen; de logica erachter vergt handwerk. Dit is bij uitstek een onderdeel dat AssistSec tijdens een penetratietest systematisch doorloopt, van tokenanalyse tot resetflow, zodat u precies weet via welke route een aanvaller daadwerkelijk bij een account komt.
Hoe voorkomt u broken authentication?
- Schakel multi-factor authenticatie (MFA) in, minimaal voor beheerders. Een gelekt of geraden wachtwoord is dan niet langer genoeg.
- Sla wachtwoorden op als hash met bcrypt, scrypt of Argon2, nooit in platte tekst en nooit met snelle hashes zoals MD5 of SHA-1.
- Begrens inlogpogingen met rate limiting, oplopende vertraging of een tijdelijke blokkade per account én per IP-adres.
- Houd foutmeldingen generiek, ongeacht of het e-mailadres bestaat, en houd ook de reactietijd gelijk.
- Genereer sessietokens met een cryptografisch veilige generator, bewaar ze server-side en geef cookies de vlaggen httpOnly, secure en sameSite mee.
- Vernieuw het sessietoken direct na inloggen en maak alle sessies ongeldig bij uitloggen en na een wachtwoordwijziging.
- Maak resettokens eenmalig en kort geldig en bevestig gevoelige wijzigingen via een tweede kanaal.
- Toets nieuwe wachtwoorden aan lijsten met gelekte wachtwoorden in plaats van alleen op complexiteitsregels te vertrouwen.
- Laat de hele authenticatieketen periodiek testen, inclusief sessiebeheer en herstelflows. Daar zitten de fouten die scanners missen.
Bronnen
Veelgestelde vragen
Wat valt er allemaal onder broken authentication?
Alle fouten waarmee een aanvaller zich als iemand anders kan voordoen: zwakke of gelekte wachtwoorden, brute force zonder limiet, onveilige wachtwoordopslag, voorspelbare sessietokens en kwetsbare herstelflows voor vergeten wachtwoorden.
Wat is credential stuffing?
Een aanval waarbij gelekte combinaties van e-mailadres en wachtwoord uit eerdere datalekken geautomatiseerd op andere sites worden geprobeerd. Omdat veel mensen wachtwoorden hergebruiken, slaagt steevast een klein maar winstgevend percentage.
Is een streng wachtwoordbeleid voldoende?
Nee. Complexiteitsregels helpen weinig tegen hergebruikte of gelekte wachtwoorden en niets tegen zwak sessiebeheer. Combineer een goed beleid met MFA, rate limiting en veilige sessietokens.
Helpt MFA tegen broken authentication?
Het is de effectiefste losse maatregel: een gestolen of geraden wachtwoord is dan niet meer genoeg om in te loggen. MFA beschermt alleen niet tegen fouten in sessiebeheer, dus ook die basis moet op orde zijn.
Verwante artikelen
- CVE'sCWE-119A07:2021Citrix Bleed (CVE-2023-4966)Citrix Bleed uitgelegd: hoe aanvallers sessietokens uit NetScaler-geheugen lazen, daarmee MFA omzeilden en waarom patchen alleen niet genoeg was.
- BegrippenMFA (multifactorauthenticatie)MFA vraagt naast uw wachtwoord om een tweede factor. Waarom sms en push zwakker zijn en waarom passkeys en FIDO2 wel phishing-bestendig zijn.
- BegrippenPentestEen pentest is een gecontroleerde aanval op uw systemen door ethische hackers. Lees hoe een penetratietest werkt en welke kwetsbaarheden u ermee vindt.
- BegrippenPhishingPhishing is een aanval waarbij criminelen zich voordoen als een vertrouwde partij om inloggegevens of geld los te krijgen. Zo werkt het en zo stopt u het.
- KwetsbaarhedenCWE-352A01:2021Cross-site request forgery (CSRF)Cross-site request forgery (CSRF) uitgelegd: hoe een aanvaller de browser van een ingelogde gebruiker misbruikt voor ongewenste acties, en hoe u het voorkomt.