Responses inline.

> Still, there is some initial incorrect point that makes the rest of the 
> discussion complicated, and partly wrong.

I believe the key to make the discussion less complicated is to acknowledge 
that there are two separate issues:

1. An attacker can potentially obtain tokens from the legitimate application
2. An attacker can obtain a set of tokens from the AS directly, completely 
independent of any application behavior

Given that the goal is to prevent an attacker from obtaining tokens, scenario 1 
becomes irrelevant when scenario 2 is a possibility. It would be really helpful 
to analyze the SW approach with this in mind. I’ll add comments inline to 
highlight why this matters.

> 
> Specifically, §6.4.2.1 says this: The service worker MUST NOT transmit 
> tokens, authorization codes or PKCE code verifier to the frontend application.
> 
> Wording should be refined, but the idea is that the service worker is to 
> actually restrict authorization codes from even reaching the frontend. Of 
> course, easier said than done, but that part happens to be quite easy to 
> implement. 

This is related to both scenarios. If the SW is running, you can indeed hide 
tokens from the main browsing context, which helps to support scenario 1. For 
scenario 2, you need the guarantee that the SW will intercept all new flows, 
otherwise the attacker  can run a silent flow. As long as the SW is running in 
the main context, I would assume that the attacker can indeed not reach the 
authorization endpoint directly. 

The key part above is “as long as the SW is running”. An attacker with the 
ability to run malicious JS can unregister the SW that prevents the attacker 
from reaching the authorization endpoint. 

I have raised this issue before, and the response back then was that the SW is 
only actually removed after the browsing context reloads, which is true. So 
from the main context, the attacker cannot launch the attack. However, when the 
attacker instantiates a new browsing context (i.e., an iframe), the 
unregistered SW is no longer present, and is thereby not able to restrict 
access to the authorization endpoint. 

I address this concern in the talk I have referenced before. This link with the 
time code included (https://youtu.be/OpFN6gmct8c?feature=shared&t=1973) points 
you to the exact demo scenario, where I illustrate how an unregistered SW 
cannot prevent access to an endpoint in an iframe. Admittedly, I have not 
implemented a full OAuth client as a SW, but the minimal PoC you see here 
suffices to illustrate the ineffectiveness of this approach.

With this information, the attack scenario becomes the following:
The attacker unregisters the SW in the main browsing context, preventing it 
from being used in any new browsing context
The attacker injects a new iframe and points it to the authorization endpoint
The AS responds with a redirect with the authorization code
The attacker detects the redirect, copies the authorization code, and aborts 
the page from loading (so that the authorization code is never exchanged or the 
SW is never reloaded)
The attacker extracts the authorization code and exchanges it for tokens


TL;DR: a SW is not a security mechanism, and the browser cannot guarantee that 
a SW permanently prevents requests to a certain endpoint.


> This has further impact on much of the other statements:
> > The main problem with a browser-only client is that the attacker with 
> > control over the client has the ability to run a silent Authorization Code 
> > flow, which provides them with an independent set of tokens
> [...]
> > The security differences between a BFF and a browser-only app are not about 
> > token storage, but about the attacker being able to run a new flow to 
> > obtain tokens.
> [...]
> > Again, the security benefits of a BFF are not about stoken storage. Even if 
> > you find the perfect storage solution for non-extractable tokens in the 
> > browser, an attacker still controls the client application and can simply 
> > request a new set of tokens. 
> 
> Truth is: no, you can't start a new authentication flow and get the 
> authorization code back in the main thread. I'm talking about the redirection 
> scenario, which I'm the most familiar with, but it would probably apply to 
> the "message" one as well (which is new to me and seems to be ashtoningly 
> legit due to vague "for example" wording in the OAuth2 spec :-) ).

The attack scenario above does not run the redirect scenario in the main 
browsing context, but in an iframe. Opening an iframe instantiates a new nested 
browsing context, where unregistered SWs are not available. 


> The service worker, according to 
> https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerGlobalScope/fetch_event#description
>  , just intercepts the authorization code, gets a token, and never sends it 
> back to the main code.

This point is not relevant, since your SW is no longer active when the 
attacker’s authorization code is being returned. 


> But don't trust me on my words: what about demonstrating our claims with 
> actual code, and as such create a shorter, simpler, but more constructive 
> discussion?

I don’t understand where this remark comes from. I have already demonstrated 
back in January that this approach is not effective, and have referred to the 
recording of this presentation numerous times. I stand by my demonstration of 
the ineffectiveness of SW and encourage you to test this out yourself. It is as 
simple as setting up your SW, unregistering it, and running an authorization 
code flow in an iframe. You’ll see that the request goes through to the AS, and 
that your SW is no longer able to stop it.

> 
> The demonstration in its current form would not lead to a successful 
> compromise of a good implementation of access tokens handled by a service 
> worker.

Once again, I refer back to the start of my mail: it is not about protecting 
existing tokens (scenario 1), it is all about preventing the attacker from 
running a new flow (Scenario 2).


I understand that all of this is quite inconvenient, especially if one is 
heavily invested in running browser-only OAuth clients. Unfortunately, it is 
the nature of web-based applications, and doing so requires a complete picture 
of the security implications. That’s exactly what we are working on with the 
specification.


Kind regards

Philippe


—
Pragmatic Web Security
Security for developers
https://pragmaticwebsecurity.com/
_______________________________________________
OAuth mailing list
OAuth@ietf.org
https://www.ietf.org/mailman/listinfo/oauth

Reply via email to