A few clarifications about CVE-2022-21449

Just a few quick notes/updates to correct some potentially inaccurate statements that are floating around on Reddit/Twitter etc:

  • The bug only impacts Java 15 and above. The original advisory from Oracle incorrectly listed earlier versions (like 7, 8 and 11) as being impacted. They have since corrected this. Note that they now only list 17 and 18, because 15 and 16 are no longer supported.
  • Bouncy Castle is not impacted by this vulnerability. They have their own ECDSA implementation, and it performs the relevant check to prevent this bug.
  • Although an all-zero signature value is the simplest way to exploit this, there are several alternative values that exhibit the same bug. As previously mentioned, Project Wycheproof has an excellent selection of test vectors for this bug and many variations on it, in different signature formats, and for different elliptic curves.
  • On a related note, some JWT libraries were initially assumed to be unaffected because a quirk of re-encoding raw (IEEE P1363) format signatures into ASN.1 format rejected zero values. But, as pointed out above, there are other invalid values that are not rejected by this conversion that still trigger the bug. Either upgrade your JVM, or your JWT library, and ideally both.
  • Some JWT libraries also apparently accept signature values in several alternative encodings, so if you are checking for bad signatures in a pre-processing step then you have even more values to check. Again, best to update to get the patches rather than trying to fix this yourself.

CVE-2022-21449: Psychic Signatures in Java

The long-running BBC sci-fi show Doctor Who has a recurring plot device where the Doctor manages to get out of trouble by showing an identity card which is actually completely blank. Of course, this being Doctor Who, the card is really made out of a special “psychic paper“, which causes the person looking at it to see whatever the Doctor wants them to see: a security pass, a warrant, or whatever.

Doctor Who holding up a blank ID card with a badly superimposed image of Duke (the Java mascot) holding a glass of wine.
“Looks legit to me. Hic!

It turns out that some recent releases of Java were vulnerable to a similar kind of trick, in the implementation of widely-used ECDSA signatures. If you are running one of the vulnerable versions then an attacker can easily forge some types of SSL certificates and handshakes (allowing interception and modification of communications), signed JWTs, SAML assertions or OIDC id tokens, and even WebAuthn authentication messages. All using the digital equivalent of a blank piece of paper.

It’s hard to overstate the severity of this bug. If you are using ECDSA signatures for any of these security mechanisms, then an attacker can trivially and completely bypass them if your server is running any Java 15, 16, 17, or 18 version before the April 2022 Critical Patch Update (CPU). For context, almost all WebAuthn/FIDO devices in the real world (including Yubikeys*) use ECDSA signatures and many OIDC providers use ECDSA-signed JWTs.

If you have deployed Java 15, Java 16, Java 17, or Java 18 in production then you should stop what you are doing and immediately update to install the fixes in the April 2022 Critical Patch Update.

Update: the official announcement from Oracle also lists older versions of Java, including 7, 8 and 11. Although I’m not aware of the bug impacting those older implementations they did fix a similar bug in the (non-EC) DSA implementation at the same time, so it’s possible older versions are also impacted. There are also other security vulnerabilities reported in the same CPU, so (as always) it is worth upgrading even if you are running an older Java version. The OpenJDK advisory on the other hand lists only versions 15, 17, and 18 as affected by this specific issue (CVE-2022-21449).

Update 2: Oracle have informed me they are in the process of correcting the advisory to state that only versions 15-18 are impacted. The CVE has already been updated. Note that 15 and 16 are no longer supported, so it will only list 17 and 18 as impacted.

Continue reading “CVE-2022-21449: Psychic Signatures in Java”

So how *do* you validate (NIST) ECDH public keys?

Updated 20th July 2017 to clarify notation for the point of infinity. A previous version used the symbol 0 (zero) rather than O, which may have been confusing.

Updated 28th May 2020: in step 4 of the full validation check, n is the order of the prime sub-group defined by the generator point G, not the order of the curve itself. This is critical for security if you are performing this check because small-order points will satisfy the order of the curve (which is h * n), but not the order of G.

In the wake of the recent critical security vulnerabilities in some JOSE/JWT libraries around ECDH public key validation, a number of implementations scrambled to implement specific validation of public keys to eliminate these attacks. But how do we know whether these checks are sufficient? Is there any guidance on what checks should be performed? The answer is yes, but it can be a bit hard tracking down exactly what validation needs to be done in which cases. For modern elliptic curve schemes like X25519 and Ed25519, there is some debate over whether validation should be performed at all in the basic primitive implementations, as the curve eliminates some of the issues while high-level protocols can be designed to eliminate others. However, for the NIST standard curves used in JOSE, the question is more clear cut: it is absolutely critical that public keys are correctly validated, as evidenced by the linked security alert.

Continue reading “So how *do* you validate (NIST) ECDH public keys?”

Updating OpenAM’s encryption

Updated 30th March 2017 to reflect updated information (see comments), add additional links and add some clarifying text about why misuse-resistance is useful.

With the impending release of the ForgeRock Identity Platform, I thought I’d spend some time writing up a few of the bits of OpenAM 14 that I was directly involved with creating. One of my last acts before leaving FR to go solo, was to put in place the first phase of modernising AM’s aging system credential encryption scheme. Before I start, I should say that this encryption scheme is not used for encrypting user passwords (which are hashed by the LDAP user store, not AM). Instead, this scheme is used for encrypting various system credentials (passwords for SMTP servers, HMAC shared secrets, etc) in the config store and in exported system configurations and in a few other places.

