Apache Geode CHANGELOG

Securing HTTP Session Deserialization

This topic describes how to configure session deserialization security using ObjectInputFilter (JEP 290) to protect against deserialization vulnerabilities.

Overview

Apache Geode HTTP Session Management uses Java serialization to store session attributes in the distributed cache. To protect against deserialization attacks, you can configure an ObjectInputFilter that controls which classes are allowed to be deserialized.

Key Benefits:

  • Application-Level Security: Each web application defines its own security policy
  • Zero-Downtime Configuration: Changes take effect on WAR deployment and no cluster restart is required
  • Defense in Depth: Explicit allowlist prevents gadget chain attacks
  • Backward Compatibility: Existing applications continue to work without configuration

Security Warning

Always configure a deserialization filter for production deployments.

Without a configured filter, session deserialization has NO restrictions. Any serializable class can be deserialized, leaving your application vulnerable to:

  • Remote Code Execution (RCE)
  • Denial of Service (DoS)
  • Arbitrary object instantiation attacks

Basic Configuration

Step 1: Add Filter Pattern to web.xml

Add a context parameter to your application’s web.xml:

<web-app>
  <context-param>
    <param-name>serializable-object-filter</param-name>
    <param-value>com.myapp.model.**;java.lang.**;!*</param-value>
  </context-param>

  <!-- Your existing filter configuration -->
  <filter>
    <filter-name>gemfire-session-filter</filter-name>
    <filter-class>org.apache.geode.modules.session.filter.SessionCachingFilter</filter-class>
  </filter>
  <!-- ... -->
</web-app>

Step 2: Deploy WAR File

Deploy or redeploy your WAR file to the application server. The filter takes effect immediately and no cluster restart is required.

Pattern Syntax

The filter pattern follows JEP 290 syntax:

Pattern Meaning
com.myapp.** Allow all classes in com.myapp package and subpackages
com.myapp.model.User Allow specific class only
java.lang.**; java.util.**; java.time.** Allow essential Java packages
!com.dangerous.** Explicitly reject package (takes precedence)
!* Reject everything else (default deny)

Pattern Evaluation Order:

  1. Patterns are evaluated left-to-right
  2. Rejection patterns (!) take precedence over allowlist patterns
  3. First matching pattern determines the result
  4. Always end with !* for default deny

Configuration Examples

Minimal Configuration

Allow only your application models and essential Java classes:

<param-value>
  com.myapp.model.**;
  java.lang.**;java.util.**;
  !*
</param-value>

E-Commerce Application

<param-value>
  com.shop.model.**;
  com.shop.cart.**;
  com.payment.dto.**;
  java.lang.**;java.util.**;java.time.**;
  !*
</param-value>

Multi-Module Application

<param-value>
  com.company.common.**;
  com.company.customer.**;
  com.company.order.**;
  java.lang.**;java.util.**;java.math.BigDecimal;
  !com.company.internal.**;
  !*
</param-value>

Rejecting Specific Classes

<param-value>
  com.myapp.**;
  !com.myapp.deprecated.**;
  !com.myapp.legacy.OldClass;
  java.lang.**;java.util.**;
  !*
</param-value>

Multi-Application Deployments

Each web application has its own isolated security policy:

Application 1 (E-commerce): xml <param-value> com.shop.model.**; com.payment.**; java.lang.**;java.util.**; !* </param-value>

Application 2 (Analytics): xml <param-value> com.analytics.**; com.ml.models.**; java.lang.**;java.util.**; !* </param-value>

Application 3 (CMS): xml <param-value> com.cms.content.**; java.lang.**;java.util.**; !* </param-value>

Each application’s sessions can only deserialize classes allowed by its specific filter pattern.

Best Practices

1. Use Explicit Allowlists

Don’t: xml <param-value>*</param-value> <!-- Allows everything, insecure -->

Do: xml <param-value> com.myapp.safe.**; java.lang.**;java.util.**; !* </param-value>

2. Always End with !*

This creates a default-deny policy where only explicitly allowed classes can be deserialized.

3. Be Specific with Package Names

Less secure: xml <param-value>com.**;!*</param-value> <!-- Too broad -->

More secure: xml <param-value>com.myapp.model.**;!*</param-value> <!-- Specific -->

4. Include Essential Java Packages

Most applications need these: xml java.lang.**; java.util.**; java.time.**;

5. Test Thoroughly

After configuring the filter:

  1. Test all session operations (create, read, update, delete).
  2. Verify that the session attributes deserialize correctly.
  3. Test session failover scenarios.
  4. Monitor logs for ObjectInputFilter rejections.

Troubleshooting

ClassNotFoundException or Deserialization Failures

Symptom: Session attributes fail to deserialize after adding filter

Solution: Add the missing class package to your filter pattern:

<param-value>
  com.myapp.model.**;
  com.thirdparty.library.**;  <!-- Add missing package -->
  java.lang.**;java.util.**;
  !*
</param-value>

Filter Not Working

Symptom: Filter pattern changes are not applied

Solution:

  1. Verify web.xml is packaged correctly in the WAR
  2. Redeploy the WAR file completely
  3. Check application server logs for errors
  4. Verify parameter name is exactly serializable-object-filter

Session Attribute Classes Rejected

Symptom: Logs show “ObjectInputFilter rejected class: com.myapp.NewClass”

Solution: Add the class or package to your allowlist:

<param-value>
  com.myapp.model.**;
  com.myapp.NewClass;  <!-- Add specific class -->
  java.lang.**;java.util.**;
  !*
</param-value>

Migration Guide

For Existing Applications

  1. Identify Session Attribute Classes

    • List all classes stored in HTTP sessions
    • Include transitive dependencies (classes referenced by session objects)
  2. Create Filter Pattern

    • Start with your application packages
    • Add essential Java packages
    • End with !*
  3. Test in Development

    • Deploy with filter enabled
    • Exercise all session operations
    • Fix any deserialization failures
  4. Deploy to Production

    • Add filter to web.xml
    • Redeploy WAR file (zero downtime)
    • Monitor logs for unexpected rejections

Backward Compatibility

Without Filter Configuration: Sessions continue to work as they did prior. There are no breaking changes. There is no security protection (vulnerable).

With Filter Configuration: Explicit security policy is enforced. Only allowed classes can be deserialized. You are protected against deserialization attacks.

Security Reference

JEP 290

The filter implementation uses Java’s JEP 290: Filter Incoming Serialization Data, which provides:

  • Per-stream filtering capability
  • Pattern-based class allowlists/denylists
  • Built-in protection against known gadget chains

Additional Resources