I am implementing XML validation which prevents XXE (External XML Entity) Injection. I borrowed some code from OWASP XXE Prevention Cheat Sheet. My code looks like this -
SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = factory.newSchema(xsdFileURL);
Validator validator = schema.newValidator();
validator.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
validator.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
validator.validate(new StreamSource(new StringReader(xml)));
The code runs correctly on my local windows machine (JDK 1.8.0_92, Wildfly 8.2). But on a QA Red Hat machine with similar config (JDK - 1.8.0_101, Wildfly 8.2), it throws an exception with the message -
Property 'http://javax.xml.XMLConstants/property/accessExternalDTD' is not recognized.
After some reading my suspicion is that during runtime, incorrect class definition is being read for the validator class. How do I fix this?
Update
Turns out Jboss comes with its own implementation of JAXP, and my code needs to pick the JAXP implementation from JDK and not from JBoss. I can do this easily by passing -jaxpmodule argument in standalone.sh (using this, my code picked the correct JAXP implementation as well) -
java -jar jboss-modules.jar -jaxpmodule "javax.xml.jaxp-provider"
But I'd like to do this using jboss-deployment-structure.xml and add an exclusion like this -
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<deployment>
<exclusions>
<module name="javax.api" /> // is the module name correct?
</exclusions>
</deployment>
</jboss-deployment-structure>
But this isn't working, how can I fix this?
As you mentioned in your update, JBoss/Wildfly does ship its own JAXP implementation - Xalan (and Xerces). As such, it uses that implementation as it builds the classpath for your deployed application(s).
You can override this behavior in your jboss-deployment-structure.xml file as follows:
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.2">
<deployment>
<exclusions>
<module name="org.apache.xalan" />
<module name="org.apache.xerces" />
</exclusions>
</deployment>
</jboss-deployment-structure>
Instead of trying to remove JARs from the Server's runtime.It is always advisable to exclude these JARs from your project at runtime.E.g. If you are using Maven for dependency management,then for this particular JAR in your pom.xml,you can just provide scope for this JAR as "provided".Provided scope indicates that this JAR will be used for compile time and at runtime it will be provided by runtime itself.
Related
I have SpringBoot app (1.4.3.RELEASE). Recently I have upgraded Jackson (com.fasterxml.jackson.datatype, com.fasterxml.jackson.core) from 2.8.5 to 2.12.2 because of polymorphic subtype deduction feature. Everything works just fine on my local development environment during unit tests and also when I'm running app from IDE.
The problem occurs when I push my changes to build and deploy it on development environment, where app is deployed on Wildfly 21.0.2. (as a WAR archive). Calling ObjectMapper#readValue throws java.lang.EnumConstantNotPresentException (detailed stack below).
There are no enums used in objects which I'm deserializing and I have already checked through Wildfly management console, that there is correct version of Jackson on deployed app. Now I am a bit clueless. Any ideas?
com.fasterxml.jackson.annotation.JsonTypeInfo$Id.DEDUCTION
at com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector._findTypeResolver(JacksonAnnotationIntrospector.java:1424)
at com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector.findTypeResolver(JacksonAnnotationIntrospector.java:522)
at com.fasterxml.jackson.databind.introspect.AnnotationIntrospectorPair.findTypeResolver(AnnotationIntrospectorPair.java:225)
at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory.findTypeDeserializer(BasicDeserializerFactory.java:1584)
at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory.findPropertyTypeDeserializer(BasicDeserializerFactory.java:1748)
at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory.resolveMemberAndTypeAnnotations(BasicDeserializerFactory.java:2116)
at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory.constructCreatorProperty(BasicDeserializerFactory.java:1000)
at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory._addExplicitPropertyCreator(BasicDeserializerFactory.java:634)
at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory._addDeserializerConstructors(BasicDeserializerFactory.java:407)
at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory._constructDefaultValueInstantiator(BasicDeserializerFactory.java:283)
at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory.findValueInstantiator(BasicDeserializerFactory.java:224)
at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.buildBeanDeserializer(BeanDeserializerFactory.java:220)
at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.createBeanDeserializer(BeanDeserializerFactory.java:143)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer2(DeserializerCache.java:414)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer(DeserializerCache.java:349)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:264)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:244)
at com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer(DeserializerCache.java:142)
at com.fasterxml.jackson.databind.DeserializationContext.findRootValueDeserializer(DeserializationContext.java:479)
at com.fasterxml.jackson.databind.ObjectMapper._findRootDeserializer(ObjectMapper.java:4405)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4214)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3214)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3197)
Well, the problem was solved by explicit exclusion of Jackson related libraries in jboss-deployment-structure.xml file (as shown on code below). Without these exlusions Wildfly was forcing its own Jackson lib located in /wildfly/modules/system/layers/base/ path (e.g. wildfly/modules/system/layers/base/com/fasterxml/jackson/core/jackson-core) which is 2.10.5 for Wildfly 21.0.2. Wildfy is doing this regardless of specifing custom version in maven pom.xml. Also I wasn't able to find any mention about this "embedded" Jackson version in Wildfly through management console, so it was a bit pain to realize where is the problem. Maybe this will save someone else some time.
<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.3">
<deployment>
<exclusions>
<module name="com.fasterxml.jackson.core.jackson-core" />
<module name="com.fasterxml.jackson.core.jackson-databind" />
<module name="com.fasterxml.jackson.datatype.jackson-datatype-jdk8" />
<module name="com.fasterxml.jackson.datatype.jackson-datatype-jsr310" />
<module name="com.fasterxml.jackson.jaxrs.jackson-jaxrs-json-provider" />
<module name="org.jboss.resteasy.resteasy-jackson2-provider" />
</exclusions>
<dependencies>
<module name="jdk.unsupported"/>
</dependencies>
</deployment>
</jboss-deployment-structure>
I didn't think I would end up here but after a lot of Google and StackOverflow searches here I'm.
This is my exact problem except that I can't afford to make code changes.
The WAR I'm trying to deploy includes a JMS library (i.e. javax.jms, which I cannot exclude form the WAR.) which is already loaded by Jboss EAP 7 by default. The path to jar is something like this jboss/modules/system/layers/base/javax/jms/api/ain/jboss-jms-api_2.0_spec-1.0.0.Final-redhat-1.jar. Because of this two different versions of the same classes loading I'm getting ClassCastException.
org.apache.activemq-ra.ActiveMQConnectionFactory cannot to be cast to javax.jms.ConnectionFactory
So, I want Jboss to NOT load javax.jms so that my application can use the JAR included with the WAR.
So, I was wondering if there was any way to exclude the module globally (for all WAR deployments).
Excluding it per deployment would work too. And I do realize it can be acheivd using jboss-deployment-structure.xml but I can't get it to work.
Here is what I tried:
<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure
xmlns="urn:jboss:deployment-structure:1.2">
<deployment>
<exclude-subsystems>
<subsystem name="javax" />
<subsystem name="javax.jms" />
</exclude-subsystems>
</deployment>
</jboss-deployment-structure>
and
<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure
xmlns="urn:jboss:deployment-structure:1.2">
<deployment>
<exclusions>
<module name="javax" />
<module name="javax.jms" />
<module name="javax.jms.api" />
</exclusions>
</deployment>
</jboss-deployment-structure>
I placed the file in WEB-INF directory. It didn't work. It still loaded the JMS class from modules folder of Jboss EAP. So, how do I correctly do this?
The correct jboss-deployment-structure.xml is here:
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.2">
<deployment>
<exclude-subsystems>
<subsystem name="messaging-activemq"></subsystem>
</exclude-subsystems>
<exclusions>
<module name="javax.jms.api"></module>
</exclusions>
</deployment>
</jboss-deployment-structure>
This way you exclude both messaging subsystem and the JMS api.
You should remove the JMS API JAR from your deployment. You can still keep the JMS implementation JAR in your deployment but that should probably end up in a RAR, preferably outside your deployment.
This link has some things you could try.
Notably:
I think the problem is that activemq-all-5.4.2.jar contains javax.jms.*. Your deployment already gets this implicitly from the javaee.api module (see more information about implicity module dependencies here). I don't think it is appropriate for an application module/jar to package Java EE interfaces. You can try simply deleting the javax directory from activemq-all-5.4.2.jar or using a different set of ActiveMQ jars in your module to limit it to only what you need.
and/or altering your module.xml for ActiveMQ
<module xmlns="urn:jboss:module:1.0" name="activemq">
<resources>
<resource-root path="activemq-all-5.4.2.jar"/>
</resources>
<dependencies>
<module name="javax.api"/>
</dependencies>
</module>
There appears to be a method to embed ActiveMQ in Jboss as well, if you're interested. I won't pull out information from that article, as it doesn't answer the original question.
I have a web application which uses Log4j2 and I am deploying it on JbossEAP 6.0.
However I am using some libraries which still use Log4j. So for this I have added the log4j-1.2 api jar provided for log4j2. The issue I am facing is that my application is logging everything using log4j2 but the libraries are still logging using log4j.
I am guessing that this is because Jboss is adding its own copy of log4j to the classpath. Hence I tried by excluding that module by defining it to be excluded in the jboss-deployment-structure.xml file.
However it is still not working.
Please help.Thanks.
jboss-deployment-structure.xml:
<jboss-deployment-structure>
<deployment>
<!-- Exclusions allow you to prevent the server from automatically adding some dependencies -->
<exclusions>
<module name="org.apache.log4j" />
</exclusions>
</deployment>
</jboss-deployment-structure>
I am getting this error:
java.lang.ClassCastException: org.apache.jcp.xml.dsig.internal.dom.DOMReference cannot be cast to org.jcp.xml.dsig.internal.dom.DOMReference
Maybe the problem is on the jboss-deployment-structure.xml of the servlet:
<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.1">
<deployment>
<dependencies>
<module name="javax.api"/>
<module name="org.apache.santuario.xmlsec"/>
<module name="org.apache.xerces" />
<system export="true">
<paths>
<path name="com/sun/org/apache/xerces/internal/dom"/>
</paths>
</system>
</dependencies>
</deployment>
</jboss-deployment-structure>
Do you have any hint of whats going on?
Thanks in advance.
Your problem is different xmlsec library version.
org.apache.jcp.xml.dsig.internal.dom.DOMReference located in xmlsec-1.5.1.jar (org.apache.santuario.xmlsec module in JBoss)
org.jcp.xml.dsig.internal.dom.DOMReference located in xmlsec-1.4.3.jar (dependency in your pom.xml)
Jboss 7 uses isolated modules https://docs.jboss.org/author/display/AS7/Class+Loading+in+AS7 it is complicated and i really don't know how it works inside.
But if simplify, when jboss start, it loads xmlsec-1.5.1, when start your application, it loads xmlsec-1.4.3. As result you have class cast exception, when pass DOMReference object between jboss and webapp classloders.
You can resolve your issue in different ways:
remove dependency of org.apache.santuario.xmlsec module in jboss-deployment-structure.xml. Application will use his own defined xmlsec-1.4.3 library
locate dependency xmlsec in pom.xml, set version to 1.5.1, and set scope to provided. Application will use JBoss module with xmlsec-1.5.1
locate dependency xmlsec in pom.xml and exclude it completly, if your code complies without xmlsec dependency. Application will use JBoss module with xmlsec-1.5.1
mvn:dependency:tree command helps here.
I have a problem that is driving me nuts for three days.
I was deployed spring-eap6-quickstart code according to tutorial on the OpenShift account. I'm configured debug options and I'm synchronized eclipse workspace with OpehShift server - everything on the server is working properly, but in Eclipse I got an error that I can not eliminate.
I have this error:
cvc-complex-type.2.4.a: Invalid content was found starting with element 'deployment'. One of '{ear-subdeployments-isolated, deployment, sub-deployment, module}' is expected. jboss-deployment-structure.xml /spring-eap6-quickstart/src/main/webapp/WEB-INF line 2
That indicates error on deployment tag.
My jboss-deployment structure xml is:
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.0">
<deployment>
<dependencies>
<module name="com.h2database.h2"/>
<module name="org.codehaus.jackson.jackson-core-asl"/>
<module name="org.codehaus.jackson.jackson-mapper-asl"/>
<module name="org.slf4j"/>
</dependencies>
</deployment>
</jboss-deployment-structure>
When I changed deployment structure to:
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:2.0">
this change in eclipse corrects the error, but then the application does not work on OpenShift server.
I realize that the problem is in the setup, but I do not know how to overcome problem. Did anyone knows what I have to do? Please help. Thank You.
Your xml is absolutely valid when using urn:jboss:deployment-structure:1.0. Unfortunately there are errors in the jbossas deployment-structure scheme and thus Eclipse will complain:
https://issues.jboss.org/browse/JBIDE-15311
Bumping the version of the referred scheme to 2.0 fixes it in Eclipse by referring an inexistent scheme, 2.0 does not exist yet. Thus OpenShift will then fail. There's currently 1.0, 1.1 and 1.2. The upcoming 2.0 should fix the scheme and thus have Eclipse validating properly. But we're not there yet unfortunately. I suggest that you simply turn the validation off, either all or only the scheme validation: Window->Preferences->Validation:
update your xml to define the namespace, ie:
<?xml version="1.0" encoding="UTF-8"?>
<jds:jboss-deployment-structure xmlns:jds="urn:jboss:deployment-structure:1.0">
<deployment>
<dependencies>
<module name="org.dom4j" />
</dependencies>
</deployment>
</jds:jboss-deployment-structure>