close
close

Blog – Stapelauthenticatie

Blog – Stapelauthenticatie

Ik wilde een blogpost schrijven voor iedereen die op dezelfde manier leert als ik: door te proberen ze te doorbreken.

Ik begin met een implementatie die enorm gebrekkig is en die een gebruiker toegang geeft tot een app van derden. Vervolgens ga ik deze implementatie continu aanvallen tot we iets hebben gevonden dat enigszins veilig is.

NB: Dit is niet voor jou als je OAuth 2.0 in productie wilt implementeren. Je kunt beter de relevante RFC’s lezen, maar zelfs dan zou ik vragen waarom je het wiel opnieuw probeert uit te vinden.

Trouwens, we bouwen Stack Auth, het open-source Auth0-alternatief. Je kunt meer over ons te weten komen op onze GitHub-repo.

De wereld zonder OAuth

Big Head wil opslagruimte besparen op zijn Hooli Cloud-drive. Hij vindt Pied Piper, een app die belooft zijn bestanden te comprimeren. Maar om Pied Piper zijn magie te laten doen, heeft hij toegang nodig tot zijn Hooli-drive.

De eenvoudigste manier voor Pied Piper om die toegang te krijgen is om Big Head te vragen om zijn Hooli-gebruikersnaam en wachtwoord. Daarmee kan Pied Piper namens hem inloggen op Hooli en toegang krijgen tot zijn bestanden.

Dat zou als volgt gaan:

Big Head geeft zijn Hooli-gebruikersnaam en wachtwoord aan Pied Piper

Het scherm dat Big Head in zijn browser ziet, zou er ongeveer zo uit kunnen zien:

Big Head ziet het Hooli-inlogscherm

Aanval #1: De geloofsbrieven van Big Head worden blootgelegd

Door zijn gebruikersnaam en wachtwoord te geven, geeft Big Head Pied Piper volledige toegang tot zijn hele Hooli-account. Dit omvat Hooli Mail, Hooli Chat en zelfs de mogelijkheid om zijn wachtwoord te wijzigen! Bovendien, als iemand ooit Pied Piper hackt, krijgen ze Big Heads wachtwoord in platte tekst te zien.

Dus komen ze met een nieuw plan: genereer een access token. Dit is een sleutel waarmee Pied Piper toegang krijgt tot Big Head’s data op Hooli met beperkte rechten.

Big Head geeft Pied Piper een toegangstoken

En zo zou het er voor Big Head uitzien:

Big Head ziet het Hooli-toegangstokenscherm

Hoewel deze aanpak veilig is, is het niet bepaald gebruiksvriendelijk. Big Head wil niet elke keer dat hij een bestand comprimeert of inlogt op een service handmatig een toegangstoken genereren. Hij wil dat Pied Piper dat voor hem doet.

Automatisering

In plaats van dat Big Head handmatig toegangstokens genereert en deze naar Pied Piper kopieert, kan Pied Piper Hooli vragen om namens hem toegangstokens te genereren.

Big Head geeft Pied Piper toegang tot zijn Hooli-drive

Dit zou geweldig zijn als er geen slechteriken op deze wereld waren! Big Head hoeft alleen maar op een knop te klikken en alles wordt automatisch gedaan. Maar er is hier een duidelijk probleem.

Aanval #2: Iedereen kan zomaar beweren dat hij iemand anders is

We hebben misschien een probleem

Er is absoluut geen veiligheid in deze aanpak! Pied Piper kan gewoon doen alsof hij namens iemand handelt, en Hooli zal met plezier een toegangstoken genereren.

Om er zeker van te zijn dat het verzoek daadwerkelijk van Big Head komt, moet Hooli hem om bevestiging vragen.

Big Head ziet het Hooli-inlogscherm

In de wijde wereld van het web wordt stap 3 meestal uitgevoerd door Big Head om te leiden naar een pagina op een hooli.com domein. Dus zijn browser zou dit tonen:

Big Head ziet het Hooli-inlogscherm

Hooli kan nu verifiëren dat de persoon die voor de browser zit Big Head is. In stap 3 kan Hooli het bevestigingsproces vrij ontwerpen. Hooli kan Big Head vragen om zijn e-mail/wachtwoord-login te bevestigen, 2FA uit te voeren en/of om toestemming te vragen.

Er een naam aan geven: Impliciete stroom

Vroege implementaties van OAuth zagen er precies zo uit; wij noemen het de impliciete stroomHoewel we nog niet eens halverwege dit bericht zijn, kun je misschien wel raden dat je dit niet in je productie-apps moet gebruiken.

Maar laten we de dingen een naam geven, in overeenstemming met de naam die OAuth eraan geeft:

OAuth impliciete stroom

De queryparameters in de URL zijn:

  • client_id=piedpiper:Hierdoor weet Hooli welke app om toegang vraagt ​​(in dit geval Pied Piper).
  • redirect_uri=https://piedpiper.com/callback: Dit is waar Hooli Big Head naartoe moet sturen nadat hij de verbinding heeft goedgekeurd.
  • scope=drive: De rechten die Pied Piper nodig heeft.
  • response_type=token: Vertelt Hooli dat we de impliciete stroom gebruiken.

Tot zover alles goed!

Aanval #3: Redirect URI-manipulatie

Endframe, een kwaadaardige concurrent van Pied Piper, wil de Hooli-schijfgegevens van Big Head stelen.

  1. Endframe stuurt Big Head een e-mail met als onderwerp: “Koppel je Hooli-account aan Pied Piper”.
    • Ze bevatten een link naar https://hooli.com/authorize?...met dezelfde client_id En scope als een echt verzoek van Pied Piper.
    • Maar ze veranderen de redirect_uri parameter naar https://endframe.com.
  2. Big Head controleert het domein en ziet dat het hooli.comdus hij klikt op de link.
  3. Het Hooli-toestemmingsscherm verschijnt. Big Head bevestigt dat het Pied Pipers client-ID is, dus hij logt in en bevestigt de toegang.
  4. Echter, nadat Big Head op “Toestaan” heeft geklikt, stuurt Hooli hem door naar https://endframe.com in plaats van https://piedpiper.com/callbackwaarbij het toegangstoken naar Endframe wordt verzonden.
  5. Endframe heeft nu toegang tot de Hooli-schijf van Big Head!

Het probleem is dat Hooli niet heeft geverifieerd dat de client_id En redirect_uri overeenkomst.

De oplossing is om Pied Piper te verplichten om eerst alle mogelijke redirect-URI’s te registreren. Vervolgens zou Hooli moeten weigeren om te redirecten naar een ander domein.

Aanval #4: Cross-site request forgery (CSRF)

Er zijn echter nog wat geavanceerdere aanvallen. Endframe kan Big Head nog steeds misleiden om in te loggen met een kwaadaardig Hooli-account:

  1. Endframe registreert een account bij Pied Piper.
  2. Ze loggen in op Pied Piper en genereren een toegangstoken access_token_456 voor hun eigen Hooli-rit.
  3. Ze sturen Big Head een e-mail met de titel “Bekijk ons ​​Bachmanity-fotoalbum” en een link https://piedpiper.com/callback?access_token=access_token_456.
  4. Big Head controleert het domein en ziet dat het piedpiper.comen klikt erop.
  5. De Pied Piper-website opent de callback en logt Big Head in op de Hooli-schijf van Endframe. Alle fukes die hij uploadt, worden dan naar de Hooli-schijf van Endframe gestuurd.

Hoe kunnen we dit voorkomen? We moeten ervoor zorgen dat we de OAuth-flow alleen voltooien als we deze zelf hebben geïnitieerd.

Om dit te doen, kan Pied Piper een willekeurige string genereren (we noemen het state), sla het op in cookies en stuur het naar Hooli. Hooli zal dit dan sturen state terug naar Pied Piper wanneer het Big Head terugstuurt. Pied Piper moet dan controleren of de ontvangen state komt overeen met die in de koekjes.

CSRF-bescherming

  • state=random_string_123: Een willekeurig gegenereerde tekenreeks om CSRF-aanvallen te voorkomen.

Aanval #5: Afluisteren van toegangstokens

