This post is also available in: 日本語 (Japanese)
Jan. 30, 2023
After hearing the community's feedback about the prerequisites of the exploitation scenario of the vulnerability, we made the decision to work with Auth0 to retract CVE-2022-23529.
The security issue described in this blog remains a concern when the JsonWebToken library is used in an insecure way. In that scenario, if all the prerequisites are met, the issue may be exploitable. We agree that the source of this risk in that case will be in the calling code, and not in the library.
Important security checks were added to the JsonWebToken code to address this issue.
Users of jsonwebtoken 8.5.1 and earlier are encouraged to update to the latest version, 9.0.0, which presents safer code that fixes this security flaw and others, and prevents misuse of the package that was presented in this blog.
We want to thank Auth0 for their work to address the security issue, as well as the security community for the interest and feedback. We would also like to thank GitHub for their help. The update can be read on the Auth0 GitHub.
Jan. 12, 2023
After receiving feedback from the community, we decided to make some clarifications regarding possible exploitation. We originally mentioned that an attacker needs to have control over the secret manager and decided that there was a practical need to make this even more clear in our language and associated figures.
Unit 42 researchers discovered a new vulnerability in the popular JsonWebToken open source project. The vulnerability is identified as CVE-2022-23529, rated high severity (CVSS 7.6).
By exploiting this vulnerability, attackers could achieve remote code execution (RCE) on a server verifying a maliciously crafted JSON web token (JWT) request. This vulnerability requires several prerequisites in order to be exploitable, which makes it less likely for an attacker to use it in the wild.
If you are using JsonWebToken 8.5.1 or an earlier version, we suggest updating to JsonWebToken version 9.0.0, which includes a fix for this vulnerability.
Palo Alto Networks customers can identify assets that are running vulnerable versions of the JsonWebToken package with Prisma Cloud, and they can identify the relevant CVE within scan results.
|Related Unit 42 Topics
|CVE-2022-23529, remote code execution, open source, cloud
JWT (pronounced “jot”) is an open standard that defines a method of transferring information securely by encoding and signing JSON data. JWTs have a string structure that consists of 3 parts separated by a dot (.):
JWTs are used to transmit different types of information, but are mainly used to deliver “claims,” which are pieces of information about some subject. In practice, this will most likely contain useful information about a user.
The most common use case of JWTs is for authorization and authentication. Let’s quickly go over the JWT structure.
As shown in Figure 1, the header consists mostly of two parameters that indicate the type of the token and the signing algorithm.
The payload (shown in Figure 2) is the second part of the token, which will contain the claims. In most cases, this will provide useful information about a user.
There are three different types of claims: registered, public and private. You can find more information about them in RFC 7519.
The header and payload are each Base64Url encoded to form the first and second parts of a JWT string (Header.Payload.Signature):
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 and eyJ1c2VyX25hbWUiOiJKb2huIERvZSIsImFkbWluIjp0cnVlfQ.
The third part of the JWT, the signature, is then computed (signed) by the following formula using a secret key. A signature is used to verify that the token isn’t forged or manipulated. Because it is signed with a secret key, we can validate the authenticity of the sender. Here is an example of a signature calculation:
base64Url(HMACSHA256(base64Url(header) + ”.” + base64Url(payload), secret_key)) = epQym-1JoN9eep458VBZw4-cVhwfmsI1cfaGa6PE818
Putting it all together, we will get a JWT in its complete form, as shown in Figure 3.
Let’s take a look at a simple authentication process using a JSON web token (also shown in Figure 4):
- To access a protected resource, the user will log in using credentials, usually username and password.
- A request containing this information will be sent to the authentication server.
- An authentication server will validate the information sent within a request and issue a JWT signed with a secret key, which can be stored on a server or in a different location using a secret manager.
- From now on, each user request will contain a JWT in the authorization header. This way, users with the right permissions can receive access to protected resources.
- When a user requests access to a protected resource, a request containing a JWT will be generated from the application to the JWT authentication server.
- Before the user receives access to a requested resource, the JWT that was sent in the authorization header will be verified using the secret key. This is done to verify it was not tampered along the way and that the user has the right permissions to view the requested information. In the node.js JsonWebToken package, this is done with the verify() function.
Open source projects help a lot of organizations to save time and other resources. At times, this can serve as an elegant and quick problem solver. JWT became a very popular technology that many organizations rely on, and this is one of the reasons that some of the open source projects implementing JWT have become a great success.
Typically, attacks on JWT will involve different forgery techniques abusing buggy JWT implementations. These kinds of attacks have severe consequences because, in most cases, a successful attack allows an attacker to bypass authentication and authorization mechanisms to access confidential information or steal and/or modify data.
One of the methods provided by the JsonWebToken package is verify. The verify method receives three parameters: token, secretOrPublicKey and options. This function verifies the validity of the JWT and returns the decoded payload part.
According to the documentation, secretOrPublicKey is a string or buffer. We can see the lines of code shown in Figure 5 in the JsonWebToken verify.js source code.
When no allowed algorithms are provided within the options algorithms list, the values within the privacy enhanced mail (PEM) file, which is provided by the secretOrPublicKey parameter, will be assigned instead. This presents a problem: There is no check in place that secretOrPublicKey is actually a valid PEM file’s content, and this unverified object’s toString method is blindly being used. Attackers with control over this object can supply their own toString method, which will then be executed by JsonWebToken’s verify in line 114.
Our malicious code will execute and exit the node process before the .includes(‘BEGIN CERTIFICATE’)check in the verify function, resulting in an arbitrary write file on the hosting machine.
With the same technique, it is possible to achieve RCE, but we will have to slightly modify our payload by using the child_process module (as shown in Figure 8).
Secrets can be stored outside of the authenticating server – for example, they can be kept within a secret manager in a different location. An attacker that only had write access to the secret manager can now execute code on the authentication server. If there was a check in place that the malicious object was a valid secret, code execution was not possible.
In the previous section, we demonstrated how a poisoned secret key could lead to an RCE. In reality, keeping and maintaining secret keys usually involves secret managers, secret key rotations, encryption and other best practices.
In order to exploit the vulnerability described in this post and control the secretOrPublicKey value, an attacker will need to have control or exploit a flaw within the secret management process. Even then, exploitation might be complicated as the output of a secret manager is uncertain. It can be of a type not suited for an exploitation (a string, for example) or many other possible scenarios.
Due to the complexity of exploitation of this vulnerability, we initially suggested a CVSS score of 6.6. However, we decided to accept the CVSS calculation made by the vendor, which yielded a higher severity of 7.6.
JsonWebToken version 9.0.0 contains the following fix:
The vulnerable code was removed and replaced with checks for the type of secretOrPublickey parameter, which prevents secretOrPublicKey from containing malicious objects.
- July 13, 2022 – Unit 42 researchers sent a disclosure to the Auth0 team under responsible disclosure procedures
- July 27, 2022 – Auth0 team updated that the issue was under review
- Aug. 23, 2022 – Unit 42 researchers sent an update request
- Aug. 24, 2022 – Auth0 team updated that the engineering team was working on the resolution
- Dec. 21, 2022 – A patch was provided by the Auth0 engineering team
Open source projects are commonly used as the backbone of many services and platforms today. This is also true for the implementation of sensitive security mechanisms such as JWT, which play a huge role in authentication and authorization processes.
Security awareness is crucial when using open source software. Reviewing commonly used security open source implementations is necessary for maintaining their dependability, and it's something the open source community can take part in.
As part of the commitment of Palo Alto Networks to open source software security, we regularly conduct security research efforts that include identifying security vulnerabilities in open source projects.
Palo Alto Networks Prisma Cloud customers can detect affected images and hosts under the Vulnerabilities tab. The platform detects JsonWebToken packages and alerts on entities running with a vulnerable version. In addition, our users can search for CVE-2022-23529 in the Vulnerability Explorer section to discover more details about the vulnerability and assets affected by it.
We would like to thank the Auth0 team for professionally handling the disclosure process and providing a patch for the reported vulnerability.
Updated January 12, 2023, at 3:31 p.m. PT.
Updated January 30, 2023, at 7:20 a.m. PT.