My last comment was rather ironic: user-facing applications are dangerous (security is hard, which I say nothing with), and that is true for any scheme.. BFFs are not any safer, XSS or any successful malicious javascript execution has the same end effect (=game over, complete compromise of authenticated calls), and there was still no factual demonstration of multiple levels of security here. See my detailed explanations.
Le lun. 28 août 2023 à 11:35, Steinar Noem <stei...@udelt.no> a écrit : > I think this is a great discussion, and it seems to me that Yannicks last > comment is basically what Phillippe is trying to point out.. > I just wanted to remind the authors about a couple of things that we > briefly discussed during OSW in London. > > Although it might not be directly relevant for this discussion I do think > that it might be a good idea that the spec mentions that: > > - The level of security you require for any client is often a > reflection of the sensitivity of the information that the API exposes. You > will have different requirements for confidential information than for open > data. An example of a similar recommendation can be found in the HTTP > Semantics specification: https://httpwg.org/specs/rfc9110.html#GET > - In my domain it is most often the owner of the API (the data > controller) who defines and approves the level of security which it finds > to fit their responsibilities (e.g. legal obligations) - although in some > cases it might be both the data provider and the data consumer. Meaning - > this BCP might be equally important for the API-owner as it is to the > client developer. > - I think this discussion shows that any mitigation on the browser > side will only raise the bar for the attacker, and can never be a fully > effective countermeasure. I think this point could be even more clearly > stated early in the spec, and that both the API-owner or client owner > should be aware of this risk, and select their appropriate choice of > security measures based on a risk assessment. In some cases their > conclusion might be that a browser based app is not secure enough for > their responsibilities. > > > S > > søn. 27. aug. 2023 kl. 18:41 skrev Yannick Majoros <yann...@valuya.be>: > >> Yes, but this is true for all flows. Web applications are dangerous. >> Applications handling user input are dangerous too. >> >> Le dim. 27 août 2023, 17:46, Tom Jones <thomasclinganjo...@gmail.com> a >> écrit : >> >>> You can write your code as strong as you wish. You cannot determine if >>> the code running in the computer is that code running unaltered. ..tom >>> >>> >>> On Sun, Aug 27, 2023 at 5:25 AM Yannick Majoros <yann...@valuya.be> >>> wrote: >>> >>>> Thanks for taking the time to respond and for the constructive feedback. >>>> >>>> Still, there is some initial incorrect point that makes the rest of the >>>> discussion complicated, and partly wrong. >>>> >>>> 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 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 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. >>>> >>>> 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? >>>> >>>> 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. >>>> >>>> Yannick >>>> >>>> >>>> Le sam. 26 août 2023 à 14:20, Philippe De Ryck < >>>> phili...@pragmaticwebsecurity.com> a écrit : >>>> >>>>> 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 >>>>> >>>>> >>>> >>>> -- >>>> Yannick Majoros >>>> Valuya sprl >>>> >>>> _______________________________________________ >>>> 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 >> > > > -- > Vennlig hilsen > > Steinar Noem > Partner Udelt AS > Systemutvikler > > | stei...@udelt.no | h...@udelt.no | +47 955 21 620 | www.udelt.no | > -- Yannick Majoros Valuya sprl
_______________________________________________ OAuth mailing list OAuth@ietf.org https://www.ietf.org/mailman/listinfo/oauth