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:
- Patterns are evaluated left-to-right
- Rejection patterns (
!) take precedence over allowlist patterns - First matching pattern determines the result
- 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:
- Test all session operations (create, read, update, delete).
- Verify that the session attributes deserialize correctly.
- Test session failover scenarios.
- Monitor logs for
ObjectInputFilterrejections.
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:
- Verify
web.xmlis packaged correctly in the WAR - Redeploy the WAR file completely
- Check application server logs for errors
- 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
Identify Session Attribute Classes
- List all classes stored in HTTP sessions
- Include transitive dependencies (classes referenced by session objects)
Create Filter Pattern
- Start with your application packages
- Add essential Java packages
- End with
!*
Test in Development
- Deploy with filter enabled
- Exercise all session operations
- Fix any deserialization failures
Deploy to Production
- Add filter to
web.xml - Redeploy WAR file (zero downtime)
- Monitor logs for unexpected rejections
- Add filter to
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