Security Architectures & Security Protocols – Working with Software Development Teams (ISVs and in-house) • Co-Creator of IdentityServer & IdentityModel OSS Project – Certified OpenID Connect & OAuth 2.0 Implementation for .NET – https://identityserver.io • Co-Creator of PolicyServer – Authorization for modern Applications – https://policyserver.io email [email protected] blog https://leastprivilege.com twitter @leastprivilege slides https://speakerdeck.com/leastprivilege
Authorization Server 1 2 • rogue client or RS registered with legit AS • trick legit client to trust rogue AS • trick user in using rogue client or RS • manipulation of network messages
1 2 can read, but not modify, the contents of the authorization request or response • open redirector vulnerabilities • client or AS • redirect interception on mobile devices • leakage • browser history • proxies • log files
a workaround in 2012 to overcome cross-origin AJAX limitations – solved now with CORS • Error prone – tokens are transmitted via URLs and can leak easily • log files • browser history • referrer headers • implementation errors • proxies – no solution for token injection attacks (without adding OpenID Connect)
to client – increased attack surface – credentials can leak in more places than just the authorization server – users are trained to type in credentials in multiple places • more prone to phishing attacks • Incompatible with modern authentication flows – FIDO – 2FA – federation
– can easily leak (configuration management, network traces, proxies…) – should have high entropy (e.g. GUIDs, RNGs) – should be stored non-reversible on authorization server • Asymmetric keys – no need to store any secret on authorization server – secret does not get transmitted over a network – provides key material for sender constraining – signed JWTs and/or Mutual TLS
• e.g. sub-domain takeover – https://somesite.com/* • find a page with an open redirector • find a page where attacker can inject content GET /authorize?response_type=code&client_id=s6BhdRkqt3&state=9ad67f13 &redirect_uri=https://somesite.com/some_endoint
on client or authorization server <html> <body> <img src='https://evil.com/image.png' /> </body> </html> GET /some_endpoint?code=xyz GET https://evil.com/image.png Referrer: https://myapp.com/cb?code=xyz
redirect URIs • Beware of open redirectors • Callback pages should not contain third-party resources – use Content Security Policy for lock-down • Always use PKCE • Use state parameter to bind request to user-agent • Immediately invalidate state after usage • Immediately invalidate authorization codes after usage • Use rel="noreferrer" and referrer policies
AS (H-AS) 1. User selects H-AS 6. Client still assumes that A-AS was used and sends code and client secret to A-AS 2. Attacker intercepts request, and changes to A-AS 3. Client stores A-AS selection in user session 4. Attacker changes HTTP response to point to H-AS 5. User authenticates with H-AS – redirects back /login?p=H-AS /login?p=A-AS A-AS 302 A-AS 302 H-AS /cb?code=xyz code + secret 1 2 3 4 5 6 7. Attacker can redeem code 7
AS (H-AS) 1. User selects A-AS 5. Client sends H-AS code and client secret to A-AS 3. A-AS changes client ID and redirect URI and forwards to H-AS 4. User authenticates with H-AS – redirects back /login?p=A-AS A-AS 302 A-AS /cb?code=xyz code + secret 2. Clients sends user to A-AS to authenticate 1 2 3 4 5
exact redirect URI matching 2. Store for each authorization request the intended AS 3. Compare the intended AS with the actual redirect URI where the authorization response was received
Each external provider is represented by an authentication handler – with a unique name + unique callback endpoint GET /authorize?client_id=mvc&redirect_uri=https://myapp.com/signin-as1 &state=protected(correlationId + other_data) set cookie: correlation.as1.correlationId Challenge (name = as1) Callback GET /signin-as1?code=xyz&state=protected(correlationId + other_data) read cookie: correlation.as1.correlationId
mapping of client ID to client instance – public clients cannot store secrets (and thus don’t use them) • IOW no way to authenticate a public client • there are exceptions for certain environments (e.g. trusted hardware) • Native desktop/mobile applications • Browser-based appplications (aka SPAs)
web view • private browser & private cookie container – system browser** • e.g. ASAuthenticationSession, Chrome Custom Tabs, or desktop browser • full featured including address bar & add-ins • shared cookie container • Handling the callback – event handling – custom URI schemes – local HTTP listener – "claimed" HTTPS URIs** ** most recommended
client type from a security point of view – but also most popular client type • Unique attacks due to "shared execution environment" nature of browser – Cross-Site Request Forgery (CSRF) – Cross-Site Scripting (XSS) • Two fundamental ways to do API authentication in SPAs – implicit credential that browser sends automatically • cookies, Integrated Windows authentication (Kerberos), X509 client certificates – explicit credential that must be sent from application code • access tokens
stores & manages tokens • proxies cross-domain calls • Browser • stores no tokens • uses cookies JavaScript Applications with a Backend JavaScript Applications without a Backend • Browser • initiates flow • store & manages tokens • makes all API calls • use no cookies
data storage mechanism in browsers – session storage, local storage, in-memory… – prone to XSS-based attacks • potential exfiltration of tokens • origin-isolation of storage mechanism might help • Content Security Policy (CSP) highly recommend – but not always easy – strict dynamic support not widely deployed yet
tokens even more dangerous when stored in browser – MUST rotate refresh tokens on each use, in order to be able to detect a stolen refresh token if one is replayed – SHOULD detect replay of refresh tokens – MUST either set a maximum lifetime on refresh tokens OR expire if the refresh token has not been used within some amount of time • …or no refresh tokens at all – "silent renew" is a session-bound mechanism to request new access tokens – becomes more and more problematic with browser default settings
move into more specialized and high security/risk scenarios – financial, health care… • Formal analysis shows more potential attack vectors – https://arxiv.org/abs/1901.11520 • Additonal specs are being created to mitigate those attacks – JWT secured authorization requests, rich/pushed authorization requests (RAR/PAR), OAuth.xyz
a developer) – compromise of infrastructure • Some threats are easy to mitigate – CSRF, injection attacks, open redirectors... • Some threats are hard to mitigate – complex setups that specifically target an application • Know your threat/attacker model – implement the mitigations that affect you