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

auth: Update JWT implementation to support other signature methods #9696

Closed
jxuan opened this issue May 4, 2018 · 10 comments
Closed

auth: Update JWT implementation to support other signature methods #9696

jxuan opened this issue May 4, 2018 · 10 comments
Assignees

Comments

@jxuan
Copy link

jxuan commented May 4, 2018

The current JWT implementation uses the public key to verify a given JWT token from client, as shown in the following code in auth/jwt.go
31 verifyKey *rsa.PublicKey
47 parsed, err := jwt.Parse(token, func(token *jwt.Token) (interface{}, error) {
48 return t.verifyKey, nil
49 })

As explained in https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/, this implementation is vulnerable to certain attacks that hackers can defeat JWT. To fix it, private key should be used to verify JWT tokens from client, instead of using the public key.

@gyuho
Copy link
Contributor

gyuho commented May 4, 2018

/cc @mitake

@joelegasse
Copy link
Contributor

@jxuan The actual vulnerability here would be changing the JWT header to a symmetric method (HMAC) instead of asymmetric (RSA). The correct fix is to ensure that the method in the token being verified is actually an asymmetric token. I'll work on getting a fix up for this.

@joelegasse joelegasse self-assigned this May 9, 2018
@jxuan
Copy link
Author

jxuan commented May 9, 2018

All JWT token libraries are designed to support both symmetric and asymmetric encryption methods, as it is what the JWT spec requires. And this is what hackers can take advantage of. Restricting ETCD to use asymmetric algorithm is one way to fix it by going away from JWT spec. Using private key to verify signature is another way to fix by staying with the JWT spec.

I recommend that you do both and using private key to verify signature is a tiny change.

@joelegasse
Copy link
Contributor

@jxuan I am going to update the JWT code to take the algorithm into account and behave accordingly (use the private key for symmetric methods). Asymmetric tokens (like RSA) can only be verified with the public key by design. It means that anyone can verify an asymmetric token, but only the holder of the private key can generate valid tokens.

@jxuan
Copy link
Author

jxuan commented May 9, 2018

@joelegasse This is not correct: "Asymmetric tokens (like RSA) can only be verified with the public key by design".

Mathematically asymmetric tokens (like RSA) can be verified with both the public key and the private key. Please refer to https://en.wikipedia.org/wiki/RSA_(cryptosystem).

@joelegasse
Copy link
Contributor

@jxuan I understand the math behind RSA. In order to use only the private key (d, n) to verify a message, you could: re-create the signature using the private key (treating it as a symmetric operation) and verify that it is identical to the received signature. Note, however, that this is not the signature verification algorithm typically used or even described by the article you linked (emphasis mine):

When Bob receives the signed message, he uses the same hash algorithm in conjunction with Alice's public key. He raises the signature to the power of e (modulo n) (as he does when encrypting a message), and compares the resulting hash value with the message's actual hash value. If the two agree, he knows that the author of the message was in possession of Alice's private key, and that the message has not been tampered with since.

Notice the mention of using Alice's public key to verify ownership of Alice's private key.

In general, encoded private key files also include the public portion. So in that regard, yes, having the encoded private key file is enough information to verify the message. However, as far as signature verification (and this library in particular) is concerned, only the public portion of the key is used to verify the signature.

if rsaKey, ok = key.(*rsa.PublicKey); !ok {
    return ErrInvalidKeyType
}

https://github.com/dgrijalva/jwt-go/blob/master/rsa.go#L61-L63

That's probably enough pedantic back-and-forth about the exact words I chose to use, and none of this will change what needs to be done to properly address the JWT signature verification bug at hand.

@jxuan
Copy link
Author

jxuan commented May 10, 2018

I see. This is limited by the JWT-go package.

Then restricting the usage of symmetric algorithm in the JWT header for ETCD is suffice.

@jxuan
Copy link
Author

jxuan commented May 11, 2018

I opened dgrijalva/jwt-go#263 for jwt-go and asked them to support using private key to verify JWT signature.

@joelegasse joelegasse changed the title JWT implementation vulnerable to critical JWT security issue auth: Update JWT implementation to support other signature methods May 14, 2018
@ericchiang
Copy link
Contributor

@jxuan thanks for raising this concern. In the future if you believe you've found a security vulnerability, please disclose it to our private mailing list :)

https://coreos.com/security/disclosure/
#9724

@jxuan
Copy link
Author

jxuan commented May 15, 2018

Sure. Thanks for clarifying!

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

No branches or pull requests

5 participants