Endframe geeft niet op. Ze hebben een ander plan bedacht:

  1. Ze werkten samen met een geniale ontwikkelaar genaamd Jian Yang en creëerden een “Hotdog or not”-tool die hotdogs detecteert. Kwaadaardig genoeg stuurt het ook de volledige browsergeschiedenis naar Endframe.
    • (Er zijn nog een aantal andere history sniffing- of HTTP downgrade-aanvallen die dit ook zouden kunnen doen.)
  2. Big Head vindt het grappig en installeert het.
  3. Endframe ziet nu alle toegangstokens voor alle services waarmee Big Head ooit is ingelogd, door te zoeken naar URL’s die eruitzien als https://piedpiper.com/callback?access_token=access_token_123.

Er is een oplossing voor. We moeten ervoor zorgen dat toegangstokens nooit worden uitgewisseld in browser-URL’s.

Hooli genereert een kortstondige “autorisatiecode” en stuurt deze terug naar Pied Piper met deze code. Pied Piper doet vervolgens een POST-aanvraag naar een ander eindpunt, waardoor de autorisatiecode ongeldig wordt en wordt ingewisseld voor het toegangstoken.

Op deze manier komt het toegangstoken nooit in de browsergeschiedenis terecht. We noemen dit de autorisatiecode flow. Het is veiliger dan de impliciete flow, maar we zijn er nog niet.

Autorisatiecodestroom

  • response_type=code: Vertelt Hooli dat we de autorisatiecodestroom gebruiken in plaats van de impliciete stroom.
  • code=authorization_code_123: De autorisatiecode die Hooli voor Pied Piper heeft gegenereerd.
  • grant_type=authorization_code: Voor de autorisatiecodestroom is dit altijd authorization_code (de andere soorten subsidies worden niet besproken).

Is dit veilig? Niet helemaal…

Aanval #6: Afluisteren van autorisatiecodes

Als Endframe de autorisatiecode in real-time afluistert, kunnen ze deze razendsnel inwisselen voor een toegangstoken, nog voordat de browser van Big Head dat doet.

  1. Big Head heeft nog steeds de tool “Hotdog or not” geïnstalleerd.
  2. Zodra Big Head verbinding maakt met zijn Hooli Drive-account, haalt “Hotdog or not” de autorisatiecode op uit de browsergeschiedenis van Big Head.
  3. In realtime, sneller dan Big Heads browser het verzoek kan versturen, duikt Endframe op en stuurt een verzoek naar Hooli met Big Heads autorisatiecode. Ze krijgen het toegangstoken en Big Heads verzoek mislukt.

Momenteel kan iedereen met de autorisatiecode deze inwisselen voor een toegangstoken. We moeten ervoor zorgen dat alleen de persoon die de aanvraag heeft geïnitieerd, de uitwisseling kan uitvoeren.

We doen dit door een geheim veilig op te slaan op de client. We hashen dit geheim en sturen het samen met het allereerste verzoek naar Hooli. Bij het uitwisselen van de autorisatiecode voor de toegangstoken sturen we het originele geheim naar Hooli. Hooli vergelijkt vervolgens de hashes en bewijst dat het verzoek van dezelfde client komt.

Deze procedure heet bewijssleutel voor code-uitwisseling (PKCE).

PKCE-stroom

  • code_verifier=random_string_456: De originele willekeurige reeks die Pied Piper naar Hooli stuurde.
  • code_challenge=hashed_string_123: De verificator van de gehashte code.

Aanval #7: Redirect URI-manipulatie op vertrouwde URI’s

Stel je voor dat Pied Piper twee geregistreerde omleidings-URI’s heeft:

  • https://piedpiper.com/callback
  • https://piedpiper.com/share-files-callback

De eerste autoriseert en comprimeert Hooli-schijfbestanden, en de tweede deelt bestanden openbaar met andere gebruikers. (Dit kan ook hetzelfde eindpunt zijn met andere queryparameters.)

