如何消除因使用JsonParser.parse导致的Fortify扫描JSON注入漏洞
JsonParser.parse() Great question! Let's break down why Fortify is calling out this code and walk through the most effective fixes to eliminate the vulnerability.
First, the core issue: Using new JsonParser().parse(jsonRequest) directly with untrusted input exposes your app to JSON injection risks. Fortify flags this because the default JsonParser (most often from Jackson) doesn’t enforce strict security controls—maliciously crafted JSON could trigger parsing errors, exploit polymorphic deserialization flaws, or inject unexpected fields that cause issues downstream.
Here are the best solutions, ordered by effectiveness and robustness:
1. Switch to a Securely Configured ObjectMapper
Instead of using raw JsonParser, use Jackson’s ObjectMapper with security-focused settings. This addresses the root of Fortify’s warning head-on:
// Initialize ObjectMapper with hardened security configurations ObjectMapper objectMapper = new ObjectMapper(); // Reject JSON with unknown properties to block unexpected malicious fields objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true); // Disable default view inclusion to prevent unintended data exposure objectMapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false); // Limit maximum JSON tree depth to prevent stack overflow attacks objectMapper.getFactory().setJsonParserFeature(JsonParser.Feature.MAX_DEPTH, 32); // Parse input securely JsonObject object = objectMapper.readValue(jsonRequest, JsonObject.class); Message<JsonObject> msg = new GenericMessage<>(object, hdr); Message<?> rsp = gwService.process(msg);
This configuration hardens the parser against common JSON-based attacks, which Fortify will recognize as a valid mitigation.
2. Validate Input with JSON Schema
Add a pre-parsing validation step to ensure the input matches your expected structure. This blocks malformed or malicious JSON early:
ObjectMapper objectMapper = new ObjectMapper(); // Define your expected JSON Schema (customize this to match your valid input structure) String expectedSchemaJson = "{ \"type\": \"object\", \"properties\": { \"yourCriticalField\": { \"type\": \"string\" } }, \"required\": [\"yourCriticalField\"] }"; // Validate input against the schema JsonSchema schema = JsonSchemaFactory.byDefault().getSchema(expectedSchemaJson); ProcessingReport validationReport = schema.validate(objectMapper.readTree(jsonRequest)); if (!validationReport.isSuccess()) { // Handle invalid input: throw an error, log the issue, or return a bad request response throw new IllegalArgumentException("Invalid JSON input structure"); } // Proceed with parsing only if validation passes JsonObject object = objectMapper.readValue(jsonRequest, JsonObject.class); Message<JsonObject> msg = new GenericMessage<>(object, hdr); Message<?> rsp = gwService.process(msg);
Validation adds an extra safety net, ensuring only legitimate JSON gets parsed.
3. Map to a Strongly Typed DTO (Best Long-Term Fix)
Instead of using a generic JsonObject, map the JSON directly to a custom Data Transfer Object (DTO) that matches your business requirements. This restricts input to only the fields you expect, eliminating the risk of unexpected malicious fields:
// Define a DTO that mirrors your valid request structure public class MyRequestDTO { private String requiredField; private Integer optionalField; // Getters and setters public String getRequiredField() { return requiredField; } public void setRequiredField(String requiredField) { this.requiredField = requiredField; } public Integer getOptionalField() { return optionalField; } public void setOptionalField(Integer optionalField) { this.optionalField = optionalField; } } // Parse directly to the DTO (combine with secure ObjectMapper config from solution 1) ObjectMapper objectMapper = new ObjectMapper(); objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true); MyRequestDTO request = objectMapper.readValue(jsonRequest, MyRequestDTO.class); Message<MyRequestDTO> msg = new GenericMessage<>(request, hdr); Message<?> rsp = gwService.process(msg);
Using a DTO makes your code more maintainable, readable, and far more secure—Fortify will no longer flag this as a vulnerability because you’re explicitly controlling what input is accepted.
Final Recommendation
For the strongest defense, combine all three approaches: use a securely configured ObjectMapper, validate input with a JSON Schema, and map to a strongly typed DTO. This creates multiple layers of protection against JSON injection and ensures your code is robust for the long term.
内容的提问来源于stack exchange,提问作者user3520253

