Spring4shell in Dynamodb
How Spring4shell Manifests in Dynamodb
Spring4shell (CVE-2022-22965) is a remote code execution vulnerability in Spring Framework arising from unsafe deserialization and class loading when processing request parameters on certain configurations. Its manifestation in applications using Amazon DynamoDB is indirect but critical: it occurs when a vulnerable Spring application processes attacker-controlled data that subsequently influences DynamoDB operations through Spring Data DynamoDB or custom integration code. The core issue is not DynamoDB itself but how Spring-managed beans or controllers handle input that is later used in reflection-based or expression-based DynamoDB queries.
A typical attack pattern involves an API endpoint that accepts a parameter (e.g., className, filterExpression, or attributeValue) which is then used to construct a DynamoDB query via Spring Expression Language (SpEL) or Java reflection. If an attacker can inject a fully qualified class name (e.g., org.springframework.context.support.FileSystemXmlApplicationContext) into such a parameter, and the application evaluates it using vulnerable Spring methods (like ExpressionParser or BeanWrapper), they can achieve remote code execution. This is exacerbated when the application uses DynamoDB's ExpressionSpec or DynamoDBMapper in a way that dynamically evaluates expressions from request data without proper sanitization.
Example vulnerable code using Spring Data DynamoDB:
@RestController
public class UserController {
@Autowired
private DynamoDBMapper mapper;
@GetMapping("/users")
public List<User> getUsers(@RequestParam String filterExpr) {
// VULNERABLE: Directly using request parameter in SpEL expression
Expression expression = new Expression().withExpressionString(filterExpr);
ScanScanRequest request = new ScanScanRequest()
.withTableName("Users")
.withFilterExpression(expression);
return mapper.scan(User.class, request);
}
}Here, an attacker could submit filterExpr=#{T(java.lang.Runtime).getRuntime().exec('calc')} to trigger code execution when the expression is parsed by Spring's ExpressionParser during the scan operation. The vulnerability is triggered in the Spring layer before the query even reaches DynamoDB, but the DynamoDB operation is the attack conduit.
Dynamodb-Specific Detection
Detecting Spring4shell in DynamoDB-integrated applications requires identifying API endpoints that accept dynamic expressions or class names which influence DynamoDB operations. middleBrick's scanner tests for this by analyzing both the OpenAPI/Swagger specification (if available) and runtime behavior. It looks for parameters named className, expression, filter, or similar that are used in operations mapped to DynamoDB actions (Scan, Query, UpdateItem). The scanner then sends payloads containing known Spring4shell exploitation patterns (e.g., class loading via T(Class) or new in SpEL) and observes responses for signs of code execution or error messages indicating class loading.
For example, middleBrick's Input Validation and LLM/AI Security checks are adapted to detect SpEL injection attempts in DynamoDB contexts. It cross-references the API's defined parameters with the actual HTTP responses. If an endpoint like /users?filterExpr= returns a 500 error with a stack trace mentioning ClassNotFoundException or SpelEvaluationException when probed with a malicious payload, it flags a high-severity finding.
Using middleBrick to detect:
1. Web Dashboard: Submit the API URL. The report will highlight any endpoint where SpEL injection was possible, with a category like "Input Validation" and a severity of "Critical". The per-category breakdown will show a failure in the "Input Validation" check.
2. CLI tool: Run middlebrick scan https://api.example.com. The JSON output includes a findings array; look for entries with "title": "Potential SpEL Injection in DynamoDB Query" and "severity": "critical".
{
"findings": [
{
"id": "SPEL_INJECTION_001",
"title": "SpEL Injection in DynamoDB Scan Operation",
"severity": "critical",
"endpoint": "/users",
"parameter": "filterExpr",
"evidence": "Response contained 'T(java.lang.Runtime)' in error message"
}
]
}3. GitHub Action: In your CI pipeline, the action will fail the build if a critical finding like this is detected, preventing deployment of a vulnerable service.
Dynamodb-Specific Remediation
Remediation focuses on eliminating dynamic expression evaluation from user input in DynamoDB operations and updating Spring Framework. The primary fix is to avoid using request parameters directly in SpEL or reflection-based constructs. Instead, use DynamoDB's native expression builders with strict parameter binding. DynamoDB's ExpressionSpec (from AWS SDK v2) or DynamoDBMapper with DynamoDBScanExpression should be configured with static expressions and separate, validated attribute values.
Step 1: Update Spring Framework to a version patched against CVE-2022-22965 (Spring 5.3.18+, 5.2.20+, or corresponding Spring Boot releases). This is non-negotiable but not DynamoDB-specific.
Step 2: Refactor DynamoDB query construction to use safe patterns. Never pass raw request strings to withFilterExpression() or withProjectionExpression(). Instead, build expressions programmatically and use withExpressionAttributeValues() to bind user input as values, not as part of the expression string.
Vulnerable code (from previous section):
// UNSAFE: user-controlled filterExpr directly in expression
Expression expression = new Expression().withExpressionString(filterExpr);Remediated code using DynamoDB's ExpressionSpec (AWS SDK v2):
@GetMapping("/users")
public List<User> getUsers(@RequestParam String status) {
// SAFE: Static expression with bound parameter
Map<String, String> expressionNames = new HashMap<>();
expressionNames.put("#s", "status");
Map<String, Object> expressionValues = new HashMap<>();
expressionValues.put(":status", new AttributeValue().withS(status));
ExpressionSpec expressionSpec = ExpressionSpec.builder()
.expression("#s = :status")
.expressionNames(expressionNames)
.expressionValues(expressionValues)
.build();
ScanRequest request = ScanRequest.builder()
.tableName("Users")
.filterExpression(expressionSpec.expression())
.expressionNames(expressionSpec.expressionNames())
.expressionAttributeValues(expressionSpec.expressionValues())
.build();
return mapper.scan(User.class, request);
}Here, the expression string is static. The user-supplied status is bound as a value via :status, which DynamoDB treats as a literal string, not executable code. This pattern prevents SpEL injection because no expression parsing of user input occurs. For more complex queries, use the DynamoDBEnhancedClient and its type-safe QueryConditional APIs.
Additional hardening:
- Validate and whitelist allowed characters in any parameters that might influence expressions (e.g., alphanumeric only for sort keys).
- Use Spring's
@Validatedand custom validators to reject input containing#{,T(, ornew. - Enable DynamoDB's
ReturnConsumedCapacityto monitor for unexpectedly expensive queries that might indicate probing.
After remediation, re-scan with middleBrick to confirm the finding is resolved. The report should show no critical input validation issues for that endpoint.
Frequently Asked Questions
Is DynamoDB itself vulnerable to Spring4shell?
Can middleBrick detect Spring4shell in APIs that use DynamoDB but don't expose a Swagger spec?
filter, expr) and probe for SpEL injection patterns. The scanner's runtime analysis will flag critical findings if the endpoint's behavior indicates class loading or SpEL evaluation.