Die SAML-handtekening was geldig. Dit was nooit die probleem nie.
SAML single sign-on het 'n herspeel-probleem wat in sy vorm ingebou is, en die meeste diensverskaffers 'los' dit op die een plek op wat 'n aanvaller kan bereik.
Hier is die opstelling. Jy is die diensverskaffer. 'n Gebruiker beland op jou aanmelding, jy stuur 'n AuthnRequest na hul identiteitsverskaffer, en daardie versoek dra 'n lukrake ID. Die IdP verifieer die gebruiker en pos 'n SAML Response terug met InResponseTo="<that ID>". Jy soek die ID op, bevestig dat jy dit werklik uitgereik het, en verbruik dit sodat dit nooit twee keer gebruik kan word nie. Versoek gebind aan die respons, respons een keer gebruik, herspeel verslaan. Handboek.
Nou die vraag wat dit breek: wat het die IdP werklik geteken?
Nie die Response nie. Die Assertion. Entra, Okta, die meeste in die bedryf teken die <Assertion>-element en laat die <Response>-koevert daarom heen ongetekend. Dit is normaal, en die spesifikasie laat dit toe. Maar InResponseTo leef op die <Response>. Dus, die veld waarop jou hele herspeel-verdediging staatmaak, is die een veld wat die handtekening nie dek nie. Jy kan dit wysig, dit skrap, enigiets daaraan doen, en die assertion se handtekening valideer steeds perfek, want jy het nooit aan die assertion geraak nie.
Kyk dan wat gebeur wanneer 'n aanvaller die voor die hand liggende ding doen.
SAML het twee variante. SP-geïnisieerde response beantwoord 'n versoek wat jy gestuur het, so hulle dra InResponseTo. IdP-geïnisieerde (ongevraagde) response is nooit gevra nie, so hulle het glad nie 'n InResponseTo nie. Jou kode vertak, redelikerwys, hierop: as daar 'n InResponseTo is, pas dit by 'n gestoorde versoek en verbruik dit; as daar nie een is nie, is daar geen versoek om te pas nie, so dit slaan daardie kontrole oor. Daardie oorslaan is die hele kwesbaarheid.
Die aanval is drie stappe en nul kriptografie:
- Vang een werklike, suksesvolle SAML Response vas. 'n Egte aanmelding, 'n egte handtekening, 'n egte assertion.
- Skrap die
InResponseTo-attribuut. Die handtekening dek die assertion, nie die koevert nie, so dit verifieer steeds. - Pos dit terug. Sonder 'n
InResponseTobehandel jou SP dit as IdP-geïnisieer, neem die tak sonder herspeel-kontrole, valideer die handtekening (geldig), en teken die gebruiker in.
Pos dit dan weer. En weer. Die assertion is nou 'n loper-sleutel. Elke kontrole waarop jy trots was slaag steeds: handtekening geldig, sertifikaat vasgepen, uitreiker korrek, voorwaardes binne datum. Die een beheer wat 'n herspeel sou gestop het was gekoppel aan 'n veld wat die aanvaller gratis skrap.
Hier is die strik in een reël: jy het die assertion geteken, maar jou hek sit op die koevert.
Die regstelling is nie meer validasie nie. Dit is om die regte ding te valideer. Hou op om herspeel-beskerming op InResponseTo te koppel, wat ongetekend en opsioneel is, en koppel dit aan die assertion se eie ID, wat geteken en altyd teenwoordig is. Elke assertion het 'n ID, dit sit binne die handtekening, en om daarmee te peuter breek verifikasie. Hou 'n eenmalige-gebruik-kas van assertion-ID's, begrens deur elke assertion se NotOnOrAfter sodat die kas nooit sonder perk groei nie, en verwerp enige ID wat jy reeds gesien het. Nou baat die skrap van InResponseTo die aanvaller niks nie, want die waarde wat jy werklik nagaan kan nie vervals word nie en kan nie herspeel word nie.
Terwyl jy daar is, behandel die versoek-binding as verdediging in diepte eerder as die primêre beheer. Pas steeds InResponseTo wanneer dit teenwoordig is. Verwerp steeds ongevraagde response reguit as jy nooit IdP-geïnisieerde aanmelding aanbied nie. Handhaaf steeds Audience en die Conditions-venster. Maar die dravende anti-herspeel-kontrole moet op getekende grepe sit, punt uit.
Ons weet van hierdie een omdat ons dit gevind het terwyl ons ons eie SAML geoudit het voordat ons gelanseer het, nie omdat 'n klant dit agterna gevind het nie. En die les veralgemeen ver verby SAML. 'n Handtekening beantwoord presies een vraag: het die houer van hierdie sleutel hierdie grepe geproduseer. Dit vertel jou nie dat die grepe vars is nie, dat hulle vir jou bedoel was nie, of dat jy hulle nie reeds een keer aanvaar het nie. Dit is drie afsonderlike kontroles, en elkeen van hulle moet 'n veld lees wat die handtekening werklik dek. Die oomblik wanneer 'n sekuriteitsbesluit afhang van data wat buite die handtekening sit, hou dit op om 'n sekuriteitsbesluit te wees en word dit 'n beleefde versoek wat 'n aanvaller vry is om te weier.
Teken die veld waarop jou hek staan, of laat jou hek staan op die veld wat geteken is. Daar is geen derde opsie wat 'n herspeel oorleef nie.
As jy eerder nie SAML-validasie self wil bou en die herspeel-geval verkeerd kry nie, is dit 'n goeie rede om iemand anders dit te laat bestuur. Authagonal koppel herspeel aan die getekende assertion-ID, so om InResponseTo af te stroop lei nêrens heen nie.