-
Notifications
You must be signed in to change notification settings - Fork 0
Introduced protections against deserialization attacks #16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Introduced protections against deserialization attacks #16
Conversation
<groupId>com.h2database</groupId> | ||
<artifactId>h2</artifactId> | ||
</dependency> | ||
<dependency> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This library holds security tools for protecting Java API calls.
License: MIT ✅ | Open source ✅ | More facts
<version>${system-lambda.version}</version> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This library holds security tools for protecting Java API calls.
License: MIT ✅ | Open source ✅ | More facts
<artifactId>junit-jupiter-engine</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This library holds security tools for protecting Java API calls.
License: MIT ✅ | Open source ✅ | More facts
<dependency> | ||
<groupId>io.github.pixee</groupId> | ||
<artifactId>java-security-toolkit</artifactId> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This library holds security tools for protecting Java API calls.
License: MIT ✅ | Open source ✅ | More facts
Unable to locate .performanceTestingBot config file |
Micro-Learning Topic: Deserialization attack (Detected by phrase)Matched on "deserialization attack"It is often convenient to serialize objects for communication or to save them for later use. However, serialized data or code can be modified. This malformed data or unexpected data could be used to abuse application logic, deny service, or execute arbitrary code when deserialized. This is usually done with "gadget chains Try a challenge in Secure Code WarriorHelpful references
Micro-Learning Topic: Deserialization of untrusted data (Detected by phrase)Matched on "Deserialization of untrusted data"It is often convenient to serialize objects for communication or to save them for later use. However, serialized data or code can be modified. This malformed data or unexpected data could be used to abuse application logic, deny service, or execute arbitrary code when deserialized. This is usually done with "gadget chains Try a challenge in Secure Code WarriorHelpful references
|
Reviewer's Guide by SourceryThis PR implements security hardening for Java deserialization operations by adding ObjectInputFilter protection. The implementation adds a security filter to all ObjectInputStream instances to prevent deserialization attacks that could lead to arbitrary code execution. The changes are implemented by adding a single line of code that enables object filtering wherever ObjectInputStream is used. Sequence diagram for deserialization with ObjectInputFiltersequenceDiagram
participant Client
participant Application
participant ObjectInputStream
participant ObjectInputFilters
Client->>Application: Send serialized data
Application->>ObjectInputStream: Create ObjectInputStream
Application->>ObjectInputFilters: enableObjectFilterIfUnprotected(ois)
ObjectInputFilters-->>ObjectInputStream: Apply filter
Application->>ObjectInputStream: readObject()
ObjectInputStream-->>Application: Return deserialized object
Application-->>Client: Processed data
Class diagram for ObjectInputStream with ObjectInputFilterclassDiagram
class ObjectInputStream {
+readObject() Object
}
class ObjectInputFilters {
+enableObjectFilterIfUnprotected(ObjectInputStream)
}
ObjectInputFilters --|> ObjectInputStream : applies filter
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
Seems you are using me but didn't get OPENAI_API_KEY seted in Variables/Secrets for this repo. you could follow readme for more information |
Changed Files
|
No applications have been configured for previews targeting branch: master. To do so go to restack console and configure your applications for previews. |
The files' contents are under analysis for test generation. |
Thanks @pixeebot[bot] for opening this PR! For COLLABORATOR only :
|
Unsafe Deserialization
DescriptionUnsafe Deserialization (also referred to as Insecure Deserialization) is a vulnerability wherein an application insecurely deserializes malformed and untrusted data input. It is exploited to hijack the logic flow of the application and might result in the execution of arbitrary code. Although this isn't exactly a simple attack to employ, it featured in OWASP's Top 10 most recent iteration as part of the Software and Data Integrity Failures risk, due to the severity of impact upon compromise. Converting an object state or data structure into a storable or transmissible format is called serialization. Deserialization is the opposite - the process of extracting the serialized data to reconstruct the original object version. Unsafe Deserialization issues arise when an attacker can pass ad hoc malicious data into user-supplied data to be deserialized. This could result in arbitrary object injection into the application that might influence the correct target behavior. Read moreImpactA successful Unsafe Deserialization attack can result in the full compromise of the confidentiality, integrity, and availability of the target system, and the oft-cited Equifax breach is the best example of the worst outcome that can arise. In Equifax's case, an unsafe Java deserialization attack leveraging the Struts 2 framework resulted in remote code execution, which, in turn, led to the largest data breach in history. PreventionIt is important to consider any development project from an architectural standpoint to determine when and where serialization is necessary. If it is unnecessary, consider using a simpler format when passing data. In cases where it is impossible to forego serialization without disrupting the application's operational integrity, developers can implement a range of defense-in-depth measures to mitigate the chances of being exploited.
Finally, if possible, replace object serialization with data-only serialization formats, such as JSON. TestingVerify that serialization is not used when communicating with untrusted clients. If this is not possible, ensure that adequate integrity controls (and possibly encryption if sensitive data is sent) are enforced to prevent deserialization attacks, including object injection.
|
Feedback
|
Thanks for opening this pull request! |
👋 Hi there!Everything looks good!
|
PR Details of @pixeebot[bot] in java-design-patterns :
|
Thanks for opening this Pull Request!
|
View changes in DiffLens |
Important Review skippedBot user detected. To trigger a single review, invoke the You can disable this status message by setting the 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have skipped reviewing this pull request. It seems to have been created by a bot (hey, pixeebot[bot]!). We assume it knows what it's doing!
Micro-Learning Topic: Insecure deserialization (Detected by phrase)Matched on "Unsafe Deserialization"It is often convenient to serialize objects for communication or to save them for later use. However, serialized data or code can be modified. This malformed data or unexpected data could be used to abuse application logic, deny service, or execute arbitrary code when deserialized. This is usually done with "gadget chains Try a challenge in Secure Code WarriorHelpful references
Micro-Learning Topic: Template Object Injection (Detected by phrase)Matched on "object injection"Instantiating a template using a user-controlled object is vulnerable to local file read and potential remote code execution. Try a challenge in Secure Code WarriorHelpful references
|
Potential issues, bugs, and flaws that can introduce unwanted behavior.
Code suggestions and improvements for better exception handling, logic, standardization, and consistency.
|
Please double check the following review of the pull request:Issues counts
Changes in the diff
Identified Issues
Detailed Issue Explanations1. Best Practices IssueExplanation: In the files Code: ObjectInputFilters.enableObjectFilterIfUnprotected(ois); Fix: ObjectInputFilter filter = ObjectInputFilter.Config.createFilter("com.iluwatar.serializedentity.Country;!*");
ObjectInputFilters.enableObjectFilterIfUnprotected(ois, filter); Explanation of Fix: The fix involves creating a custom filter that specifies which classes are allowed during deserialization. This enhances security by ensuring only expected classes are deserialized, reducing the risk of deserialization attacks. Missing Tests
These tests will ensure that the custom filters are correctly implemented and provide the necessary security against deserialization attacks. Summon me to re-review when updated! Yours, Gooroo.dev |
🎉🥳 Looks like issue resolved, feel free to reopen, if not. |
🎉🥳 Looks like issue resolved, feel free to reopen, if not. |
View changes in DiffLens |
Manage this branch in SquashTest this branch here: https://pixeebotdrip-2024-10-31-pixee-klmx3.squash.io |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The changes in the pull request generally look good, but there are a few issues that need to be addressed:
-
Missing Newline at End of File:
- Ensure that all files end with a newline. This is a common convention in many coding standards and helps avoid unnecessary diffs in version control systems.
-
Unnecessary Blank Lines:
- There are some unnecessary blank lines added in the
CountrySchemaSql.java
andCountryTest.java
files. Please remove these to keep the code clean and consistent.
- There are some unnecessary blank lines added in the
-
Dependency Version Management:
- In the
pom.xml
file, the version forjava-security-toolkit
is defined as a property (<versions.java-security-toolkit>1.2.0</versions.java-security-toolkit>
). However, in theserialized-entity/pom.xml
andtolerant-reader/pom.xml
files, the version is not specified. It is better to manage the dependency version in a single place to avoid inconsistencies.
- In the
Here are the specific changes needed:
pom.xml
<properties>
<sonar.projectKey>iluwatar_java-design-patterns</sonar.projectKey>
<sonar.moduleKey>${project.artifactId}</sonar.moduleKey>
<sonar.projectName>Java Design Patterns</sonar.projectName>
<versions.java-security-toolkit>1.2.0</versions.java-security-toolkit>
</properties>
<modules>
<module>abstract-factory</module>
serialized-entity/pom.xml
<dependencies>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
<dependency>
<groupId>io.github.pixee</groupId>
<artifactId>java-security-toolkit</artifactId>
<version>${versions.java-security-toolkit}</version>
</dependency>
</dependencies>
<build>
<plugins>
serialized-entity/src/main/java/com/iluwatar/serializedentity/CountrySchemaSql.java
package com.iluwatar.serializedentity;
import io.github.pixee.security.ObjectInputFilters;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
serialized-entity/src/test/java/com/iluwatar/serializedentity/CountryTest.java
package com.iluwatar.serializedentity;
import io.github.pixee.security.ObjectInputFilters;
import org.junit.jupiter.api.Test;
import java.io.*;
tolerant-reader/pom.xml
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.github.pixee</groupId>
<artifactId>java-security-toolkit</artifactId>
<version>${versions.java-security-toolkit}</version>
</dependency>
</dependencies>
<build>
<plugins>
tolerant-reader/src/main/java/com/iluwatar/tolerantreader/RainbowFishSerializer.java
package com.iluwatar.tolerantreader;
import io.github.pixee.security.ObjectInputFilters;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
Please make these changes to ensure the code is clean, consistent, and follows best practices.
Vulnerable Libraries (8)
More info on how to fix Vulnerable Libraries in Java. 👉 Go to the dashboard for detailed results. 📥 Happy? Share your feedback with us. |
ObjectInputStream ois = new ObjectInputStream(baos); | ||
ObjectInputFilters.enableObjectFilterIfUnprotected(ois); | ||
country = (Country) ois.readObject(); | ||
LOGGER.info("Country: " + country); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Logging the entire Country
object at INFO level could potentially expose sensitive data in the logs. Consider logging only non-sensitive information or increasing the log level to DEBUG to reduce the visibility of potentially sensitive data.
ByteArrayInputStream baos = new ByteArrayInputStream(countryBlob.getBytes(1, (int) countryBlob.length())); | ||
ObjectInputStream ois = new ObjectInputStream(baos); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The method countryBlob.getBytes(1, (int) countryBlob.length())
can throw a SQLException
if the blob size exceeds the maximum size that can be converted to a byte array. Consider adding error handling for this scenario to prevent a potential denial of service if large blobs are processed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Micro-Learning Topic: Denial of service (Detected by phrase)
Matched on "denial of service"
The Denial of Service (DoS) attack is focused on making a resource (site, application, server) unavailable for the purpose it was designed. There are many ways to make a service unavailable for legitimate users by manipulating network packets, programming, logical, or resources handling vulnerabilities, among others. Source: https://www.owasp.org/index.php/Denial_of_Service
Try a challenge in Secure Code Warrior
import io.github.pixee.security.ObjectInputFilters; | ||
import org.junit.jupiter.api.Test; | ||
|
||
import java.io.*; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using a wildcard import for java.io.*
can lead to namespace pollution and ambiguity in large projects. It's generally better to import only the specific classes needed.
Recommended Solution:
Replace the wildcard import with specific class imports, e.g., import java.io.FileInputStream;
and import java.io.ObjectInputStream;
.
objectInputStream.close(); | ||
System.out.println(country); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using System.out.println
in test methods is not recommended as it does not contribute to test assertions and can clutter the test output. Additionally, catching a generic Exception
is too broad and can mask other unexpected issues.
Recommended Solution:
- Remove the
System.out.println
statement. - Replace the generic
Exception
catch with more specific exceptions, such asIOException
andClassNotFoundException
, to handle expected issues more precisely.
import java.io.FileInputStream; | ||
import java.io.FileOutputStream; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The direct use of FileInputStream
and FileOutputStream
within the class methods can lead to tight coupling with the file system, which may hinder unit testing and flexibility in data handling. Consider abstracting file operations behind an interface to improve modularity and testability. For instance:
interface DataStreamFactory {
InputStream createInputStream(String path) throws IOException;
OutputStream createOutputStream(String path) throws IOException;
}
This approach allows for easier mocking during testing and can accommodate different storage mechanisms without modifying the core serialization logic.
ObjectInputFilters.enableObjectFilterIfUnprotected(objIn); | ||
map = (Map<String, String>) objIn.readObject(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The use of ObjectInputFilters.enableObjectFilterIfUnprotected(objIn);
is crucial for security to prevent deserialization vulnerabilities. However, ensure that this method effectively blocks deserialization of potentially harmful classes. It's recommended to explicitly define which classes are allowed or disallowed to further tighten security. For example:
ObjectInputFilter filter = ObjectInputFilter.Config.createFilter("com.iluwatar.*;java.base/*;!");
objIn.setObjectInputFilter(filter);
This configuration explicitly allows certain packages while blocking others, reducing the risk of unwanted or malicious object creation during deserialization.
New and removed dependencies detected. Learn more about Socket for GitHub ↗︎
|
Issues Summary1. Project not foundLogs Summary: Failed to execute goal org.sonarsource.scanner.maven:sonar-maven-plugin:3.9.1.2184:sonar (default-cli) on project java-design-patterns: Project not found. Please check the 'sonar.projectKey' and 'sonar.organization' properties, the 'SONAR_TOKEN' environment variable, or contact the project administrator to check the permissions of the user the token belongs toFailing Step: org.sonarsource.scanner.maven:sonar-maven-plugin:3.9.1.2184:sonar (default-cli) Related Source Files: None Related Failures: None ℹ️ Help(You can turn this bot off by adding a comment/ai off , or force a refresh of this report with /ai ... )
For more support, join our Discord channel |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Auto Pull Request Review from LlamaPReview
1. Overview
1.1 PR Summary
- Purpose and Scope: This PR introduces protections against deserialization attacks by adding
ObjectInputFilter
toObjectInputStream
instances. The primary objective is to prevent untrusted data from being deserialized, which can lead to arbitrary code execution. - Key Components Modified:
pom.xml
: Addedjava-security-toolkit
dependency.- Serialization and deserialization processes in multiple files.
- Impact Assessment: The changes mainly affect serialization and deserialization processes, enhancing security without significantly altering the system architecture.
1.2 Architecture Changes
- System Design Modifications: Introduction of
ObjectInputFilter
toObjectInputStream
instances to block potentially harmful classes during deserialization. - Component Interactions: The changes involve the interaction between
ObjectInputStream
andObjectInputFilters
. - Integration Points: The filter is applied during the deserialization process, affecting how objects are reconstructed from serialized data.
2. Detailed Technical Analysis
2.1 Code Logic Deep-Dive
Core Logic Changes
-
[File Path]
serialized-entity/src/main/java/com/iluwatar/serializedentity/CountrySchemaSql.java
- [Function/Class Name]selectCountry
- Submitted PR Code:
import io.github.pixee.security.ObjectInputFilters; try (var connection = dataSource.getConnection(); var preparedStatement = connection.prepareStatement(sql)) { Blob countryBlob = rs.getBlob("country"); ByteArrayInputStream baos = new ByteArrayInputStream(countryBlob.getBytes(1, (int) countryBlob.length())); ObjectInputStream ois = new ObjectInputStream(baos); ObjectInputFilters.enableObjectFilterIfUnprotected(ois); country = (Country) ois.readObject(); LOGGER.info("Country: " + country); } catch (SQLException e) { LOGGER.info("Exception thrown " + e.getMessage()); }
- Analysis:
- The logic flow involves creating an
ObjectInputStream
and applying theObjectInputFilter
to prevent deserialization of potentially harmful classes. - Edge Cases: Handling of null or improperly initialized
ObjectInputStream
. - Potential Issues/Bugs: If
ois
is null, aNullPointerException
may occur.
- The logic flow involves creating an
- LlamaPReview Suggested Improvements:
import io.github.pixee.security.ObjectInputFilters; try (var connection = dataSource.getConnection(); var preparedStatement = connection.prepareStatement(sql)) { Blob countryBlob = rs.getBlob("country"); ByteArrayInputStream baos = new ByteArrayInputStream(countryBlob.getBytes(1, (int) countryBlob.length())); ObjectInputStream ois = new ObjectInputStream(baos); if (ois != null) { ObjectInputFilters.enableObjectFilterIfUnprotected(ois); } country = (Country) ois.readObject(); LOGGER.info("Country: " + country); } catch (SQLException e) { LOGGER.info("Exception thrown " + e.getMessage()); }
- Submitted PR Code:
-
[File Path]
serialized-entity/src/test/java/com/iluwatar/serializedentity/CountryTest.java
- [Function/Class Name]testGetMethod
- Submitted PR Code:
import io.github.pixee.security.ObjectInputFilters; try { ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("output.txt")); objectOutputStream.writeObject(country); objectOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } try { ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("output.txt")); ObjectInputFilters.enableObjectFilterIfUnprotected(objectInputStream); Country country = (Country) objectInputStream.readObject(); objectInputStream.close(); System.out.println(country); } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); }
- Analysis:
- The logic flow involves creating an
ObjectInputStream
and applying theObjectInputFilter
to prevent deserialization of potentially harmful classes. - Edge Cases: Handling of null or improperly initialized
ObjectInputStream
. - Potential Issues/Bugs: If
objectInputStream
is null, aNullPointerException
may occur.
- The logic flow involves creating an
- LlamaPReview Suggested Improvements:
import io.github.pixee.security.ObjectInputFilters; try { ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("output.txt")); objectOutputStream.writeObject(country); objectOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } try { ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("output.txt")); if (objectInputStream != null) { ObjectInputFilters.enableObjectFilterIfUnprotected(objectInputStream); } Country country = (Country) objectInputStream.readObject(); objectInputStream.close(); System.out.println(country); } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); }
- Submitted PR Code:
Algorithm & Data Structure Analysis
- Complexity Analysis: The introduction of
ObjectInputFilter
adds minimal complexity to the deserialization process. - Performance Implications: The performance impact is minimal as the filter is applied only during deserialization, which is typically not a frequent operation.
- Memory Usage Considerations: No significant increase in memory usage is expected.
2.2 Implementation Quality
- Code Organization and Structure: The code is well-organized and follows a logical structure.
- Design Patterns Usage: The changes align with the design principle of defense-in-depth, enhancing security without major architectural changes.
- Error Handling Approach: The current implementation lacks comprehensive error handling for scenarios where
ObjectInputStream
is null or improperly initialized. - Resource Management: Resources are managed properly, ensuring that streams are closed after use.
3. Critical Findings
3.1 Potential Issues
-
🔴 Critical Issues
- Issue Description: The default filter provided by
ObjectInputFilters.enableObjectFilterIfUnprotected(ois)
may not be sufficient for all security needs. - Impact: High risk of deserialization attacks if the default filter is insufficient.
- Recommendation: Implement a custom filter to explicitly specify allowed or disallowed classes.
ObjectInputFilter filter = ObjectInputFilter.Config.createFilter("com.iluwatar.serializedentity.*;!*"); ObjectInputFilters.enableObjectFilterIfUnprotected(ois, filter);
- Issue Description: The default filter provided by
-
🟡 Warnings
- Warning Description: If the
ObjectInputStream
(ois
) is null or improperly initialized, it could lead to aNullPointerException
. - Potential Risks: Medium risk of runtime exceptions.
- Suggested Improvements: Validate the
ObjectInputStream
before applying the filter.if (ois != null) { ObjectInputFilters.enableObjectFilterIfUnprotected(ois); }
- Warning Description: If the
3.2 Code Quality Concerns
- Maintainability Aspects: Ensure that the
ObjectInputFilter
is applied consistently across all deserialization processes. - Readability Issues: Remove unnecessary blank lines for better code readability.
- Performance Bottlenecks: No significant performance bottlenecks are expected.
4. Security Assessment
4.1 Security Considerations
- Authentication/Authorization Impacts: No direct impacts on authentication/authorization mechanisms.
- Data Handling Concerns: The use of
ObjectInputFilter
ensures that only trusted data is deserialized. - Input Validation: The filter acts as an input validation mechanism, blocking potentially harmful classes during deserialization.
- Security Best Practices: The changes align with security best practices for preventing deserialization attacks.
4.2 Vulnerability Analysis
- Potential Security Risks: The primary security risk is the prevention of deserialization attacks, which can lead to arbitrary code execution.
- Mitigation Strategies: Implement a custom filter to explicitly specify allowed or disallowed classes.
- Security Testing Requirements: Ensure comprehensive testing of the deserialization process to validate that the filter is applied correctly.
5. Testing Strategy
5.1 Test Coverage
- Unit Test Analysis: Ensure that tests cover scenarios where the filter is applied and edge cases where the filter blocks deserialization of harmful classes.
- Integration Test Requirements: Test the deserialization process in the context of the entire application to ensure the filter is applied correctly.
- Edge Cases Coverage: Include tests that handle scenarios where the
ObjectInputStream
is null or improperly initialized.
5.2 Test Recommendations
Suggested Test Cases
@Test
public void testDeserializationWithCustomFilter() throws Exception {
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(serializedData));
ObjectInputFilter filter = ObjectInputFilter.Config.createFilter("com.iluwatar.serializedentity.*;!*");
ObjectInputFilters.enableObjectFilterIfUnprotected(ois, filter);
Country country = (Country) ois.readObject();
assertEquals("Expected Country", country.getName());
}
@Test
public void testNullObjectInputStream() throws Exception {
ObjectInputStream ois = null;
assertThrows(NullPointerException.class, () -> {
ObjectInputFilters.enableObjectFilterIfUnprotected(ois);
});
}
- Coverage Improvements: Ensure that all edge cases are covered in the tests.
- Performance Testing Needs: Measure the performance impact of applying the filter during deserialization.
6. Documentation & Maintenance
6.1 Documentation Requirements
- API Documentation Updates: No API changes are introduced.
- Architecture Documentation: Document the addition of
ObjectInputFilter
toObjectInputStream
instances. - Configuration Changes: Document the addition of the
java-security-toolkit
dependency. - Usage Examples: Provide examples of how to apply the filter to
ObjectInputStream
instances.
6.2 Maintenance Considerations
- Long-Term Maintainability: Ensure that the
ObjectInputFilter
is applied consistently across all deserialization processes. - Technical Debt Assessment: Monitor for any deserialization attempts that are blocked by the filter to identify potential technical debt items.
- Monitoring Requirements: Implement monitoring to track blocked deserialization attempts.
7. Deployment & Operations
7.1 Deployment Impact
- Deployment Strategy: Thoroughly test the changes in a staging environment before deployment to ensure they do not introduce any regressions.
- Rollback Plan: Consider implementing a rollback strategy in case the changes introduce unexpected issues in the production environment.
- Configuration Changes: Update deployment instructions to reflect the new dependency.
7.2 Operational Considerations
- Monitoring Requirements: Monitor for any deserialization attempts that are blocked by the filter.
- Performance Metrics: Measure the performance impact of applying the filter during deserialization.
- Resource Utilization: Ensure that resources are managed properly, with no significant increase in resource usage expected.
8. Summary & Recommendations
8.1 Key Action Items
- Implement a custom filter to specify allowed or disallowed classes.
- Ensure proper initialization of
ObjectInputStream
to preventNullPointerException
. - Update test coverage to include edge cases and null pointer scenarios.
- Monitor for blocked deserialization attempts and provide insights into potential attack vectors.
- Document the addition of the
java-security-toolkit
dependency and update deployment instructions.
8.2 Future Considerations
- Long-Term Improvements: Consider implementing a more robust deserialization mechanism using a different serialization format like JSON.
- Technical Debt Items: Monitor for any deserialization attempts that are blocked by the filter to identify potential technical debt items.
- Scalability Considerations: The changes should scale well with the existing system, but continued monitoring is recommended to ensure long-term scalability.
By addressing these action items, the PR can be further enhanced to provide comprehensive protection against deserialization attacks while maintaining code quality and performance.
I'm confident in this change, but I'm not a maintainer of this project. Do you see any reason not to merge it? If this change was not helpful, or you have suggestions for improvements, please let me know! |
Just a friendly ping to remind you about this change. If there are concerns about it, we'd love to hear about them! |
This change may not be a priority right now, so I'll close it. If there was something I could have done better, please let me know! You can also customize me to make sure I'm working with you in the way you want. |
This change hardens Java deserialization operations against attack. Even a simple operation like an object deserialization is an opportunity to yield control of your system to an attacker. In fact, without specific, non-default protections, any object deserialization call can lead to arbitrary code execution. The JavaDoc now even says:
Let's discuss the attack. In Java, types can customize how they should be deserialized by specifying a
readObject()
method like this real example from an old version of Spring:Reflecting on this code reveals a terrifying conclusion. If an attacker presents this object to be deserialized by your app, the runtime will take a class and a method name from the attacker and then call them. Note that an attacker can provide any serliazed type -- it doesn't have to be the one you're expecting, and it will still deserialize.
Attackers can repurpose the logic of selected types within the Java classpath (called "gadgets") and chain them together to achieve arbitrary remote code execution. There are a limited number of publicly known gadgets that can be used for attack, and our change simply inserts an ObjectInputFilter into the
ObjectInputStream
to prevent them from being used.This is a tough vulnerability class to understand, but it is deadly serious. It offers the highest impact possible (remote code execution), it's a common vulnerability (it's in the OWASP Top 10), and exploitation is easy enough that automated exploitation is possible. It's best to remove deserialization entirely, but our protections is effective against all known exploitation strategies.
More reading
🧚🤖 Powered by Pixeebot
Feedback | Community | Docs | Codemod ID: pixee:java/harden-java-deserialization
Summary by Sourcery
Bug Fixes: