Ons het MFA vereis. Een query-parameter het dit afgeskakel.
Ons het multifaktor-verifikasie vrygestel. Ná die wagwoord het die aanmeldbladsy 'n tweede faktor afgevra, soos jy sou verwag. Ons het dit getoets, dit het gewerk, ons het aanbeweeg. Toe, in 'n voor-bekendstelling-deurloop van ons eie auth-bediener, het ons ontdek jy kon die hele ding oorslaan deur 'n URL te wysig.
Hier is die vorm daarvan. In 'n OIDC-vloei stuur jou toepassing die gebruiker na /connect/authorize. As hulle nog nie aangemeld is nie, bons die bediener hulle na die aanmeldbladsy met die oorspronklike bestemming in 'n parameter weggesteek: /login?returnUrl=/connect/authorize?.... Jy voer jou wagwoord in, jy slaag MFA, en die aanmeldvloei stuur jou terug na daardie returnUrl, waarop /connect/authorize 'n magtigingskode uitreik en die tokens volg.
Die fout het in die volgorde van bewerkings gelê. Die wagwoordstap het jou aangemeld. Dit wil sê, dit het 'n geverifieerde cookie gestel. MFA was die volgende bladsy in die reeks. En /connect/authorize, die endpoint wat werklik tokens uitdeel, het presies een vraag gevra voordat dit dit doen: is hierdie versoek geverifieer? Dit het nooit gevra of die sessie 'n tweede faktor geslaag het nie. "Geverifieer" en "geverifieer met MFA" was dieselfde cookie.
Die omseiling is dus nie slim nie. Jy dien jou wagwoord in. Jy ontvang die geverifieerde cookie. Dan, in plaas daarvan om die vloei na die MFA-prompt te volg, gaan jy self reguit na die returnUrl, /connect/authorize?..., die adres wat die bediener jou heel aan die begin gegee het. Authorize sien 'n geverifieerde principal, voer sy een kontrole uit, en reik die kode uit. Die tweede faktor gebeur nooit nie. Die MFA-prompt was 'n stap in 'n gang, en niks het jou gekeer om daar omheen te loop nie.
Die rede waarom dit toetsing oorleef, is dat die gelukkige pad waterdig is. Klik deur die koppelvlak soos 'n mens en jy word elke keer uitgedaag. Die hek is eg. Dit is net op die verkeerde plek. Die sekuriteitsgrens in 'n OIDC-bediener is nie die aanmeldskerm nie. Dit is /connect/authorize, die punt waar 'n sessie in tokens verander. Enige vereiste wat net in die bladsye leef wat na daardie grens lei, is adviserend, want enigiemand wat die onderliggende versoek kan maak, kan dit direk maak.
Daardie herformulering is die regstelling. MFA is nie 'n stap wat jy uitvoer nie. Dit is 'n eienskap wat die sessie óf het óf nie het nie. So ons het opgehou om dit as 'n bladsy te modelleer en dit begin modelleer as 'n claim. Wanneer jy die tweede faktor slaag, skryf die aanmeldvloei 'n mfa_authenticated-merker in die auth-cookie. /connect/authorize aanvaar nie meer "geverifieer" nie. Dit vereis "geverifieer en met daardie merker daarby." 'n Wagwoord-alleen-cookie is nou kragteloos by die token-endpoint: dit word teruggebons om MFA te voltooi, maak nie saak na watter URL jy dit mik nie, want wat dit kortkom, is 'n claim, nie 'n bladsybesoek nie.
Federasie val hieruit netjies uit. Wanneer 'n gebruiker aanmeld deur 'n eksterne identiteitsverskaffer wat sy eie MFA uitgevoer het, staan daardie verskaffer in vir die tweede faktor, so die gefedereerde aanmelding stel dieselfde merker. SSO-gebruikers word nie twee keer uitgedaag vir iets wat hul IdP reeds afgedwing het nie. Die merker is die enkele bron van waarheid, en elke pad wat MFA regmatig kan bevredig, skryf dit.
Die oordraagbare les het niks met MFA in die besonder te doen nie. Dit is dít: dwing 'n kontrole af by die grens wat die ding toestaan wat jy beskerm, nie by die koppelvlakstap wat veronderstel is om soontoe te lei nie. Ons het die kontrole gehad. Ons het die MFA-logika geskryf, dit getoets, dit vrygestel. Dit was bloot geheg aan die deel van die stelsel wat 'n aanvaller nie hoef te gebruik nie. Toestemmingskerms, aanvaarding van bepalings, step-up vir sensitiewe scopes: dieselfde falingsmodus. As die endpoint wat die geloofsbrief uitreik nie die voorwaarde verifieer nie, is die skerm wat daarvoor vra 'n voorstel.
Ons het hierdie een gevang voordat enige klant dit getref het, in dieselfde oudit wat 'n paar van sy broers en susters opgelewer het. Dit is die argument daarvoor om jou eie auth deur te gaan asof jy dit aanval, en spesifiek om by elke endpoint wat iets waardevols uitdeel te vra, nie "het die gebruiker die vloei deurgestap" nie, maar "wat bewys hierdie versoek werklik." Ons s'n het 'n wagwoord bewys. Ons het dit as bewys van twee faktore behandel.
Om MFA af te dwing by die endpoint wat tokens munt, nie die bladsy wat daarvoor vra nie, is die hele verskil tussen regte MFA en 'n voorstel. Authagonal dwing dit af waar die geloofsbrief uitgereik word, so 'n handgewysigde return-URL kom nêrens nie.