3

We recently failed a pen test due to our implementation of Identity Server 4 not preventing a replay attack. I have uploaded a simplified version of our setup to github to demonstrate what is going wrong. https://github.com/adriver-kwiboo/id4-replay-attack-demo

Here are the steps to replicate:

  • Clone github repo
  • In VS start multiple projects (IdentityServer + API)
  • In VS Code navigate to Bebop.WebApp
  • npm install
  • npm start
  • Get a trial version of BurpSuite Pro: https://portswigger.net/burp/pro
  • Start a new temp project
  • Proxy
  • Options
  • Make sure Intercept Server response is ticked

enter image description here

  • On the Intercept tab
  • Click open browser
  • Navigate to http://localhost:3000
  • Click Login button
  • In Burpsuite click the "Intercept is off" to turn it on:

enter image description here

  • Input "alice" as username and password
  • In Burpsuite, Forward the first response
  • You should get a 302 as the second response:

enter image description here

  • Copy this response to Notepad
  • Turn off Intercept, and it will continue you back into localhost:3000
  • Click the Sign out button
  • Navigate back to http://localhost:3000
  • Click the Sign in button
  • Turn on Intercept back in Burpsuite.
  • Input an invalid username / password
  • Forward the first response
  • On the 200 response, where it displays the invalid username / password. Replace the response, with the text you previously copied into Notepad
  • Turn off Intercept
  • You will get an error page enter image description here
  • Navigate to http://localhost:3000
  • Click the Sign in button
  • You will see that you are not prompted for the username / password, but instead logged straight in.

Is there something I am missing in my implementation? Or is this a limitation of Identity Server? My expectation would be that if you tried to login with a previous response, it would validate that the response did not match the request and prevent logging in.

The oidc-client.js is checking something, as it throws the error about no matching state. Should the front-end then inform the backend of the failure and remove the successful token from ID server? This feels like it could be intercepted as well, and ignored.

Alex Driver
  • 125
  • 7
  • What is the question? – Aviad P. Sep 05 '22 at 20:26
  • Sorry if it was unclear. My question is "how do I prevent replay attacks using the authorization flow and PKCE". I have followed numerous online tutorials, but I have yet to find a way that would prevent the scenario detailed above from logging the user in without having to confirm the password on the replay. – Alex Driver Sep 06 '22 at 05:04
  • Is this an issue of the implementation of identityserver4? If so this should be opened as an issue in their repo https://github.com/DuendeSoftware/IdentityServer - also please edit your question to include the actual question, so that I can remove my downvote :) – Aviad P. Sep 06 '22 at 06:22
  • I noticed that you are using an outdated version of identity server https://github.com/adriver-kwiboo/id4-replay-attack-demo/blob/10e8eb0a187e4808491ab67328fb4721d1ccec12/Bebop.Identity/IdentityServer.csproj#L7 - you should be using `Duende.IdentityServer` instead. – Aviad P. Sep 06 '22 at 06:30
  • I submitted a pull request for that https://github.com/adriver-kwiboo/id4-replay-attack-demo/pull/1 – Aviad P. Sep 06 '22 at 06:39
  • Thanks Aviad for the PR, I have tested it locally and unfortunately using the replication steps above I can replace the response with a replay. – Alex Driver Sep 06 '22 at 07:09
  • I've updated the question to include the actual question, apologies for not making it clear originally. – Alex Driver Sep 06 '22 at 07:14

1 Answers1

1

A big thank you to Brock Allen, he has helped me diagnose this.

Basically the response that I'm intercepting and replacing has the header to set the auth cookie.

Set-Cookie: idsrv.session=XXXX; path=/; secure; samesite=none
Set-Cookie: .AspNetCore.Identity.Application=XXXX

ID Server using ASP.NET Core's cookie authentication handler checks the cookie to make sure it hasn't expired, and the claim for the user's unique ID is read from it. That's how IdentityServer knows who the user is so it can issue tokens for them.

Brock has suggested I look into the profile service in ID server to see how I can use that to confirm the user is valid on the 2nd attempt.

Alex Driver
  • 125
  • 7