Description of problem: After I found a side-channel issue in a JWT library I was working with, I reviewed other implementations and found similar issues in a dozen different Open Source projects. In the case of libjwt, the problem is located here: https://github.com/benmcollins/libjwt/blob/323fb1c76f435b2d0d57f992ffa2a6cdc0d9f397/libjwt/jwt-openssl.c#L145 https://github.com/benmcollins/libjwt/blob/323fb1c76f435b2d0d57f992ffa2a6cdc0d9f397/libjwt/jwt-gnutls.c#L93 https://github.com/benmcollins/libjwt/blob/323fb1c76f435b2d0d57f992ffa2a6cdc0d9f397/libjwt/jwt-wincrypt.c#L627 The time strcmp() takes to complete depends on whether the characters in the provided base64url-encoded MAC matches the proper value. This could allow an attacker to mount a timing attack through measurement of response times and statistical analysis. Version-Release number of selected component (if applicable): As far as I can see, all versions are vulnerable. Additional info: One way to fix the issue is to use a contant-time comparison function such as OpenSSL's CRYPTO_memcmp(). Another possibility is to use Double HMAC Verification as described here: https://web.archive.org/web/20160203044316/https:/www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2011/february/double-hmac-verification/ I have reported the issue to the maintainer of the original Open Source project separately.
Did you get any feedback from upstream? If there isn't a patch, I can't do much.
Yes, I was able to reach the maintainer and he said he would release a patch. I had started contacting maintainers of packages in Linux distros because I couldn't find a way to contact him at first. Then I found a way but I opened this anyway.
From upstream: As noted, the strcmp() function can be used for time-based side attacks. I tried to test this and could not find a reasonable way to implement this attack for several reasons: 1) strcmp() is optimized to compare 4 and 8 bytes at a time when possible on almost every modern system, making the attack almost impossible. 2) Running 128 million iterations of strcmp() for a single byte attack gave sub-nanosecond average differences (locally on same excution stack) and almost as often as the comparison was correct, it was also wrong in the reverse sense (i.e. two byte strcmp() took less time than single byte). 3) Adding noise from network, application stack, web server, etc. would only add to the failure rate of guessing the differences above. Erwan noted that there are proofs out there showing that signal noise reduction can make this guessing more "accurate", but this proof also noted it would take up to 4 billion guesses to completely cover this attack surface. The claim was that 50k attempts per second would break a 256-bit hmac in 22 hours. While this isn't impossible, it's very implausible. However, for the sake of cryptographic correctness, I implemented jwt_strcmp() which always compares all bytes, and does so up to the longest string in the 2-string set, without passing string boundaries. This makes it time-consistent for len(max(a,b)) comparisons. I proofed this using a 128 million interation average for various scenarious.
I've created scratch build of libjwt 1.17.0. The biggest issue is that there is a soname change: the main library bumped from so.1 to so.2. I'm not sure what the proper procedure is on this? Pushing this to EPEL will break anything that uses it (like the Slurm job scheduler).
Created attachment 2017561 [details] Proposed patch Patch against libjwt-0.12.1
Here is a patch against 0.12.1. I hope this helps.