Again, there is something fundamentally misunderstood here: Philippe's exploit will not work with a correctly implemented service worker. Also not in an iframe. Also not if you unregister it and you start a new iframe.
There is no "need to explain yourself several times" and nobody has "already demonstrated back in January that this approach is not effective", because a correctly implemented service worker can effectively prevent this attack. The attacker cannot "run a new flow" and automate getting a token if the service worker implementation follows the specified guidelines: *§6.4.2.1* * * The application MUST register the Service Worker before running any code interacting with the user.* The redirect URI is registered within your application. If you allow any redirect_uri to be a silent refresh flow (typically in an iframe), you *must* make it synchronously register the service worker as the first action on the page, just as any other part of the application (and stopping that is a whole different attack than XSS). The single-threaded nature of javascript and synchronous loading of scripts will not let any secret leak before it has been loaded (and as an additional counter-measure for half-manual access code leaks, you could add some restriction to remove auth codes from pages before it is loaded). Hence my proposal: instead of a demonstration where you test a possibly incomplete implementation (which, as far as I can see, doesn't have the fine details that make it fool-proof), I propose to deliver a proof-of-contest that would follow these guidelines. Before admitting that "you cannot secure browser-flows only", I'd still want to actually see that you can do this (which isn't the case from the explanation I read this far). This whole story can perfectly be all wrong, but it's work checking first. Let's be pragmatic, right? Le lun. 28 août 2023 à 14:15, Jim Manico <j...@manicode.com> a écrit : > *applause* > > Sucks you need to explain yourself several times but this is very helpful > for the community. > > On Aug 28, 2023, at 7:52 AM, Philippe De Ryck < > phili...@pragmaticwebsecurity.com> wrote: > > 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: > > 1. The attacker unregisters the SW in the main browsing context, > preventing it from being used in any new browsing context > 2. The attacker injects a new iframe and points it to the > authorization endpoint > 3. The AS responds with a redirect with the authorization code > 4. 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) > 5. 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 > > -- Yannick Majoros Valuya sprl
_______________________________________________ OAuth mailing list OAuth@ietf.org https://www.ietf.org/mailman/listinfo/oauth