The original (and still default) encryption method was first mentioned in Dante’s Inferno. Actually it dates from the original iPlanet codebase from the mid-90s, and uses correspondingly ancient cryptographic algorithms (MD5 and DES). It is best to regard it as providing only limited obfuscation of credentials, rather than any true security guarantees, and the advice has always been to secure the config store by traditional means (TLS, access controls) rather than rely on this encryption. Still, we can do much better than this now, so AM 14 ships with a new AESWrapEncryption scheme that provides significantly improved security:

Continue reading “Updating OpenAM’s encryption”

Ephemeral elliptic curve Diffie-Hellman key agreement in Java

If you like this post, you might like my book: API Security in Action (use discount code fccmadden to get 37% off when ordering).

Update 2 (17th May, 2017): I’ve written some notes on correctly validating ECDH public keys.

Update (20th April, 2017): I’ve noticed that this article gets by far the most daily hits on my blog. This worries me that people are using this code as a template for building real ECDHE key agreement, when it was only intended as a guide to the Java API. There are a lot of details in safe construction of such a protocol. More secure alternatives than to trying to roll this yourself include the various complete protocols listed at the end of the article. With that said, we’ll get back to the original article:

Diffie-Hellman key agreement (DH) is a way for two parties to agree on a symmetric secret key without explicitly communicating that secret key. As such, it provides a way for the parties to negotiate a shared AES cipher key or HMAC shared secret over a potentially insecure channel. It does not by itself provide authentication, however, so it is vulnerable to man-in-the-middle attacks without additional measures. There are several ways to provide these additional measures (e.g. signing the ephemeral public keys using a CA-issued certificate, or using a protocol like OTR), but we will not discuss them here, or go into the details of how the key agreement works. Java provides support out-of-the-box for both original discrete log DH and elliptic curve (ECDH) key agreement protocols, although the latter may not be supported on all JREs. ECDH should be preferred for any new applications as it provides significantly improved security for reasonable key sizes.

elliptic curve
An elliptic curve defined by y2 = x3 – 2x + 2

As is often the case in Java, the use of these classes can be a bit convoluted. Here we demonstrate simple Java code for ECDH key agreement on the command line. We only demonstrate ephemeral key agreement, in which the two parties generate unique public/private key pairs at the start of the protocol and throw them away once the shared secret has been negotiated. This can form the basis for perfect forward secrecy.

WARNING: the code here is not a complete security protocol and should be used for reference on the Java API only.

Continue reading “Ephemeral elliptic curve Diffie-Hellman key agreement in Java”

ThreadLocal variables and PermGen memory leaks – not always a leak

This blog post is a re-posting of my recent answer on StackOverflow regarding ThreadLocal objects and supposed PermGen memory leaks. Essentially, despite what Tomcat may say, ThreadLocal usage in a container is not always a memory leak. Repost of my answer below the line:

Continue reading “ThreadLocal variables and PermGen memory leaks – not always a leak”

The curious case of transient final locks and CopyOnWriteArrayList

Every now and then I discover a new class in the Java standard library that I’ve not needed to use before. Today, that class was CopyOnWriteArrayList (or rather the CopyOnWriteArraySet wrapper). This is a good choice when implementing a set of subscribers in an observer pattern, as typically the set of subscribers doesn’t change very often but we iterate through the set regularly to broadcast events. The COW implementations are optimised for exactly this case, as the iterator only hits a volatile read rather than needing a lock.

Being curious, I decided to have a look at the implementation of this class to verify that it behaved as I expected from the docs. Sure enough, everything is as I would expect. However, something did stick out immediately as a bit odd. Continue reading “The curious case of transient final locks and CopyOnWriteArrayList”

Single Interface Java 8 Applications

Now that the dust has settled on the launch of Java 8, we can begin to see the benefits that all these new features will bring to those of us willing to throw off the yoke of corporate oppression and start committing lambda expressions to a “Java 5” code base. The possibilities that lambdas bring, along with default methods, and the startling addition of static methods in interfaces  are real game changers. For instance, it is now possible to write an entire Java application in a single interface! Those of us who have long railed against the tyranny of a single-class-per-file can now rejoice at being able to place all of our logic in a single file, and it doesn’t even need to be a class. As you will see from this post, the future is here and it is beautiful.

Continue reading “Single Interface Java 8 Applications”

Pimp my Java!

There seem to be lots of new programming languages popping up at the moment. Clojure, Scala, Opa, Dart, Go, Rust, and so on. I’m always a fan of new programming languages, as I feel there is still so much untapped innovation to explore. However, it can take years, or even decades for a new language to reach commercial acceptance (a sad reality). In the meantime, mainstream languages can incorporate proven features from more experimental cousins. Java, for instance, has adopted generics and annotations, both features I have some fondness for. In the spirit of encouraging further progress I offer the following as a list of largely conservative enhancements to Java that are in keeping with it’s fundamental design as an imperative object-oriented language. I don’t wish to turn Java into Haskell, because Haskell is already good enough.

So, here’s my top five “easy” extensions to Java:

Continue reading “Pimp my Java!”

%d bloggers like this: