Burp Suite User Forum

Login to post

OAuth/lab question: Authentication bypass via OAuth implicit flow

paul | Last updated: Sep 21, 2022 02:10PM UTC

In the final step of the 'OAuth implicit flow' lab, a request is made to the client application with the email/username and token values thus authenticating the user. {"email":"wiener@hotdog.com","username":"wiener","token":"FUf9B-cPHUJe1raByVFbcUmPsjkBRWtG9aBnyj7D8FO"} In this implicit flow, my understanding is that there isn't any server-to-server out-of-band communication. However, the token included in the request IS checked --- modifying the token value invalidates the request. How does the client application check the token value?

Michelle, PortSwigger Agent | Last updated: Sep 22, 2022 12:18PM UTC

If the POST /authenticate request does not contain the same token that was sent during the requests/responses with the OAuth server, then the request will no longer be valid. If you trace through the requests in the proxy history, you should be able to follow the flow and see a request immediately before the callback URL, where the response contains a location header that includes the token. There's a section on the Implicit grant type here that should help to explain things in a bit more detail: https://portswigger.net/web-security/oauth/grant-types I hope this helps.

paul | Last updated: Sep 22, 2022 02:20PM UTC

Hi Michelle, Thx for the response. Still confused: i have traced the flow and do see the request immediately before the callback URL, with the response containing the location header. Location: https://0a1500b9034ec513c0b723e400ad0002.web-security-academy.net/oauth-callback#access_token=FUf9B-cPHUJe1raByVFbcUmPsjkBRWtG9aBnyj7D8FO&expires_in=3600&token_type=Bearer&scope=openid%20profile%20email What i think i see and what i think i understand regarding the implicit flow is the following: Per the implicit grant type description and as can be seen above the token is contained within the url fragment of this Location header. When the browser submits this request the token is not sent to the client server. Instead, the token is extracted via javascript contained within the response from the client server callback response (cliient-app-host/oauth-callback URL). <script> const urlSearchParams = new URLSearchParams(window.location.hash.substr(1)); const token = urlSearchParams.get('access_token'); fetch('https://oauth-0af300f20358c5e0c020237402b80059.web-security-academy.net/me', { method: 'GET', headers: { 'Authorization': 'Bearer ' + token, 'Content-Type': 'application/json' } }) .then(r => r.json()) .then(j => fetch('/authenticate', { method: 'POST', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ email: j.email, username: j.sub, token: token }) }).then(r => document.location = '/')) </script> At this point the client server has never seen the token and doesn't see the token until it is submitted in the /authenticate request. So, when /authenticate request is made the token hasn't been delivered to client server beforehand, and since one can change the email address in the attack, it would seem the token can't be some kind of hash of the email/username. So still confused as to how the client server knows when the token is invalid (only think i can think of is that it is somehow an enctyped time value that is decrypted using a shared secret key and times out after a finite period of time)? vr, paul

Liam, PortSwigger Agent | Last updated: Sep 23, 2022 12:55PM UTC

Hi Paul. Thanks for following up. It sounds like you may not have followed step 4: 4. API call Once the client application has successfully extracted the access token from the URL fragment, it can use it to make API calls to the OAuth service's /userinfo endpoint. Unlike in the authorization code flow, this also happens via the browser. GET /userinfo HTTP/1.1 Host: oauth-resource-server.com Authorization: Bearer z0y9x8w7v6u5

You need to Log in to post a reply. Or register here, for free.