On 8 Dec 2020, at 22:47, Brian Campbell
<bcampb...@pingidentity.com <mailto:bcampb...@pingidentity.com>>
wrote:
Danial recently added some text to the working copy of the draft
with https://github.com/danielfett/draft-dpop/commit/f4b42058
<https://github.com/danielfett/draft-dpop/commit/f4b42058> that I
think aims to better convey the "nutshell: XSS = Game over"
sentiment and maybe dissuade folks from looking to DPoP as a
cure-all for browser based applications. Admittedly a lot of the
initial impetus behind producing the draft in the first place was
born out of discussions around browser based apps. But it's
neither specific to browser based apps nor a panacea for them. I
hope the language in the document and how it's recently been
presented is reflective of that reality.
The more specific discussions/recommendations around in-browser
apps are valuable (if somewhat over my head) but might be more
appropriate in the OAuth 2.0 for Browser-Based Apps
<https://datatracker.ietf.org/doc/draft-ietf-oauth-browser-based-apps/>
draft.
With respect to the contents of the DPoP draft, I am still keen
to try and flush out some consensus around the question posed in
the start of this thread, which is effectively whether or not to
include a hash of the access token in the proof. Acknowledging
that "XSS = Game over" does sort of evoke a tendency to not even
bother with such incremental protections (what I've tried to
humorously coin as "XSS Nihilism" with no success). And as such,
I do think that leaving it how it is (no AT hash in the proof) is
not unreasonable. But, as Filip previously articulated, including
the AT hash in the proof would prevent potentially prolonged
access to protected resources even when the victim is offline.
And that seems maybe worthwhile to have in the protocol, given
that it's not a huge change to the spec. But it's a trade-off
either way and I'm personally on the fence about it.
Including an RT hash in the proof seems more niche. Best I can
tell, it would guard against prolonged offline access to
protected resources when access tokens are bearer and the RT was
DPoP-bound and also gets rotated. The trade-off there seems less
worth it (I think an RT hash would be more awkward in the
protocol too).
On Fri, Dec 4, 2020 at 5:40 AM Philippe De Ryck
<phili...@pragmaticwebsecurity.com
<mailto:phili...@pragmaticwebsecurity.com>> wrote:
The suggestion to use a web worker to ensure that proofs
cannot be pre-computed is a good one I think. (You could
also use a sandboxed iframe for a separate
sub/sibling-domain - dpop.example.com
<http://dpop.example.com/>).
An iframe with a different origin would also work (not really
sandboxing, as that implies the use of the sandbox attribute
to enforce behavioral restrictions). The downside of an
iframe is the need to host additional HTML, vs a script file
for the worker, but the effect is indeed the same.
For scenario 4, I think this only works if the attacker can
trick/spoof the AS into using their redirect_uri? Otherwise
the AC will go to the legitimate app which will reject it
due to mismatched state/PKCE. Or are you thinking of XSS on
the redirect_uri itself? I think probably a good practice is
that the target of a redirect_uri should be a very minimal
and locked down page to avoid this kind of possibility.
(Again, using a separate sub-domain to handle tokens and
DPoP seems like a good idea).
My original thought was to use a silent flow with Web
Messaging. The scenario would go as follows:
1. Setup a Web Messaging listener to receive the incoming code
2. Create a hidden iframe with the DOM APIs
3. Create an authorization request such as
“//authorize?response_type=code&client_id=...&redirect_uri=https%3A%2F%example.com
<http://example.com/>&state=...&code_challenge=7-ffnU1EzHtMfxOAdlkp_WixnAM_z9tMh3JxgjazXAk&code_challenge_method=S256&prompt=none&response_mode=web_message/”
4. Load this URL in the iframe, and wait for the result
5. Retrieve code in the listener, and use PKCE (+ DPoP if
needed) to exchange it for tokens
This puts the attacker in full control over every aspect of
the flow, so no need to manipulate any of the parameters.
After your comment, I also believe an attacker can run the
same scenario without the “/response_mode=web_message/”. This
would go as follows:
1. Create a hidden iframe with the DOM APIs
2. Setup polling to read the URL (this will be possible for
same-origin pages, not for cross-origin pages)
3. Create an authorization request such as
“//authorize?response_type=code&client_id=...&redirect_uri=https%3A%2F%example.com
<http://example.com/>&state=...&code_challenge=7-ffnU1EzHtMfxOAdlkp_WixnAM_z9tMh3JxgjazXAk&code_challenge_method=S256/”
4. Load this URL in the iframe, and keep polling
5. Detect the redirect back to the application with the code
in the URL, retrieve code, and use PKCE (+ DPoP if needed) to
exchange it for tokens
In step 5, the application is likely to also try to exchange
the code. This will fail due to a mismatching PKCE verifier.
While noisy, I don’t think it affects the scenario.
IMO, the online attack scenario (i.e., proxying malicious
requests through the victim’s browser) is quite appealing to
an attacker, despite the apparent inconvenience:
- the victim’s browser may be inside a corporate firewall
or VPN, allowing the attacker to effectively bypass these
restrictions
- the attacker’s traffic is mixed in with the user’s own
requests, making them harder to distinguish or to block
Overall, DPoP can only protect against XSS to the same level
as HttpOnly cookies. This is not nothing, but it means it
only prevents relatively naive attacks. Given the
association of public key signatures with strong
authentication, people may have overinflated expectations if
DPoP is pitched as an XSS defence.
Yes, in the cookie world this is known as “Session Riding”.
Having the worker for token isolation would make it possible
to enforce a coarse-grained policy on outgoing requests to
prevent total abuse of the AT.
My main concern here is the effort of doing DPoP in a browser
versus the limited gains. It may also give a false sense of
security.
With all this said, I believe that the AS can lock down its
configuration to reduce these attack vectors. A few initial
ideas:
1. Disable silent flows for SPAs using RT rotation
2. Use the sec-fetch headers to detect and reject non-silent
iframe-based flows
For example, an OAuth 2.0 flow in an iframe in Brave/Chrome
carries these headers:
/
sec-fetch-dest: iframe
sec-fetch-mode: navigate
sec-fetch-site: cross-site
sec-fetch-user: ?1
/
Philippe
/CONFIDENTIALITY NOTICE: This email may contain confidential and
privileged material for the sole use of the intended
recipient(s). Any review, use, distribution or disclosure by
others is strictly prohibited. If you have received this
communication in error, please notify the sender immediately by
e-mail and delete the message and any file attachments from your
computer. Thank you./