Bug 2263326 - Side-channel in libjwt
Summary: Side-channel in libjwt
Keywords:
Status: ASSIGNED
Alias: None
Product: Fedora EPEL
Classification: Fedora
Component: libjwt
Version: epel9
Hardware: All
OS: Unspecified
unspecified
high
Target Milestone: ---
Assignee: Ward
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2024-02-08 11:59 UTC by Erwan Legrand
Modified: 2024-02-18 23:01 UTC (History)
3 users (show)

Fixed In Version:
Doc Type: If docs needed, set a value
Doc Text:
Clone Of:
Environment:
Last Closed:
Type: Bug
Embargoed:


Attachments (Terms of Use)
Proposed patch (1016 bytes, patch)
2024-02-18 23:00 UTC, Erwan Legrand
no flags Details | Diff

Description Erwan Legrand 2024-02-08 11:59:55 UTC
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.

Comment 1 Ward 2024-02-09 07:22:16 UTC
Did you get any feedback from upstream? If there isn't a patch, I can't do much.

Comment 2 Erwan Legrand 2024-02-09 10:30:57 UTC
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.

Comment 3 Ward 2024-02-09 17:00:18 UTC
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.

Comment 4 Ward 2024-02-13 13:38:46 UTC
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).

Comment 5 Erwan Legrand 2024-02-18 23:00:30 UTC
Created attachment 2017561 [details]
Proposed patch

Patch against libjwt-0.12.1

Comment 6 Erwan Legrand 2024-02-18 23:01:17 UTC
Here is a patch against 0.12.1. I hope this helps.


Note You need to log in before you can comment on or make changes to this bug.