7 ms·
Psychic Signatures in Java
- MrDresden 4y agoComputerphile has released a very approachable explanation of the flaw[1], along with some basic background on ECDSA as well. [1]: https://www.youtube.com/watch?v=502iGDxuiRk https://www.youtube.com/watch?v=502iGDxuiRk
- bertman 4y agoThe fix for OpenJDK (authored on Jan. 4th 22): https://github.com/openjdk/jdk/blob/e2f8ce9c3ff4518e070960bafa70ba780746aa5c/src/jdk.crypto.ec/share/classes/sun/security/ec/ECDSAOperations.java#L225 https://github.com/openjdk/jdk/blob/e2f8ce9c3ff4518e070960ba...
- drexlspivey 4y agowith commit message “Improve ECDSA signature support” :D
- baobabKoodaa 4y agoI'm guessing the commit message is obscured to give people more time to update before it's exploited in the wild.
- sdhfkjwefs 4y agoWhy are there no tests?
- MrBuddyCasino 4y agoI spot no test or comment in the code on why this assertion is important.
- bertman 4y agoIt's literally what the whole bug is about. From OP's article: >This is why the very first check in the ECDSA verification algorithm is to ensure that r and s are both >= 1. Guess which check Java forgot?
- MrBuddyCasino 4y agoYes I just think it’s insane they fixed it without adding a test or comment.
- benazzi 4y ago[dead]
- benazzi 4y ago[dead]
- benazzi 4y ago[dead]
- tptacek 4y agoThis is probably the cryptography bug of the year. It's easy to exploit and bypasses signature verification on anything using ECDSA in Java, including SAML and JWT (if you're using ECDSA in either). The bug is simple: like a lot of number-theoretic asymmetric cryptography, the core of ECDSA is algebra on large numbers modulo some prime. Algebra in this setting works for the most part like the algebra you learned in 9th grade; in particular, zero times any algebraic expression is zero. An ECDSA signature is a pair of large numbers (r, s) (r is the x-coordinate of a randomly selected curve point based on the infamous ECDSA nonce; s is the signature proof that combines x, the hash of the message, and the secret key). The bug is that Java 15+ ECDSA accepts (0, 0). For the same bug in a simpler setting, just consider finite field Diffie Hellman, where we agree on a generator G and a prime P, Alice's secret key is `a mod P` and her public key is `G^a mod P`; I do the same with B. Our shared secret is `A^b mod P` or `B^a mod P`. If Alice (or a MITM) sends 0 (or 0 mod P) in place of A, then they know what the result is regardless of anything else: it's zero. The same bug recurs in SRP (which is sort of a flavor of DH) and protocols like it (but much worse, because Alice is proving that she knows a key and has an incentive to send zero). The math in ECDSA is more convoluted but not much more; the kernel of ECDSA signature verification is extracting the `r` embedded into `s` and comparing it to the presented `r`; if `r` and `s` are both zero, that comparison will always pass. It is much easier to mess up asymmetric cryptography than it is to mess up most conventional symmetric cryptography, which is a reason to avoid asymmetric cryptography when you don't absolutely need it. This is a devastating bug that probably affects a lot of different stuff. Thoughts and prayers to the Java ecosystem!
- loup-vaillant 4y agoInterestingly, EdDSA (generally known as Ed25519) does not need as many checks as ECDSA, and assuming the public key is valid, an all-zero signature will be rejected with the main checks. All you need to do is verify the following equation: R = SB - Hash(R || A || M) A Where R and S are the two halves of the signature, A is the public key, and M is the message (and B is the curve's base point). If the signature is zero, the equation reduces to Hash(R || A || M)A = 0, which is always false with a legitimate public key. And indeed, TweetNaCl does not explicitly check that the signature is not zero. It doesn't need to. However. There are still ways to be clever and shoot ourselves in the foot. In particular, there's the temptation to convert the Edwards point to Montgomery, perform the scalar multiplication there, then convert back (doubles the code's speed compared to a naive ladder). Unfortunately, doing that introduces edge cases that weren't there before, that cause the point we get back to be invalid. So invalid in fact that adding it to another point gives us zero half the time or so, causing the verification to succeed even though it should have failed! (Pro tip: don't bother with that conversion, variable time double scalarmult https://loup-vaillant.fr/tutorials/fast-scalarmult https://loup-vaillant.fr/tutorials/fast-scalarmult is even faster.) A pretty subtle error, though with eerily similar consequences. It looked like a beginner-nuclear-boyscout error, but my only negligence there was messing with maths I only partially understood. (A pretty big no-no, but I have learned my lesson since.) Now if someone could contact the Whycheproof team and get them to fix their front page so people know they have EdDSA test vectors, that would be great. https://github.com/google/wycheproof/pull/79 https://github.com/google/wycheproof/pull/79 If I had known about those, the whole debacle could have been avoided. Heck, I bet my hat their ECDSA test vectors could have avoided the present Java vulnerability. They need to be advertised better.
- RandomBK 4y agoDoes anyone know why this was only given a CVSS score of 7.5? Based on the description this sounds way worse, but Oracle only gave it a CVSS Confidentiality Score of "None", which doesn't sound right. Is there some mitigating factor that hasn't been discussed? In terms of OpenJDK 17 (latest LTS), the issue is patched in 17.0.3, which was release ~12h ago. Note that official OpenJDK docker images are still on 17.0.2 as of time of writing.
- tptacek 4y agoCVSS is a completely meaningless Ouija board that says whatever the person authoring the score wants it to say.
- ptx 4y agoApparently you have to get a new CPU to fix this Java vulnerability, or alternatively a new PSU. (That is to say: a Critical Patch Update or a Patch Set Update. Did they really have to overload these TLAs?)
- deleted 4y ago[deleted]
- tialaramex 4y agoThis is the sort of dumb mistake that ought to get caught by unit testing. A junior, assigned the task of testing this feature, ought to see that in the cryptographic signature design these values are checked as not zero, try setting them to zero, and... watch it burn to the ground. Except that, of course, people don't actually do unit testing, they're too busy. Somebody is probably going to mention fuzz testing. But, if you're "too busy" to even write the unit tests for the software you're about to replace, you aren't going to fuzz test it are you?
- tptacek 4y agoThe point of fuzz testing is not having to think of test cases in the first place.
- solarengineer 4y agoIf we write an automated test case for known acceptance criteria, and then write necessary and sufficient code to get those tests to pass, we would know what known acceptance criteria are being fulfilled. When someone else adds to the code and causes a test to fail, the test case and the specific acceptance criteria would thus help the developer understand intended behaviour (verify behaviour, review implementation). Thus, the test suite would become a catalogue of programmatically verifiable acceptance criteria. Certainly, fuzz tests would help us test boundary conditions and more, but they are not a catalogue of known acceptance criteria.
- kasey_junk 4y agoThis is true in principle but in practice most fuzz testing frameworks demand a fair bit of setup. It’s worth it! But if you are in a time constrained environment where basic unit tests are skipped fuzz testing will be as well.
- tialaramex 4y ago[Somebody had down-voted you when I saw this, but it wasn't me] These aren't alternatives, they're complementary. I appreciate that fuzz testing makes sense over writing unit tests for weird edge cases, but "these parameters can't be zero" isn't an edge case, it's part of the basic design. Here's an example of what X9.62 says: > If r’ is not an integer in the interval [1, n-1], then reject the signature. Let's write a unit test to check say, zero here. Can we also use fuzz testing? Sure, why not. But lines like this ought to scream out for a unit test.
- cesarb 4y agoAnd once again, you'd be saved if you stayed on an older release. This is the third time this has happened recently in the Java world: the Spring4Shell vulnerability only applies to Java 9 and later (that vulnerability depends on the existence of a method introduced by Java 9, since all older methods were properly blacklisted by Spring), and the Log4Shell vulnerability only applies to log4j 2.x (so if you stayed with log4j 1.x, and didn't explicitly configure it to use a vulnerable appender, you were safe). What's going on with Java?
- taeric 4y agoYou make this sound like it is unique to java. I remember heartbleed had similar, in that the lts I was on did not have the vulnerable library. At some level, as long as releases add functionality, the basic rules of systemantics will guarantee unintended interactions.
- ragnese 4y agoWas Spring4Shell Java's fault, or Spring's fault? Log4Shell was obviously (mostly) log4j's fault. This one, I gather, is actually Java's fault. It sounds like three unrelated security bugs from totally different teams of developers.
- brazzy 4y agoI think they other two are considered "Javas's fault" because the frameworks they occurred in are so pervasive in the Java ecosystem that you might as well consider them part of the standard library.
- znep 4y agoSpring4Shell is entirely a flaw in Spring, however is somewhat understandable because it was only exploitable due to a new feature in Java (modules) that added new methods to java.lang.Class, which is a very significant change. You could argue the very existence and nature of Java object serialization deserves blame as well, but that gets nuanced quickly. Modules are also part of the reason why so many folks got "stuck" on java 8. It is definitely an interesting study in the challenges of trying to make advances in a platform when a lot of the ecosystem is very much in maintenance mode and may not have a lot of eyes on the combination of existing libraries vs new versions of Java.
- deleted 4y ago[deleted]
- LaputanMachine 4y ago>Just a basic cryptographic risk management principle that cryptography people get mad at me for saying (because it’s true) is: don’t use asymmetric cryptography unless you absolutely need it. Is there any truth to this? Doesn't basically all Internet traffic rely on the security of (correctly implemented) asymmetric cryptography?
- lazide 4y agoInitial connection negotiation and key exchange does, anything after that no. It will use some kind of symmetric algo (generally AES). It's a bad idea (and no one should be doing it) to continue using asymmetric crypto algorithms after that. If someone can get away with a pre-shared (symmetric) key, sometimes/usually even better, depending on the risk profiles.
- loup-vaillant 4y ago> It will use some kind of symmetric algo (generally AES). AES-GCM, you mean. Let's not forget the authentication in "authenticated encryption". I'm nitpicking, but if a beginner comes here it's better to make it clear that in general, encryption alone is not enough. Ciphertext malleability and all that.
- lazide 4y agoPlenty of stuff still uses CBC (or other modes) with another authentication method. AES-GCM is nice in that it combines both explicitly, but a lot of stuff just combines other methods and it’s fine. AES-GCM has the annoying property of output size > input size for instance.
- m00dy 4y ago
- 0des 4y agoI want to live in this world, but no.
- ccbccccbbcccbb 4y agoQ: Which type of cryptography is implied to be unsafe in the following sentence?: "Immediately ditch RSA in favor of EC, for it is too hard to implement safely!"
- tedunangst 4y agoWhat's java's RSA history look like?
- ccbccccbbcccbb 4y agoMy comment was rather language-agnostic. Are there any fundamental differences in implementation of RSA or EC in various languages?
- pluc 4y agoNot a good few months for Java
- lobstey 4y agoI doubt how many companies are actually using java15+. Many still sticks to 8 or 11
- lobstey 4y agoNot that a lot of companies are using the Java 15+. People generally stick to 8 or 11.
- needusername 4y agoI believe Oracle 11 is affected.
- stolsvik 4y agoI do not believe so. The "affected list" which includes 11 is for the complete set of the "CPU" - Critical Patch Update. This specific one was introduced with the rewriting of these parts of the code from C++ to Java, and that happened with Java 15.
- needusername 4y agoLooks like you’re correct and I was wrong.
- stolsvik 4y agoThe title of the blogpost is now updated to "CVE-2022-21449: Psychic Signatures in Java" - maybe this HN post could too?
- vemv 4y agoAgreed (@dang)
- dynamite-ready 4y agoWonder if someone can add a little more info to the title of this story. It's would probably draw more clicks if the title wasn't so cryptic. This is essentially a Java dev infosec post.
- pas 4y agoJust wait a few days and it'll be on the news like the log4j2 vulnerability :) (Though it might not, because in practice BouncyCastle is used in a most big/old Java software - as far as I know.)
- danmur 4y agoIt's crazy that the check for this was right there in the original code and was obviously missed when porting to Java. Great example of why unit tests are part of the code (and were missing in both in this case).
- vlowrian 4y agoWhat puzzles me most is that two days after the announcement of the vulnerability and the release of the patched Oracle JDK, there is still no patched version of OpenJDK for most distributions. We're running some production services on OpenJDK and CentOS and until now there are only two options to be safe: shutdown the services or change the crypto provider to BouncyCastle or something else. The official OpenJDK project lists the planned release date of 17.0.3 as April 19th, still the latest available GA release is 17.0.2 (https://wiki.openjdk.java.net/display/JDKUpdates/JDK+17u https://wiki.openjdk.java.net/display/JDKUpdates/JDK+17u). Adoptium have a large banner on their website and until now there is not a single patched release of OpenJDK available from them (https://github.com/adoptium/adoptium/issues/140 https://github.com/adoptium/adoptium/issues/140). There are no patched packages for CentOS, Debian or openSUSE. The only available version of OpenJDK 17.0.3 I've seen until now seems to be the Archlinux package (https://archlinux.org/packages/extra/x86_64/jdk17-openjdk/ https://archlinux.org/packages/extra/x86_64/jdk17-openjdk/). They obviously have their own build. How can it be that this is not more of an issue? I honestly don't get how the release process of something as widely used as OpenJDK can take more than 2 days to provide binary packages for something already fixed in the code. This shouldn't be much more effort than letting the CI do its job. Edit: Typo.
- ptx 4y agoAzul published updated packages yesterday, including for some older non-LTS Java versions: https://www.azul.com/downloads/?package=jdk#download-openjdk https://www.azul.com/downloads/?package=jdk#download-openjdk
- vlowrian 4y agoThanks for the info! That's very interesting since they usually only provide out-of-cycle critical fixes for their paid tiers. On the other hand - this only proves that it's actually possible to provide a hot-fixed OpenJDK in time. Unfortunately, I assume that a very common case is just using the distribution provided openjdk-package and configuring the system for auto updates. So the main issue here is that a serious number of systems is relying on the patch process of the distribution to fix issues like this and they are still vulnerable at this moment.
- benazzi 4y ago[flagged]
- benazzi 4y ago[flagged]