High severityNVD Advisory· Published Feb 15, 2018· Updated Sep 16, 2024
CVE-2017-15089
CVE-2017-15089
Description
It was found that the Hotrod client in Infinispan before 9.2.0.CR1 would unsafely read deserialized data on information from the cache. An authenticated attacker could inject a malicious object into the data cache and attain deserialization on the client, and possibly conduct further attacks.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
org.infinispan:infinispan-coreMaven | < 9.2.0.CR1 | 9.2.0.CR1 |
Affected products
1- Range: before 9.2.0.CR1
Patches
22944b0d1369aISPN-8624 Custom marshaller implementors should verify class names
3 files changed · +5 −2
commons/src/main/java/org/infinispan/commons/marshall/jboss/AbstractJBossMarshaller.java+1 −1 modified@@ -37,7 +37,7 @@ */ public abstract class AbstractJBossMarshaller extends AbstractMarshaller implements StreamingMarshaller { - private static final Log log = LogFactory.getLog(AbstractJBossMarshaller.class); + protected static final Log log = LogFactory.getLog(AbstractJBossMarshaller.class); private static final boolean trace = log.isTraceEnabled(); protected static final JBossMarshallerFactory factory = new JBossMarshallerFactory(); protected static final int DEF_INSTANCE_COUNT = 16;
documentation/src/main/asciidoc/user_guide/server_protocols_hotrod.adoc+3 −0 modified@@ -970,6 +970,9 @@ The number of connections per server, total number of connections, how long shou ==== Marshalling data The Hot Rod client allows one to plug in a custom marshaller for transforming user objects into byte arrays and the other way around. This transformation is needed because of Hot Rod's binary nature - it doesn't know about objects. +.WARNING: If developing your own custom marshaller, take care of potential injection attacks. +To avoid such attacks, make the marshaller verify that any class names read, before instantiating it, is amongst the expected/allowed class names. + The marshaller can be plugged through the "marshaller" configuration element (see Configuration section): the value should be the fully qualified name of a class implementing the link:{javadocroot}/org/infinispan/marshall/Marshaller.html[Marshaller] interface. This is a optional parameter, if not specified it defaults to the link:{javadocroot}/org/infinispan/marshall/jboss/GenericJBossMarshaller.html[GenericJBossMarshaller] - a highly optimized implementation based on the link:http://www.jboss.org/jbossmarshalling[JBoss Marshalling] library. Since version 6.0, there's a new marshaller available to Java Hot Rod clients based on Protostream which generates portable payloads. You can find more information about it <<_querying_via_the_java_hot_rod_client,here>>
integrationtests/compatibility-mode-it/src/test/java/org/infinispan/it/compatibility/CompatibilityCacheFactory.java+1 −1 modified@@ -167,7 +167,7 @@ private void createHotRodCache(HotRodServer server) { hotrod = server; hotrodClient = new RemoteCacheManager(new ConfigurationBuilder() .addServers("localhost:" + hotrod.getPort()) - .addJavaSerialWhiteList(".*Person.*") + .addJavaSerialWhiteList(".*Person.*", ".*CustomEvent.*") .marshaller(marshaller) .build()); hotrodCache = cacheName.isEmpty()
1deadcb1c74eISPN-8624 White list unmarshalling for GenericJBossMarshaller
6 files changed · +113 −15
client/hotrod-client/src/main/java/org/infinispan/client/hotrod/marshall/MarshallerUtil.java+2 −14 modified@@ -7,14 +7,13 @@ import java.io.ObjectStreamClass; import java.io.ObjectStreamConstants; import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import org.infinispan.client.hotrod.exceptions.HotRodClientException; import org.infinispan.client.hotrod.impl.protocol.HotRodConstants; import org.infinispan.client.hotrod.logging.Log; import org.infinispan.client.hotrod.logging.LogFactory; import org.infinispan.commons.CacheException; +import org.infinispan.commons.marshall.MarshallUtil; import org.infinispan.commons.marshall.Marshaller; import org.infinispan.commons.util.Util; @@ -100,18 +99,7 @@ public CheckedInputStream(InputStream in, List<String> whitelist) throws IOExcep @Override protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { //Enforce SerialKiller's whitelist - boolean safeClass = false; - for (String whiteRegExp : whitelist) { - Pattern whitePattern = Pattern.compile(whiteRegExp); - Matcher whiteMatcher = whitePattern.matcher(desc.getName()); - if (whiteMatcher.find()) { - safeClass = true; - - if (log.isTraceEnabled()) - log.tracef("Whitelist match: '%s'", desc.getName()); - } - } - + boolean safeClass = MarshallUtil.isSafeClass(desc.getName(), whitelist); if (!safeClass) throw log.classNotInWhitelist(desc.getName());
client/hotrod-client/src/main/java/org/infinispan/client/hotrod/RemoteCacheManager.java+6 −1 modified@@ -35,6 +35,7 @@ import org.infinispan.commons.api.CacheContainerAdmin; import org.infinispan.commons.executors.ExecutorFactory; import org.infinispan.commons.marshall.Marshaller; +import org.infinispan.commons.marshall.jboss.GenericJBossMarshaller; import org.infinispan.commons.util.FileLookupFactory; import org.infinispan.commons.util.Util; import org.infinispan.commons.util.uberjar.ManifestUberJarDuplicatedJarsWarner; @@ -201,7 +202,11 @@ public void start() { if (marshaller == null) { marshaller = configuration.marshaller(); if (marshaller == null) { - marshaller = Util.getInstance(configuration.marshallerClass()); + Class<? extends Marshaller> clazz = configuration.marshallerClass(); + if (clazz == GenericJBossMarshaller.class && !configuration.serialWhitelist().isEmpty()) + marshaller = new GenericJBossMarshaller(configuration.serialWhitelist()); + else + marshaller = Util.getInstance(clazz); } }
client/hotrod-client/src/test/java/org/infinispan/client/hotrod/marshall/WhiteListMarshallingTest.java+39 −0 added@@ -0,0 +1,39 @@ +package org.infinispan.client.hotrod.marshall; + +import org.infinispan.client.hotrod.RemoteCacheManager; +import org.infinispan.client.hotrod.configuration.ConfigurationBuilder; +import org.infinispan.client.hotrod.exceptions.HotRodClientException; +import org.infinispan.client.hotrod.test.InternalRemoteCacheManager; +import org.infinispan.client.hotrod.test.SingleHotRodServerTest; +import org.infinispan.test.data.Person; +import org.testng.annotations.Test; + +import java.io.Serializable; + +@Test(testName = "client.hotrod.marshall.WhiteListMarshallingTest", groups = {"functional", "smoke"} ) +public class WhiteListMarshallingTest extends SingleHotRodServerTest { + + @Override + protected RemoteCacheManager getRemoteCacheManager() { + ConfigurationBuilder builder = new ConfigurationBuilder(); + builder.addJavaSerialWhiteList(".*Person.*"); + builder.addServer().host("127.0.0.1").port(hotrodServer.getPort()); + return new InternalRemoteCacheManager(builder.build()); + } + + @Test(expectedExceptions = HotRodClientException.class, + expectedExceptionsMessageRegExp = ".*ISPN004034:.*") + public void testUnsafeClassNotAllowed() { + remoteCacheManager.getCache().put("unsafe", new UnsafeClass()); + remoteCacheManager.getCache().get("unsafe"); + } + + public void testSafeClassAllowed() { + remoteCacheManager.getCache().put("safe", new Person()); + remoteCacheManager.getCache().get("safe"); + } + + private static final class UnsafeClass implements Serializable { + } + +}
commons/src/main/java/org/infinispan/commons/logging/Log.java+4 −0 modified@@ -6,6 +6,7 @@ import java.io.IOException; import org.infinispan.commons.CacheConfigurationException; +import org.infinispan.commons.CacheException; import org.infinispan.commons.dataconversion.EncodingException; import org.infinispan.counter.exception.CounterException; import org.infinispan.counter.exception.CounterOutOfBoundsException; @@ -185,4 +186,7 @@ public interface Log extends BasicLogger { //----- counters exceptions ------ + @Message(value = "Class '%s' blocked by deserialization white list. Adjust the client configuration serialization white list regular expression to include this class.", id = 28023) + CacheException classNotInWhitelist(String className); + }
commons/src/main/java/org/infinispan/commons/marshall/jboss/GenericJBossMarshaller.java+32 −0 modified@@ -1,5 +1,11 @@ package org.infinispan.commons.marshall.jboss; +import org.infinispan.commons.marshall.MarshallUtil; +import org.jboss.marshalling.Unmarshaller; + +import java.io.IOException; +import java.util.List; + /** * A marshaller that makes use of <a href="http://www.jboss.org/jbossmarshalling">JBoss Marshalling</a> * to serialize and deserialize objects. This marshaller is oriented at external, @@ -23,4 +29,30 @@ public GenericJBossMarshaller(ClassLoader classLoader) { new DefaultContextClassResolver(classLoader != null ? classLoader : this.getClass().getClassLoader())); } + public GenericJBossMarshaller(List<String> whitelist) { + super(); + baseCfg.setClassResolver( + new CheckedClassResolver(whitelist, this.getClass().getClassLoader())); + } + + private static final class CheckedClassResolver extends DefaultContextClassResolver { + + private final List<String> whitelist; + + CheckedClassResolver(List<String> whitelist, ClassLoader defaultClassLoader) { + super(defaultClassLoader); + this.whitelist = whitelist; + } + + @Override + public Class<?> resolveClass(Unmarshaller unmarshaller, String name, long serialVersionUID) throws IOException, ClassNotFoundException { + boolean safeClass = MarshallUtil.isSafeClass(name, whitelist); + if (!safeClass) + throw log.classNotInWhitelist(name); + + return super.resolveClass(unmarshaller, name, serialVersionUID); + } + + } + }
commons/src/main/java/org/infinispan/commons/marshall/MarshallUtil.java+30 −0 modified@@ -6,10 +6,15 @@ import java.io.ObjectInput; import java.io.ObjectOutput; import java.util.Collection; +import java.util.List; import java.util.Map; import java.util.Objects; import java.util.UUID; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.infinispan.commons.logging.Log; +import org.infinispan.commons.logging.LogFactory; import org.infinispan.commons.util.Util; import net.jcip.annotations.Immutable; @@ -25,6 +30,8 @@ public class MarshallUtil { private static final byte NULL_VALUE = -1; + private static final Log log = LogFactory.getLog(MarshallUtil.class); + /** * Marshall the {@code map} to the {@code ObjectOutput}. * <p> @@ -482,6 +489,29 @@ public static <T extends Collection<Integer>> T unmarshallIntCollection(ObjectIn return collection; } + /** + * Checks whether class name is matched by the class name white list regular expressions provided. + * + * @param className class to verify + * @param whitelist list of regular expressions to match class name against + * @return true if the class matched at least one of the regular expressions, + * false otherwise + */ + public static boolean isSafeClass(String className, List<String> whitelist) { + for (String whiteRegExp : whitelist) { + Pattern whitePattern = Pattern.compile(whiteRegExp); + Matcher whiteMatcher = whitePattern.matcher(className); + if (whiteMatcher.find()) { + if (log.isTraceEnabled()) + log.tracef("Whitelist match: '%s'", className); + + return true; + } + } + + return false; + } + @FunctionalInterface public interface ArrayBuilder<E> { E[] build(int size);
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
13- access.redhat.com/errata/RHSA-2018:0294ghsavendor-advisoryx_refsource_REDHATWEB
- access.redhat.com/errata/RHSA-2018:0478ghsavendor-advisoryx_refsource_REDHATWEB
- access.redhat.com/errata/RHSA-2018:0479ghsavendor-advisoryx_refsource_REDHATWEB
- access.redhat.com/errata/RHSA-2018:0480ghsavendor-advisoryx_refsource_REDHATWEB
- access.redhat.com/errata/RHSA-2018:0481ghsavendor-advisoryx_refsource_REDHATWEB
- access.redhat.com/errata/RHSA-2018:0501ghsavendor-advisoryx_refsource_REDHATWEB
- access.redhat.com/errata/RHSA-2019:1326ghsavendor-advisoryx_refsource_REDHATWEB
- github.com/advisories/GHSA-46r5-59fg-2fjcghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2017-15089ghsaADVISORY
- www.securitytracker.com/id/1040360mitrevdb-entryx_refsource_SECTRACK
- github.com/infinispan/infinispan/commit/1deadcb1c74ea0337abd5382c0150b000f6b106fghsaWEB
- github.com/infinispan/infinispan/commit/2944b0d1369a230bde88392b222921537c99331eghsaWEB
- github.com/infinispan/infinispan/pull/5639ghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.