Ook al beschermen we Endframe tegen het vervangen van de redirect-URI door iets totaal kwaadaardigs (zoals https://endframe.com), als Endframe het verzoek op een of andere manier kan onderscheppen, kunnen ze de URI nog steeds aanpassen zodat deze naar het andere eindpunt verwijst.

De oplossing? Laat de client de huidige URI opnieuw verzenden bij het uitwisselen van de autorisatiecode voor het toegangstoken. Hooli kan dan verifiëren of de redirect-URI overeenkomt met die in het oorspronkelijke verzoek.

Big Head ziet het Hooli-inlogscherm

De laatste stroom

Gefeliciteerd, we zijn aangekomen bij de OAuth 2.0-autorisatiecodestroom met PKCE, wat tegenwoordig de geaccepteerde standaardmanier is om authenticatie door derden in browsers uit te voeren.

PKCE-stroom

Beschrijving weergeven
  1. Big Head klikt op de knop “Verbind met Hooli-station” op de website van Pied Piper.
  2. Pied Piper leidt Big Head om naar het OAuth-autorisatie-eindpunt van de Hooli-website https://hooli.com/authorize met de volgende parameters:
    • client_id=piedpiper:Hierdoor weet Hooli welke app om toegang vraagt ​​(in dit geval Pied Piper).
    • redirect_uri=https://piedpiper.com/callback: Dit is waar Hooli Big Head naartoe moet sturen nadat hij de verbinding heeft goedgekeurd.
    • scope=drive: De rechten die Pied Piper nodig heeft.
    • response_type=code: Dit geeft aan dat we een autorisatiecode willen.
    • state=random_string_123: Een willekeurige tekenreeks om CSRF-aanvallen te voorkomen.
  3. Hooli controleert of de redirect_uri is geregistreerd bij de client_idZo niet, dan wijst Hooli het verzoek af.
  4. Hooli toont Big Head een inlogscherm.
  5. Big Head logt in op zijn Hooli-account en bevestigt dat hij Pied Piper toegang wil geven tot zijn Hooli-schijf.
  6. Hooli leidt Big Head terug naar de Pied Piper callback-URL https://piedpiper.com/callback met de volgende parameters:
    • code=authorization_code_123: De autorisatiecode die Hooli voor Pied Piper heeft gegenereerd.
    • state=random_string_123: De willekeurige reeks die Pied Piper naar Hooli stuurde.
  7. Pied Piper controleert of de state overeenkomt met degene die ze hebben verzonden. Als dat niet het geval is, wijst Pied Piper het verzoek af.
  8. Pied Piper gebruikt JavaScript om een ​​POST-verzoek te doen aan het Hooli-token-eindpunt https://hooli.com/token met de volgende parameters:
    • client_id=piedpiper: De client-ID die Pied Piper bij Hooli heeft geregistreerd.
    • code=authorization_code_123: De autorisatiecode die Hooli voor Pied Piper heeft gegenereerd.
    • grant_type=authorization_code: Geeft aan dat dit een type autorisatiecodetoekenning is (de andere toekenningstypen worden hier niet behandeld).
    • redirect_uri=https://piedpiper.com/callback: De redirect-URI die Pied Piper in het oorspronkelijke verzoek gebruikte.
  9. Hooli genereert een toegangstoken en retourneert dit aan Pied Piper in de antwoordtekst:
    • access_token=access_token_123: Het toegangstoken dat Hooli genereerde voor Pied Piper om toegang te krijgen tot de Hooli-schijf van Big Head.
  10. Pied Piper gebruikt de toegangstoken om toegang te krijgen tot de API van Hooli https://hooli.com/drive met een autorisatieheader zoals Authorization: Bearer access_token_123.

Enkele afsluitende opmerkingen

Dit is een informele uitleg van de OAuth-flow en de daadwerkelijke specificatie is veel langer. Bijvoorbeeld, client secrets, refresh tokens, client credentials flow, token grants, etc., worden hier niet behandeld.

Verder zijn er een hoop details nodig voor een veilige implementatie. Je zou waarschijnlijk niet je eigen OAuth-client moeten implementeren.

Als u dieper wilt ingaan op de materie of OAuth in uw apps wilt implementeren, vindt u hier een aantal goede bronnen.