Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix for Issue: CVE-2022-41852 (CVE has been rejected) #25

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

bhmohanr-techie
Copy link

@bhmohanr-techie bhmohanr-techie commented Oct 13, 2022

Issue ID:

Issue Description:

Those using JXPath to interpret untrusted XPath expressions may be vulnerable to a remote code execution attack. All JXPathContext class functions processing a XPath string are vulnerable except compile() and compilePath() function. The XPath expression can be used by an attacker to load any Java class from the classpath resulting in code execution.

CVSS Version 3.x:

9.8 Critical

Affected versions:

1.3 and earlier

Vulnerability Type:

Remote Code Execution (RCE)

Steps to Reproduce:

  • Issue reported here is, all functions in the class JXPathContext (except compile and compilePath) are vulnerable to a remote code execution attack. - An arbitrary code can be injected in the xpath values passed to these functions, and it allows triggering java classes that can exploit the target machine.
  • For instance, the iterate() method in the JXPathContext class, can be invoked by passing the xpath argument value as, java.lang.Thread.sleep(9999999) or java.lang.Class.forName("ExploitTest"). These examples can result in triggering the injected java code, and can exploit the target machine.
  • Example:
    JXPathContext context = JXPathContext.newContext(new Test() );
    Iterator result = context.iterate("java.lang.Thread.sleep(9999999)");
    System.out.println("result.hasNext() - " + result.hasNext());

Workarounds:

  • No workaround available

Fix:

Please note that, the fix added here is via a new system property (enabling this property, will address the issue). This will ensure that we are not breaking functionality for existing users.

  • In order to fix this issue, a filter class "JXPathFilter.java" is added in JXPath. This filter object will be used to validate if the xpath passed to JXPath is a valid one
  • This new filter class, for now implements JXPathClassFilter interface, which is used to check the java classes passed in xpath. In future, we could implement any other interface, to verify other cases as well.
  • In this filter, the class filter validates to see if the class being loaded in JXPath is part of the restriction list. The restriction can be configured via a system property "jxpath.class.deny"
  • System property "jxpath.class.deny" can be set to specify the list of restricted classnames. This property takes a list of java classnames (use comma as separator to specify more than one class). If this property is not set, it exposes any java class to javascript Example: jxpath.class.deny=java.lang.Runtime will deny exposing java.lang.Runtime class via xpath, while all other classes will be exposed.
  • When a new extension function is created by JXPath, it uses the filter to check if the xpath supplied is a valid string, only then function instances are created.
  • The changes are added to pass JXPathFilter instance as an additional argument to the methods that create the ExtensionFunction objects. In addition, the ClassLoaderUtil class is modified to use the JXPathFilter instance when a new Class instance is created. Please note that, the changes here are added as overloaded methods, so that we are not affecting existing code for anyone.

Unit Testing:

  • Verified that the RCE vulnerability is no more applicable for any of the functions in the JXPathContext class.
  • Verified different code areas and found that the fix is addressed in all cases. Testing covers Class Functions, Package Funcions, Function Libraries and functions exposed in JXPathContext.
  • All the test cases for this change is covered in unit test code: in ExtensionFunctionTest.java. 10 new test methods are added in this class, to make sure all possible areas are covered.

Summary:

  • The changes added in the pull request, takes effect only if the newly added System property "jxpath.class.deny" is set. This ensures that existing users of jxpath are not affected by this change.
  • The new system property can be configured based on the environment and user needs.
  • In order to fix CVE-2022-41852, we need to configure "jxpath.class.deny=java.lang.Class" which will ensure that Class.forName() call is blocked when passed via xpath strings.

CVE-2022-41852

# Issue Description:
Those using JXPath to interpret untrusted XPath expressions may be vulnerable to a remote code execution attack. All JXPathContext class functions processing a XPath string are vulnerable except compile() and compilePath() function. The XPath expression can be used by an attacker to load any Java class from the classpath resulting in code execution.

# CVSS Version 3.x:
9.8 Critical

# Affected versions:
1.3 and earlier

# Vulnerability Type:
Remote Code Execution (RCE)

# Steps to Reproduce:
- Issue reported here is, all functions in the class JXPathContext (except compile and compilePath) are vulnerable to a remote code execution attack. - An arbitrary code can be injected in the xpath values passed to these functions, and it allows triggering java classes that can exploit the target machine.
- For instance, the iterate() method in the JXPathContext class, can be invoked by passing the xpath argument value as, java.lang.Thread.sleep(9999999) or java.lang.Class.forName("ExploitTest"). These examples can result in triggering the injected java code, and can exploit the target machine.
- Example:
        JXPathContext context = JXPathContext.newContext(new Test() );
        Iterator result = context.iterate("java.lang.Thread.sleep(9999999)");
        System.out.println("result.hasNext() - " + result.hasNext());

# Workarounds:
- No workaround available

# Fix:
Please note that, the fix added here is via a new system property (enabling this property, will address the issue). This will ensure that we are not breaking functionality for existing users.

