Right Philippe - there really is no way to create a secure client as a web app. You would need access to the trusted execution environment, which is not available.
..tom On Sat, Aug 26, 2023 at 5:21 AM Philippe De Ryck < phili...@pragmaticwebsecurity.com> wrote: > My responses inline. > > > Hi everyone, > > The document is about "OAuth 2.0 for Browser-Based Apps". Its abstract > further explains that it "details the security considerations and best > practices that must be taken into account when developing browser-based > applications that use OAuth 2.0.". > > As such, detailing security considerations is important. I share the point > of view that basing web applications on proven concepts is important. The > approaches detailed in the document have all their advantages > and disadvantages. > > > We have discussed the topic of browser-based apps in depth at the OAuth > Security Workshop last week. I am also working with Aaron Parecki on > updating the specification to more accurately reflect these advantages and > disadvantages. Updates will go out in the coming days/weeks, so we more > than welcome concrete feedback on the content there. > > There are 2 main approaches to browser-based applications security. One of > them is to store security credentials at the frontend. The other one is to > use cookies and a BFF. Though common practice, there is nothing > fundamentally more secure about them in a demonstrable way. Different > approaches, different characteristics and security assumptions. Nobody can > prove that either approach is better, just that there are different > concerns. > > Handling security in BFFs relies on cookies that cannot be read by the > javascript application. This mechanism provides some reliable protection > about the cookie itself that is used as a kind of credential to access > confidential web resources. It obviously demands some additional layers in > the flow (proxy or light server). You also need a mechanism to share > session information, either at the server side, or for example by having > the cookie itself hold that information. A bigger concern to me is that you > basically give up standard mechanisms for securing the flow between the > frontend and the backend: the security between the two is a custom solution > (based on cookies, in a specific, custom way, this part being in no way > OAuth or standard). This solves the problem by not using OAuth at all in > the browser part of the application, basically making the client > application purely backend. However, the fact that browser-based > applications cannot be secured with OAuth isn't universally true, and > strongly depends on one's definition of "secure", and basically comes down > to what the security issue is. > > > The updated specification will clearly outline the security considerations > when making the browser-based application a public OAuth client. > > *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.* These > tokens give the attacker long-term and unrestricted access in the name of > the user. A BFF-based architecture does not suffer from this issue, since > the OAuth client is a confidential client. Regardless of one’s definition > of “secure”, this is a clear difference on the achievable level of > security. > > Of course, as stated multiple times before, the use of a BFF does not > eliminate the presence of the malicious JS, nor does it solve all abuse > scenarios. > > > > Storing tokens at the frontend has advantages: it solves my concern above > about a standard based flow between the frontend and the backend. > > > The use of cookies is a core building block of the web, and is quite > standard. > > It's simpler from an operational point of view. And it's been used in the > wild for ages. > > > Anyone using a browser-only client should be informed about the clear and > significant dangers of this approach, which the updated specification will > do. > > > Both flows have been compromised numerous times. This doesn't mean they > are not right by design, but that the specific security concerns have to be > addressed. > > > If you have specific security concerns about a BFF, I’d suggest raising > them. Until now, I have only seen arguments that highlight the additional > effort it takes to implement a BFF, but nothing to undermine its security. > Plenty of highly sensitive applications in the healthcare and financial > industry opt for a BFF for its improved security properties and consider > this trade-off to be favorable. > > > Now, the concerns we are really discussing is, what happens in case of XSS > or any form of malicious javascript. > > In this case, for all known flows, session riding is the first real issue. > Whether the injected code calls protected web resources through the BFF or > using the stored tokens, is irrelevant: the evil is done. Seeing different > threat levels between token abuse and session riding is a logical shortcut: > in many cases, the impact will be exactly the same. > > > Stating that using stolen tokens is the same as sending requests through a > compromised client in the user’s browser (client hijacking) is > categorically false. Here are two concrete differences: > > > - Stolen refresh tokens give an attacker long-term access in the name > of the user. Client hijacking only works as long as the user’s browser is > online and the client is effectively running. > - Stolen access tokens give an attacker unfettered access to any > resource server that accepts it. Client hijacking forces the attacker to > play by the rules of the client. For example, an attacker can abuse a > stolen token with fake origin headers to access a resource server that > would accept the token, but has a CORS policy that rejects requests from > the client’s origin > > > As stated before, the DPoP specification takes a similar point of view on > these consequences. They explicitly aim to prevent the abuse of stolen > tokens, while considering client hijacking to be out of scope ( > https://datatracker.ietf.org/doc/html/draft-ietf-oauth-dpop#name-objectives > ) > > > On a sidenote, the term “session riding” seems to refer to CSRF, not to > client hijacking. I have only learned this myself recently and have > mis-used this term before as well. I wanted to point this out to avoid > further confusion. > > > > Reducing the attack surface with a BFF or even a simple proxy is a > possible but separate topic: this doesn't have to be linked to where tokens > are stored. Alternatively, services that shouldn't be accessible could > simply not be exposed, and token scope and audience must be well thought. > > As such, BFFs as well as frontend token storage, though different, are > application design choices and have no demonstrable superiority from a > security point of view. > > > *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.* > > You also talk about “demonstrable” differences. I have shown examples > (both in text and video) of these consequences in browser-only apps, > resulting in the attacker obtaining both an access token and a refresh > token. If you claim that BFFs are just the same, I invite you to > demonstrate your point of view. > > > Still, it seems it matters to some people to not exfiltrate tokens in case > of successful XSS. In the first instance, I don't share this need to > protect short-lived tokens in a game over scenario, but the whole > investigation of more secure frontend storage mechanisms started because > some customers are concerned. We are in the realm of choice, not of > provable security need, but it is still important to them. > > Documenting security concerns and possible solutions is part of the > document. Where you store the tokens has an impact on how easy it will be > for an attacker to exfiltrate them. Local or session storage is obviously > not the best choice here, as injected javascript can easily access it. > > > 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. > > This link points to the exact demo scenario in the video I have referenced > before: https://youtu.be/OpFN6gmct8c?feature=shared&t=1366 It clearly > shows how the attacker runs a new flow to obtain tokens, without ever > touching the application’s tokens. > > > A service worker is an interesting place to store them, as it can > additionally play the role of a front-end proxy that both holds the token > securely, and securely proxy requests to the resource server. Besides, a > track was started with Rifaat to initiate changes to the service worker > specifications to make some things simpler. > > The point that the service worker solution isn't that widespread is indeed > correct and should be addressed. I propose transparently mentioning that it > is seen as a possible but uncommon storage mechanism. There should also be > some explanation about other kinds of web workers, which are more > commonly used but exploitable, so less secure when token exfiltration is a > concern. The document isn't only about security best practices, though, but > about security concerns. Implementations are explicitly out of scope. > > > Using a SW for storage does not solve anything, since the attacker can > simply request fresh tokens. > > > My conclusion is that, though we can surely make the document better, > there is no all-encompassing solution. Similarly, BFFs are not > a higher level of security for healthcare of banks, just a different > solution. Service workers are still an interesting solution for people who > absolutely want to secure tokens at the frontend, and as improvable as > the document is, shouldn't be left out. > > > You, as the creator of the SW approach, have clearly stated that you don’t > even use it in practice, so I don’t really understand the urge to make this > a recommended pattern. On the contrary, BFFs are used in practice in a > variety of scenarios. > > That said, the SW approach should indeed be mentioned in the document, to > clearly illustrate the security considerations and limitations. > > > > > About some specific concerns: > > *While content injection attacks are still possible, the BFF limits the > attacker’s ability to abuse APIs by constraining access through a > well-defined interface to the backend which eliminates the possibility of > arbitrary API calls.* > Session riding is still the main issue and isn't addressed at all. If the > intention here was to limit the number of exposed endpoints, the > application can still be designed to either only expose what is needed, or > put a proxy or api manager between for limiting exposition, unrelated to > where token storage happen. > > > No-one has ever stated that a BFF would solve the consequences of an > attacker hijacking a client. However, when the attacker is forced to launch > attacks through a client running in the user’s browser, they are forced to > go through the BFF. That gives you a point of control which you *could* use > to implement restrictions. This is not required to benefit from a BFF, > since the main benefit is moving from a public client to a confidential > client. > > You state that you can achieve the same by using a careful design of the > application. However, you fail to mention what you consider the > “application” and where exactly this restriction fits in. This is > important, because once the attacker has exfiltrated access tokens, they > can send arbitrary requests. If the resource servers are not fully shielded > by an API manager, the attacker can contact them directly with a stolen > token. And if you apply this close to the resource servers, how will you > then configure them to only allow certain clients to access certain > endpoints? > > > *> No, because running a silent flow in an iframe typically uses a web > message response. In essence, the callback is not the redirect URI, but a > minimal JS page that sends the code to the main application context using > the web messaging mechanism. The message will have the origin of the > authorization server as a sender. * > The iframe needs to get the auth code somehow, and that typically happens > by setting its src to the auth endpoint, and having a redirect URI that > points to that minimal js page. This would mean an attacker can change the > redirect URI to be able to point to some custom js in the application, > which is a whole different > > Philippe, I'm honestly quite skeptical about that attack, but it sounds > interesting. Can you provide some details or a reproducer? > > > In all honesty, my understanding that the Web Messaging approach was > universally used turned out to be inaccurate. There are two concrete ways > to run a silent authorization code flow: (1) using > response_mode=web_message and (2) using the proper redirect URI. Both > scenarios allow the attacker to obtain the authorization code by starting > the flow with an authorization request that *is indistinguishable* from a > request coming from the legitimate application. > > *Scenario 1 (web messaging)* > > > - The iframe src points to the authorize endpoint > - The AS does not redirect, but responds with an HTML page containing > JS code. This JS code uses postmessage to send a message containing the > authorization code to the main application context. > - The attacker receives this message and obtains the authorization code > > > This approach is used by Auth0 and Apple. I have tested my attack scenario > against Auth0. Note that while this flow *does not use* the redirect URI, > it does validate the provided redirect URI. Additionally, the admin needs > to configure the AS to include the client’s origin in a list of “Allowed > Web Origins”. > > This is also the scenario I use in the demo I have linked to above, so you > can see it in action there. > > > *Scenario 2 (redirect)* > > > - The iframe src points to the authorize endpoint > - The AS redirects the frame to the application’s callback with the > authorization code as a query parameter > - The attacker can monitor the iframe for a URL that contains the > authorization code, stop the frame from loading (and redeeming the > authorization code), and extract the code > > > This approach is more universal, but just as vulnerable. The scenario is > exactly the same as in the demo linked to above, but the attack code looks > slightly different. > > > > To conclude, I have carefully argued my point of view on this mailing > list, in recorded videos, and in the sessions at the OAuth Security > Workshop last week. As far as I can tell, the experts in the community > acknowledge the dangers of browser-only apps (i.e., the attacker running a > silent flow) and agree that the browser-based apps BCP should accurately > reflect this information. We’re currently working on updating the > specification (which will happen in multiple steps, so we ask for a bit of > patience). > > Unless you have anything new to add or any new issues to raise, I > respectfully opt to disengage from further discussion. > > Kind regards > > Philippe > > _______________________________________________ > OAuth mailing list > OAuth@ietf.org > https://www.ietf.org/mailman/listinfo/oauth >
_______________________________________________ OAuth mailing list OAuth@ietf.org https://www.ietf.org/mailman/listinfo/oauth