VYPR
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.

PackageAffected versionsPatched versions
org.infinispan:infinispan-coreMaven
< 9.2.0.CR19.2.0.CR1

Affected products

1

Patches

2
2944b0d1369a

ISPN-8624 Custom marshaller implementors should verify class names

https://github.com/infinispan/infinispanGalder ZamarreñoDec 13, 2017via ghsa
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()
    
1deadcb1c74e

ISPN-8624 White list unmarshalling for GenericJBossMarshaller

https://github.com/infinispan/infinispanGalder ZamarreñoDec 13, 2017via ghsa
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

News mentions

0

No linked articles in our index yet.