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.
- 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:
- Input "alice" as username and password
- In Burpsuite, Forward the first response
- You should get a 302 as the second response:
- 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
- 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.
CodePudding user response:
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.