- In order to fix this issue, a filter class "JXPathFilter.java" is added in JXPath. This filter object will be used to validate if the xpath passed to JXPath is a valid one
- This new filter class, for now implements JXPathClassFilter interface, which is used to check the java classes passed in xpath. In future, we could implement any other interface, to verify other cases as well.
- In this filter, the class filter validates to see if the class being loaded in JXPath is part of the restriction list. The restriction can be configured via a system property "jxpath.class.deny"
- System property "jxpath.class.deny" can be set to specify the list of restricted classnames. This property takes a list of java classnames (use comma as separator to specify more than one class). If this property is not set, it exposes any java class to javascript Example: jxpath.class.deny=java.lang.Runtime will deny exposing java.lang.Runtime class via xpath, while all other classes will be exposed.
- When a new extension function is created by JXPath, it uses the filter to check if the xpath supplied is a valid string, only then function instances are created.
- The changes are added to pass JXPathFilter instance as an additional argument to the methods that create the ExtensionFunction objects. In addition, the ClassLoaderUtil class is modified to use the JXPathFilter instance when a new Class instance is created. Please note that, the changes here are added as overloaded methods, so that we are not affecting existing code for anyone.

# Unit Testing:
- Verified that the RCE vulnerability is no more applicable for any of the functions in the JXPathContext class.
- Verified different code areas and found that the fix is addressed in all cases. Testing covers Class Functions, Package Funcions, Function Libraries and functions exposed in JXPathContext.
- All the test cases for this change is covered in unit test code: in ExtensionFunctionTest.java. 10 new test methods are added in this class, to make sure all possible areas are covered.

# Summary:
- The changes added in the pull request, takes effect only if the newly added System property "jxpath.class.deny" is set. This ensures that existing users of jxpath are not affected by this change.
- The new system property can be configured based on the environment and user needs.
- In order to fix CVE-2022-41852, we need to configure "jxpath.class.deny=java.lang.Class" which will ensure that Class.forName() call is blocked when passed via xpath strings.
@bhmohanr-techie bhmohanr-techie changed the title Issue ID: CVE-2022-41852 Fix for Issue: CVE-2022-41852 Oct 14, 2022
@Paradox98
Copy link

Is anyone following up?

@bhmohanr-techie
Copy link
Author

Is anyone following up?

@Paradox98 I was trying to reachout via Apache dev community to get this PR reviewed, but my subscription request to dev-community is still pending. So, I couldn't find a reviewer yet for this PR. Thanks.

@bhmohanr-techie
Copy link
Author

bhmohanr-techie commented Oct 18, 2022

@garydgregory @markt-asf @jvz @kinow @Paradox98

Dear Apache JXPath Maintainers,

I'm requesting your review for this PR #25 which will fix the recent reported vulnerability CVE-2022-41852. I have also raised a JIRA ticket for the same, JXPATH-201

I also see one other PR raised for the same. The other PR #26 is raised on top of this PR raised by me, with one minor change that I have explained below.

  • Fix in my PR Fix for Issue: CVE-2022-41852 (CVE has been rejected) #25 : A new system property "jxpath.class.deny" is added, which can be used to specify the list of java classes that should be restricted by jxpath. With this approach, the existing jxpath users, who aren't affected by this vulnerability can continue to use jxpath without any need for this property. Only users affected by this vulnerability are required to set this property. This ensures a smooth experience for existing users, as well as fixes the vulnerability for affected users.

  • Fix in other PR Add an allow list for classes that can be loaded by JXPath #26 : This PR is raised on top of the code changes in my PR, just with one minor change. The system property is changed from deny list to allow list, which will require all users of jxpath to configure the newly added system property (irrespective of whether the user is affected by this vulnerability), without which jxpath will no longer work for them.

Also, I have contributed a similar fix in one other opensource project (where I have used the same logic to introduce a deny list to prevent Remote Code Execution vulnerability). My contribution in that project was reviewed and approved by the maintainers, Please refer: mock-server/mockserver#1466

Please review the approach in my PR #25 and let me know your thoughts. I'm open to any suggestions or feedback from you, Thankyou.

@Paradox98
Copy link

Paradox98 commented Oct 18, 2022

It looks like your commit didn't pass ci review.
image

@bhmohanr-techie
Copy link
Author

It looks like your commit didn't pass ci review. image

@Paradox98 Yes, the ci review failed here, since JAVA_HOME variable is not defined in the machine. But, this error is not related to the changes added in this PR, but it exists even in some of the earlier PRs as well.

Please let me know if there is a way to define the JAVA_HOME variable in the ci environment, Thanks.

@0roman
Copy link

0roman commented Oct 18, 2022

@bhmohanr-techie thanks for your effort, but we highly suggest to use the whitelist approach in #26.

The main problem is that the default behaviour of the library is not changing. That means if users will just update the jxpath jar file they'll still be vulnerable and they'll need to set a System property in addition.

The next problem is that blacklisting individual components is not feasible for large projects. For example, if your project has 100 classes and you just want to allow access to one class you will need to set a system property for 99 classes e.g. System.setProperty("jxpath.class.deny", "com.example1, com.example2, com.example1, ..."); From a security perspective, the feature in jxpath should rather be used to allow a small number of classes than to disallow a big number of classes.

