Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JWT Signature is not validated properly #14

Open
Smallwood19 opened this issue Apr 3, 2019 · 5 comments
Open

JWT Signature is not validated properly #14

Smallwood19 opened this issue Apr 3, 2019 · 5 comments

Comments

@Smallwood19
Copy link

It is possible to manipulate the JWT being sent to this library. The existing calls to the Microsoft ValidateSignature method (jwt = ValidateSignature(securityToken, validationParameters);) fail to compare the token against the signature.

Assuming Chrome is your browser and you have some sort of web front-end, you can follow these steps to reproduce the security hole:

  1. Login into the application using a login with reduced privileges (assuming you have a basic role)
  2. After successful login, open developer tools of the browser (click F12 ) and go to Application tab.
  3. Look into ‘Session Storage’ or ‘Local Storage’ or ‘Cookies’, The ‘access_token’ would be preserved in one of those local storages.
  4. Take the ‘access token’ and go to https://www.jsonwebtoken.io/, try to decode the JWT token.
  5. You can see JWT the content in plain English. Then you can manipulate your role(s) into an ADMIN role (assuming you know the higher roles already). In general, you will be editing one of the JSON arrays/objects in the decoded JWT:
    "resource_access": {
    "my-app": {
    "roles": [
    "MY_USER_ROLE"
    ]
    },
  6. ‘JWT string’ section on the website will update the encoded string after your manipulation, take that and update the ‘access_token’ in the local storage where you found the original one.
  7. Back to browser and refresh the Application.
  8. If the app is not strongly validating the signature of the token, it would open up all the features of ADMIN role. If security is good, API/UI should show some error message and does not display the ADMIN features.

These steps only work if your front-end also fails to validate the token signature before sending to the API.

@Smallwood19
Copy link
Author

I made a fork and added some code from BouncyCastle to perform the signature validation :(https://github.com/Smallwood19/Owin.Security.Keycloak)

@Smallwood19 Smallwood19 reopened this Apr 3, 2019
@highbyte
Copy link
Collaborator

highbyte commented Apr 4, 2019

I'm not able to reproduce this behavior. The Microsoft method ValidateSignature seem to work correctly for me when using the Keycloak .NET library in a WebApi application.

When testing this I didn't have a Web client that stores the access token in local storage (so no "access_token" in cookie etc). But instead I manipulated the JWT access token manually before sending it in the Authentication HTTP header (Bearer: xxxx) to the WebApi application, changing the realm_access/roles. The Keycloak library fails as expected in the ValidateSignature method when doing this, as the JWT payload no longer matches the JWT signature.

The access tokens generated by my Keycloak server uses RS256 encryption (which uses public/private key pair, where as HS256 would use a shared encryption secret).
The JWT header for me looks something like this:
{
"alg": "RS256",
"typ": "JWT",
"kid": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
}

Which settings are your settings when initializing the Keycloak .NET library?
app.UseKeycloakAuthentication(new KeycloakAuthenticationOptions
{
...
}

@Smallwood19
Copy link
Author

Smallwood19 commented Apr 4, 2019 via email

@highbyte
Copy link
Collaborator

highbyte commented Apr 8, 2019

I'm using the same Microsoft .NET library versions, and Keycloak server 4.8.3.

The only way I've been able to bypass signature validation is to set option KeycloakAuthenticationOptions.AllowUnsignedTokens=true (which you shouldn't do!), and skipping sending the JWT signature part of the Access Token to the API.

By looking at the Microsoft method JwtSecurityTokenHandler.ValidateSignature(string token, TokenValidationParameters validationParameters)
https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/rel/5.1.5/src/System.IdentityModel.Tokens.Jwt/JwtSecurityTokenHandler.cs
it seem to do the correct thing. The additional call you invoke in your fork (to JwtSecurityTokenHandler.ValidateToken) will eventually call the same method (ValidateSignature). So it's a bit of a mystery to me.

Thanks, but I cannot take credit for the library as a whole, I've only made a few bug fixes and compatibility with newer Keycloak server versions.

@Smallwood19
Copy link
Author

Smallwood19 commented Apr 11, 2019 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants