-
Notifications
You must be signed in to change notification settings - Fork 59
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
Add an allow list for classes that can be loaded by JXPath #26
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the contribution, we also would need upgrade notes somewhere.
// give chance to ClassFilter to filter out, if present | ||
try { | ||
if (jxPathFilter != null && !jxPathFilter.exposeToXPath(functionClass.getName())) { | ||
throw new ClassNotFoundException(functionClass.getName()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We shouldn't be using exceptions for control flow here, let's throw JXPathException directly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point! Changed to throwing a JXPathException directly.
@@ -77,12 +79,30 @@ public Set getUsedNamespaces() { | |||
*/ | |||
public Function getFunction(String namespace, String name, | |||
Object[] parameters) { | |||
return getFunction(namespace, name, parameters, null); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I worry that people will continue calling this method on upgrade and continue to be insecure by default. Instead of passing null, I think a better default would be to pass either the environment-based of a fail-closed (deny all) implementation of JXPathFilter. Same logic applies for other places where we overload the method signatures.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Excellent point. Changed all usages to use a default value of the JXPathFilter that is initialized to the filter set by the system property of the allow list. This guarantees consistent behavior among all method calls.
* System property "jxpath.class.allow" can be set to specify the list of allowd 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 no java classes | ||
* Ex: jxpath.class.allow=java.lang.Runtime will allow exposing java.lang.Runtime class via xpath, while all other |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should also document the wildcard * for allowing all classes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed!
import org.apache.commons.jxpath.JXPathNotFoundException; | ||
import org.apache.commons.jxpath.JXPathTypeConversionException; | ||
import org.apache.commons.jxpath.Pointer; | ||
import org.apache.commons.jxpath.*; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The project does not appear to use wildcard imports, let's stick with existing conventions for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed.
* @version $Revision$ $Date$ | ||
*/ | ||
public class JXPathFilter implements JXPathClassFilter { | ||
ArrayList<String> allowedClassesList = null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could probably be a Set.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed!
// } | ||
} | ||
|
||
@Override | ||
public void tearDown() throws Exception { | ||
super.tearDown(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very minor, should call super.tearDown at the end of the method not the beginning.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed
1da4f86
to
d6e0c94
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hello @kyakdan
See scattered comments.
* For instance, it JXPathClassFilter interface, which is used to check if any restricted java classes are passed via xpath | ||
* JXPath uses this filter instance when an extension function instance is created. | ||
* | ||
* @author bhmohanr-techie |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't use author tags. Credit it given in the changes.xml file after a PR is merged (to avoid conflicts with other PRs).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed!
* JXPath uses this filter instance when an extension function instance is created. | ||
* | ||
* @author bhmohanr-techie | ||
* @version $Revision$ $Date$ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't use Subversion anymore.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to @since 1.4
* | ||
* @author bhmohanr-techie | ||
* @version $Revision$ $Date$ | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
New public and protected elements should have a Javadoc since
tag for the next version, which should be 1.4
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done!
public void init() { | ||
String restrictedClasses = System.getProperty("jxpath.class.allow"); | ||
allowedClassesList = null; | ||
if (restrictedClasses != null && restrictedClasses.trim().length() > 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use String#isEmpty()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed
} | ||
|
||
public void init() { | ||
String restrictedClasses = System.getProperty("jxpath.class.allow"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use final
where you can.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK
import org.apache.commons.jxpath.Functions; | ||
import org.apache.commons.jxpath.JXPathContext; | ||
|
||
import java.util.*; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't use star imports.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed. The import was not used anyway.
@kyakdan I'm not sure what happened on your rebase but you should not have to edit pom.xml or changes.xml. |
* @param jxPathFilter the XPath filter | ||
* @return Function | ||
*/ | ||
Function getFunction(String namespace, String name, Object[] parameters, JXPathFilter jxPathFilter); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs to be a default method to avoid breaking binary compatibility. This is a misconfiguration in our parent POM.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method has different implementations for the three classes implementing the Functions
interface, it cannot be made final. So, in order to not break binary compatibility, I've removed this function and made the implemented getFunction
methods use a filter based on the jxpath.allow.class
system property. This way we don't have to explicitly pass a filter parameter to the getFunction
method.
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. 9.8 Critical 1.3 and earlier Remote Code Execution (RCE) - 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()); - No workaround available The fix added here is via a new system property "jxpath.class.allow". This list is empty by default meaning that nothing is allowed by default. Users should then explicitly configure which classes are allowed. - 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 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.allow" - System property "jxpath.class.allow" can be set to specify the list of allowed 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 disallows all classes. - 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.
@madrob @garydgregory Thanks for the review. @garydgregory I've rebased again and the PR does not contain changes to pom.xml or changes.xml now. |
* JXPath uses this filter instance when an extension function instance is created. | ||
*/ | ||
public class JXPathFilter implements JXPathClassFilter { | ||
private Set<String> allowedClassesList = null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe rename the set to just allowedClasses
, since it is not list anymore?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch. Changed. I've also simplified the constructor.
fa9fb1e
to
751b035
Compare
new PackageFunctions( | ||
"org.apache.commons.jxpath.ri.compiler.", | ||
"jxpathtest")); | ||
new PackageFunctions( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's changed here? There are too many formatting changes to make this simple to review.
In general, don't reformat existing code in PRs, it just makes noise in the PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This reason is my IDE auto-reformating the file. I've only kept the relevant changes that are part of this PR.
@@ -91,6 +92,13 @@ public Function getFunction( | |||
final String namespace, | |||
final String name, | |||
Object[] parameters) { | |||
JXPathFilter jxPathFilter = new JXPathFilter(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure, but I am a little bit worried that this can be quite limiting to developers. We force them to use System.setProperty in order to allow some classes in jxpath functions. Also, it is not possible to change the filter per JXContext
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should have some kind of interface JXPathFilter
that will have all required methods (e.g. isClassNameExposed(className)
) that will be used as the parameter of the overloaded method Functions.getFunction(...)
. The overloaded method would create the SystemPropertyJXPathFilter
implementation that uses system properties to specify filters.
Then we would add field to JXPathContext that would hold the default JXPathFilter for given context (by default our properties based filter). We would also add methods to change this filter, so that the developer can configure per-context filters.
The JXPathFilter
itself should be either interface with all the methods or just some filter-holder that would contain all the filters (interfaces JXPathClassFilter, JXPathXyzFilter, ...), so that we can pass it through the structure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the proposal. I've added an interface JXPathFilter
and an implementation SystemPropertyJXPathFilter
based on the system property of the allow list. Moreover, I have added a new default method getFunction
to the Functions
interface that takes a filter as a parameter. The default implementation simply calls the getFunction
without the filter and can be overridden by implemented classes. This guarantees binary compatibility as @garydgregory pointer out.
8a301f3
to
ea34611
Compare
This has the additional benefit of not breaking the binary compatibility of the Functions interface
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I finally got time to check the code of JXPath and I found out that this solution is unfortunately not secure enough. It will prevent the simple fully-qualified class name access, however, there is one more problem in the code. It still allows calling methods on context object like size
for List. There is also support for using methods on parameter objects (see for example PackageFunctions.getFunction(…)
and its block within parameters.length
condition. In the end, this functionality allows us to traverse the objects and also load any classes.
For example, I have created context for simple data class:
JXPathContext context = JXPathContext.newContext(new Data());
The class itself does not contain anything:
public class Data {
}
I also created DangerousClass
(in real-life scenario, this could be the ClassPathXmlApplicationContext
from Spring), which contains dangerous code:
public class DangerousClass {
public DangerousClass() {
System.out.println("Dangerous class created!");
}
public void run(String param) {
System.out.println(String.format("Running dangerous test with parameter '%s'!", param));
System.exit(42);
}
}
I have to start in context of Data.class
, but I can easily go and load the DangerousClass
and then invoke the dangerous function run
:
JXPathContext context = JXPathContext.newContext(new Data());
String jxPath = "run(newInstance(loadClass(getClassLoader(getClass(/)), \"com.warxim.dangerous.DangerousClass\")), \"warxim\")"
Object result = context.getValue(jxPath);
This will lead to the following output:
Dangerous class created!
Running dangerous test with parameter 'warxim'!
Process finished with exit code 42
Conclusion: It is crucial to secure all the mechanisms that allow calling methods on the objects.
Good point! The current implementation does not allow any classes if not otherwise configured by the user. We can merge and release this variant so that users can use get a secure version of the library. A default secure allow-list can be done in a follow-up update. |
@garydgregory No need to get all defensive, I did not want to start one of those discussions where a random nobody demands attention from a volunteer member of an open source project. I'm well aware of the situation and your work is very much appreciated. Apologies for the misunderstanding. My background is in security, so my expectations about what should happen whenever a critical vulnerability is found may be skewed a bit in favor of immediate action. So, do I understand correctly that this vulnerability is as serious as it sounds - that unsanitized user input into a JXPath expression leads to getting a remote shell, or is there some caveat I'm missing? If it's really this dangerous, would you please consider making a HotFix release of 1.3 with just this fix so that the users of And it's not like I'm just asking you to do more unpaid work - I'm willing to help too! If there's anything I can do to help move this along, just let me know. |
So, do I understand correctly that this vulnerability is as serious as it sounds - that unsanitized user input into a JXPath expression leads to getting a remote shell
As I understand it, it is about untrusted expressions not about untrusted payload instances or object trees. But I could be wrong, Is it both?
|
CVE-2022-41852 was issued in error and is in the process of being updated so the state becomes "rejected" / "disputed" / "issued in error" or whatever is the most appropriate state. |
We do not agree here. Xpath injections are pretty common, see https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=xpath. The past shows that a lot of applications from well-known companies were vulnerable to XPath injections when an attacker was able to control the XPath expression completely or partially. Sanitization of user input failed in multiple cases. It might be expected by developers that the worst-case scenario resulting from an XPath injection would be disclosing sensitive information, but no one would usually expect arbitrary code execution. In Apache Commons JXPath it is enough to have partial control of the XPath expression to call methods from an arbitrary class. @Warxim has demonstrated how easily an exploit might work, see https://hackinglab.cz/en/blog/remote-code-execution-in-jxpath-library-cve-2022-41852/. As a maintainer of a popular open-source library, you have no control over how users might use the library. We would appreciate it if apache-commons would take more responsibility here and start notifying users about the potential security risks related to untrusted input vectors instead of merely saying "library is not intended to parse untrusted input". The CVE description is valid since it clearly says "Those using JXPath to interpret untrusted XPath expressions may be vulnerable to a remote code execution attack". We are not arguing about an internal unexposed functionality here, but about an actual feature of the library that can have serious security implications. If you don't plan to assign CVEs for issues resulting from untrusted user input or plan to reject valid ones, you should consider adding a clear warning on the official project page along the lines: "Attention: The library is not intended to be used with untrusted input. Untrusted input could lead to Remote Code Execution, Denial of Service or other unexpected behavior". That would help developers to be aware of the potential security risks or consider switching to other libraries that are robust against untrusted input data. We also suggest adding such a warning to all apache-commons libraries that are not intended to be used with untrusted user input. Some small notes in the documentation are not enough to raise the required attention. In the case of JXpath, neither the current project page (https://github.com/apache/commons-jxpath) nor the user guide (https://commons.apache.org/proper/commons-jxpath/users-guide.html) contains any information that JXPath cannot safely handle untrusted input. |
Be careful, this is about xpath, and also even Jexl should handle data securely, it’s just a question if expressions/programs should be trusted or not. |
Not sure why there are some comments on JEXL which is a different library (commons-jexl) than commons-jxpath. The PR is for JXPath. But maybe I do not get the full picture. Yes, untrusted input could also be handled by the applications which are using commons-jxpath. But that would put the burden on hundreds of applications comming up with solutions on their own. And still they would not be sure if they did it correctly. The PR presented here makes jxpath secure by default - and hence should be shipped as soon as possible with high priority from my point of view. |
Sorry about the JEXL / JXPath mix-up. Trying to respond to lots of similar issues about projects with similar names. The CVE record has been updated to invalid so my request to edit the title of this PR to remove the CVE reference stands. My previous comments stand for JXPath. It is an expression language intended to manipulate (quoting from the project description) "graphs of objects of all kinds: JavaBeans, Maps, Servlet contexts, DOM etc, including mixtures thereof." It is not reasonable to expect a tool designed for that purpose to safely handle untrusted input unless using an API explicitly documented to do so. Hence this is not a security issue and will not be treated as such. Treating an application's XPath injection vulnerability as a issue in JXPath is equivalent to calling an application's SQL injection vulnerability an issue in the JDBC driver. The vulnerability is in the application, not the library the application is (ab)using. I have concerns about a filter approach for JXPath since experience across multiple projects has shown that trying to limit such tools to a subset of safe operations is difficult and typically leads to a long series issues being reported as researchers find loopholes that allow the filtering to be bypassed. However, those approaches often used deny lists whereas this PR uses an allow list so it is starting from a much safer position. I wonder if a JXPath equivalent (and it could be a very loose equivalent) to prepared statements in the SQL world could be useful. Generally, if the community consensus is to add some form of feature to handle unsafe input then it needs to be clearly documented for that purpose and the community has to be prepared to handle security vulnerability reports against that feature. |
@markt-asf I think a reasonable approach would be to make the default methods safe and provide an unsecured alternative for people who really need this functionality, with a big fat warning about injection risk. Thus, the casual users would be protected and the power users would still have all the tools they need. I like your idea about prepared statements too. |
For clarity, this is not true. The record has been marked DISPUTED which is entirely different to REJECT per the CVE website. (https://www.cve.org/ResourcesSupport/FAQs) Disputed is when there is disagreement between a vendor and security researcher so CVE Program leaves the record as is and updates the status. Rejected is when the record was placed in error and is not a vulnerability and the record could potentially be returned to the reserved pool in the future. The CVE is currently still valid and tied to the vulnerability just with the updated status so people can further research the vulnerability themselves. |
It is true that, similarly to SQL injections, Xpath injections are vulnerabilities in the applications that use the library. However, the application's responsibility ends when the library exposes functionality that enables propagating a vulnerability to other system components. In the case of SQL injections, the scope matters. If a crafted SQL payload would result in an injection that allows direct code execution outside the database context, we should treat this case as a security issue. There are multiple examples where libraries enabled code execution by mistake or as a feature. Those issues were addressed and fixed. Here are a few SQL examples:
Recently, Jazzer found an issue of a similar nature in OSS-Fuzz in a HyperSQL (https://nvd.nist.gov/vuln/detail/CVE-2022-41853). The maintainer quickly acknowledged the security risk and agreed to issue a CVE and a fix release. Based on the previous arguments, we still think this is a security issue for which a CVE should be issued. That said, I'll adjust the PR title to get it merged. Our goal here is to ensure that users get a secure version of the library and the PR title seems to be a blocker for this to happen. |
Now as @kyakdan has renamed the PR's title to "get it merged" - is there a plan / schedule when this will be done and a new version with this included will be released? It would be good if that could be communicated. |
There is no security vulnerability. This PR will be dealt with with the same priority as any other enhancement request. |
DISPUTED is the wrong state for these issues, then, they should be REJECT as they were placed in error, are not a vulnerability (as well as against CNA rules at the time of assignment). |
DISPUTED is the correct state since there is a dispute between the researcher and the maintainer. They CVE was not placed in error since obviously the researcher and others here do consider it a vulnerability. The DISPUTED tag tells individuals to research the issue; which they should do because this is an issue that could allow RCE in an application. At the very least having the CVE brings to light that there is no warning in the library to not pass untrusted input and encourages individuals to implement their own controls if the package maintainer will not. |
@markt-asf I understand if this is not in the threat model for JXPath. However, I can't seem to find any documentation explicitly stating JXPath should only be used to process trusted input, which could lead to user confusion and incorrect usages (which includes our fuzzing efforts). Would it make sense to update the documentation to make this fact very clear to users? I still think this PR as is provides a lot of values for users. Perhaps once this gets merged, we could also update documentation on how this can be used to provide users with a safe way of using JXPath on potentially untrusted inputs? |
OK, just saw that CVE-2022-41852 is marked as REJECTED: https://nvd.nist.gov/vuln/detail/CVE-2022-41852 |
I just saw this too. I disagree with this and think it should have remained DISPUTED but I'm not the CNA. At a minimum the documentation should be updated to highlight the risks of using this library and include that it should not accept any untrusted input. I think it's irresponsible to argue the CVE to be REJECTED without first updating the documentation since new users of the library may not be aware of this issue now. |
Agreed, it needs to be documented. Either as a warning that it is not possible to have untrusted expressions or with a pointer to the filter mechanism discussed here. I will propose something. |
This should work as a caveat as discussed in apache#26
Any comment on my PR? |
@garydgregory @markt-asf Is there any update on when this PR can be merged? |
@kyakdan in the current form, every class requested from ClassLoaderUtil needs to be whitelisted. |
Like many of the JXPath users community, I also think that this is a security issue because of JXPath's default configuration. The question for me now is, how all the usages of JXPath out there could be secured without having the project responsibles to change code in the project. But for all those concerned about having that security issue in their apps, there is (as far as I could find out) a secure way to get rid of the problem. You need to set the default "Functions" implementation to YOUR default instead of silently using the default from JXPathContext (which is JXPathContext.GENERIC_FUNCTIONS ). All you have to do is adding the following line for each instance of JXPathContext in your Application: Of course, you will loose any way of using direct Java Class functions. But the approach also offers the possibility to add your own, secured implementation of the JXPath's PackageFunction, which could be one with a "whitelist" approach like proposed in this thread. You could even provide your own JXPathContextFactory to your Application VM such that any Usage of JXPathContext.newContext() will return a secured context by default. |
You can provide a pattern to allow a group of classes, e.g., |
I don’t think „most“ is correct, since this was not much requested before and many users probably only issue static jxpath expressions or use it as a cheap java eval language anyway. having said that, your mentioning of the FunctionLibrary is on point, and it also looks like a better way to filter. Jxpath can just ship (configurable) alternatives, which especially have allow lists for functions, can turn java evaluation off or restrict classes and methods (similar to like the PR does, ideally without the need to allow internal methods) |
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.
Remote Code Execution (RCE)
Issue reported here is, all functions in the class JXPathContext (except compile and compilePath) are vulnerable to a remote code execution attack when used with untrusted input.
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());
No workaround available
The fix added here is via a new system property "jxpath.class.allow". This list is empty by default meaning that nothing is allowed by default. Users should then explicitly configure which classes are allowed.
This is based on #25 and the logic is changed from a deny list into an allow list