Furthermore, I have checked that "jxpath.class.deny=java.lang.Class" will not stop exploitation of CVE-2022-41852 as described by you, feel free to verify with xpath string "java.lang.Thread.sleep(1000000)".

For those reasons, we think that the allowlist is the better approach to go forward.

@bhmohanr-techie
Copy link
Author

That

@0roman I'm sorry to say that I still don't agree to your statement...

In the PR #26 you are changing the default behavior of jxpath... I would request you think from a user perspective, as a user if I move to a latest version of jxpath, the bare minimum thing that I expect is there should be nothing breaking in existing behavior. Having said that, with changes added in PR #26, if I do an upgrade, jxpath will not work for me, unless I set the newly added system property (this applies even if I'm not affected by this vulnerability).

The next problem is that with your approach of whitelisting individual components is not feasible for large projects. For example, if your project has 100 classes and you just want to deny access to one class you will need to set a system property for 99 classes e.g. System.setProperty("jxpath.class.allow", "com.example1, com.example2, com.example1, ..."); There is no hard restriction in jxpath to this, we should be capable of supporting jxpath to any kind of user (may it be a user allowing only a single class, or a user who allows jxpath to access a bunch of his trusted classes)

"jxpath.class.deny=java.lang.Class" will stop exploitation of CVE-2022-41852 with xpath string "java.lang.Thread.sleep(1000000)". This is already added in my unit test code as well which was copied in your PR #26 as well, I would request you to check this again.

So, I still think deny list is the best approach...

As I mentioned earlier, a similar vulnerability was fixed by me in one other opensource component, PR: mock-server/mockserver#1466. Over there, I had used deny list approach, which was review, approved and merged in their main release as well. So, this is an accepted approach in other opensource packages as well.

So, please let JXPath maintainers review the approach and decide the best suited one. We should take their valuable suggestion/feedback. Thanks.

@kyakdan
Copy link

kyakdan commented Oct 18, 2022

@bhmohanr-techie With the deny list approach, users do not get any protection whatsoever if they don't change their configurations. This means they stay insecure by default. In both approaches, you have to adjust your default configuration in order to be protected. Since our main goal here is to protect users who use the library, making it necessary to change the configuration by explicitly mentioning which classes are allowed is the best way to guarantee that they will not be vulnerable. Moreover, with a denylist, you can always forget/miss some dangerous classes. It is much harder to know all insecure classes to deny than to know which classes you trust. I think that while backward compatibility is great, protecting users by default takes precedence.

@bhmohanr-techie
Copy link
Author

kyakdan

I'm still not convinced, Please help me understand one thing.

Let's say I'm a JXPath user, and I'm not affected this vulnerability. JXPath is working all fine in my environment. Now, if we go ahead with you approach of specifying an allow list, then if I upgrade to the next JXPath version, then JXPath will stop working in my environment straight after upgrade, and I will need to set a system property to get it working again. This is an unnecessary ask from a user, who didn't have any problem with JXPath so far. We are affecting existing user behavior, which to me is not acceptable for any product/solution.

So, let please wait for JXPath maintainers on this, we should stick to what they suggest? They have better understanding of the JXPath code base and customers.

@garydgregory @markt-asf @jvz @kinow @Paradox98 requesting your valuable suggestions here. Thanks.

@markt-asf
Copy link

Please note it is highly likely that all the CVEs issued by Google / oss-fuzz for JXPath without consultation with the ASF and in breach of the rules for CNAs will be resolved as invalid.

Separately, if JXPath opts to provide a feature or features to support users who wish to process untrusted input without validation or sanitisation then a deny list would never be acceptable. A possible approach would be an allow list that defaults to everything that users could then narrow if they wish.

For the avoidance of doubt, my current position is that JXPath is intended to be used with trusted input. I haven't performed an in-depth review of JXPath, so if anyone is aware of reasons why JXPath should be expected to handle untrusted input safely, please speak up.

@madrob
Copy link

madrob commented Oct 18, 2022

Thanks for contributing! I strongly prefer the allow list approach in #26 and will leave specific code feedback in that PR. However, that PR wouldn't have been possible without your work here!

@garydgregory
Copy link
Member

Hello @bhmohanr-techie

  • Please rebase on Git master; I finally got the build working here on GitHub Actions (an old TODO).
  • Don't break binary compatibility

@wealthtears
Copy link

Please fix the issue with CVS 2022-41852.

@garydgregory
Copy link
Member

Please fix the issue with CVS 2022-41852.

Note that the CVE has been rejected.

@markt-asf markt-asf changed the title Fix for Issue: CVE-2022-41852 Fix for Issue: CVE-2022-41852 (CVE has been rejected) Sep 27, 2023
@0roman
Copy link

0roman commented Sep 27, 2023

If someone is interested in the rejected issue, have a look at https://github.com/Warxim/CVE-2022-41852.

There is also some interesting discussion in #26.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants