Hello everyone,

I'd like to contribute to the ongoing discussion by sharing my insights.
Giving some feedback has been on my list for a long time, but hasn't been
feasible for me due to time constraints, as I'm sure all of you have. I'm
taking some time to give my two cents.

First, some context. I started getting more involved with this while
working for one of my customers (a government organization), documenting
and architecturing the way forward for using OAuth2 and OIDC in our
frontend applications. There were some debates about what would be
acceptable for us and that we could consider secure. Besides the
specifications, there were various claims besides the specifications with
varying degrees of research and documentation. Some of them are quite
opinionated or commercially motivated. "Common sense" statements without
demonstration, made the debate difficult. One such claim is about BFFs
being more secure because they are backed by unstealable session cookies.

After some discussions, among which with Aaron, I decided to investigate
possible solutions to the "what if my frontend is compromised by an XSS
attack and I still want my token to not leak" problem. One such solution
for which I wrote some proof-of-concept and ported a few applications at
the time was with a Service Worker, for which I had some early
implementation here: https://github.com/Valuya/servicewauther .

It's worth noting that it didn't get so much traction up to this time, and
that I stopped using it in multiple applications myself. Not because it's
not a worthwhile pattern to solve the mentioned problem, but because token
leak is typically not the real issue. XSS is the first one to solve, and I
disagree it's unavoidable (and certainly at any level: extra care for
application start code can get you very far). Next comes probably session
riding: you need to restrict your attack surface as much as possible and
scope what users can access to what the application actually needs. This
problem is similar for any XSS exploit, whatever implementation is chosen
(BFF, session storage, service worker...), and lowers the priority of
token exfiltration.

Regarding the demonstration in the video, I don't think it would compromise
my current implementation.

The current draft says this in §6.4.2.1:
** The application MUST register the Service Worker before running any code
interacting with the user.*

This adds an important constraint: an attacker would not only need to
compromise any part of the application, but should also make sure the very
first thing it does (registering the service worker) is also compromised,
which is much harder.

Step by step, the code I saw would:
- open an iframe
- redirect to the authorization server
- get redirected to the registered redirect_uri (which is an additional
important constraint here)
- register the service worker to run immediately
... which would stop the attack here, the main application not even seeing
the auth code and not being able to call the /token endpoint

BFFs are not a proven better level of protection. Session riding in case of
XSS is still the same. They also have debatable points: you either need
some third party or custom software (with their own threat to security),
and in the current state of knowledge, they rather give a false sense of
security. Complexity of implementation is another point, outside of
security.

My personal conclusion is that the root issue isn't token exfiltration, XSS
or session riding, but that the real danger comes from authentication
itself. There are some flows with PROs and CONS, and we have to live with
them, accepting the risks and finding the best mitigations. The fact that
there are different point of views here is a good thing, and I think this
will help us document strengths and weaknesses of the different solutions.

Yannick

Le dim. 13 août 2023 à 08:22, Philippe De Ryck <
phili...@pragmaticwebsecurity.com> a écrit :

>
> I have a different interpretation of the objective of using a service
> worker, and it aligns with descriptions in most of those links -- minimize
> the risk of the access token and refresh token exfiltration from the
> application by malicious JS code.  Service workers, when implemented
> properly, isolate the access token, refresh token, PKCE from code in the
> DOM, similar to how properly created cookies are isolated from the DOM JS.
>
> This lowers the security risk of using OAuth to protect a server's
> resources to be similar to the risks of using cookies.  I think this is an
> improvement in the security of the application, and does not create a false
> sense of security as you claim.
>
>
> It is not just the use of a service worker that matters, it is the way the
> service worker is deployed. The examples you gave earlier all use a service
> worker to attach a token to an outgoing request. They still obtain the
> token from the main application (see [1] at the bottom), so tokens are
> still exposed to the main application. So if the goal is to prevent token
> exfiltration from the main app, this setup is not effective. The attacker
> could just run a new flow in an iframe, obtain fresh tokens and exfiltrate
> them.
>
> The proposal of using service workers in this draft aims to provide this
> security by also shielding the authorization code and token exchange. I
> have not seen a practical implementation of this pattern. Furthermore, even
> if you implement this, an attacker with XSS capabilities can still
> unregister the worker and then obtain tokens to exfiltrate.
>
>
> If an attacker has the ability to run malicious JS code in the
> application's origin, the attacker can do anything against the underlying
> web resources regardless of using OAuth or cookies.
>
> Do you have an alternative approach to isolating the OAuth credentials
> from the DOM code?
>
>
> Yes, that is exactly why it is not possible to prevent token exfiltration
> when malicious JS runs. The BFF pattern as described in this document
> reduces the impact to its minimum level: a session riding attack. In that
> scenario, the attacker will never be able to obtain access/refresh tokens,
> and can only “tunnel” requests through the user’s online browser. That’s
> also why I always recommend to focus on defending against malicious JS
> instead of just trying to hide tokens. However, history shows that even
> with the best efforts, malicious JS will eventually end up in the
> application.
>
> Unfortunately, the spec in its current from argues that techniques like
> refresh token rotation or the service worker help prevent abuse in case of
> token exfiltration. Since these techniques can (easily) be circumvented,
> they create a false sense of security. I clearly demonstrate this in the
> video I referenced earlier (https://www.youtube.com/watch?v=OpFN6gmct8c),
> as well as in this older post (
> https://mailarchive.ietf.org/arch/msg/oauth/s68mcQCC1NNe_Y2Q9Qu6x0VuLrI/).
> Note that this post is more than 3 years old, so my insights and way of
> explaining has changed since then.
>
>
> FWIW: If you want someone to understand previous posts, I'd suggest
> providing a link to the post, and even better also include a small extract.
> Also, while it is more effort on your part, I find concise, crisp responses
> more constructive for email dialog, and similarly, don't expect that the
> email list has, or will, take the time to watch your video. Have you
> watched any of mine?
>
>
> I fully understand that watching a video is not the most straightforward
> way of consuming content, but in this case, the video adds a tremendous
> amount of value. It allows me to use graphics to explain the issues, and it
> includes actual demo attacks to obtain tokens, even with recommended
> security mechanisms in place. If you would be arguing a point and refer to
> a video that clearly explains your thoughts, I would definitely watch it.
>
>
>
>
>
>
> [1]
>
> A quick Google on oauth service workers returned a number of articles and
>> descriptions of using service workers:
>>
>> https://github.com/ForgeRock/appAuthHelper/blob/master/service_workers.md
>>
>>
> No mention of how tokens end up in the worker. A brief look at the code
> mentions frames and seems to refer to the AppAuth library, so this does not
> seem to happen in the worker.
>
>
>> https://gaurav-techgeek.medium.com/re-architecting-authentication-with-service-workers-ff8fbbbfbdeb
>>
>>
> The tokens are obtained from the main application. See the section "Now
> let us get the right token."
>
> https://itnext.io/using-service-worker-as-an-auth-relay-5abc402878dd
>>
>>
> The tokens are obtained from the main application. I quote: 
> *getAuthTokenHeader
> method will communicate with js executed in a page to get current token *
>
> https://about.grabyo.com/service-workers-jwt-tokens/
>>
>>
> No mention of how tokens end up in the worker.
>
> _______________________________________________
> 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

Reply via email to