CWE-787 in Spring Boot
How Cwe 787 Manifests in Spring Boot
CWE-787 (Out-of-Bounds Write) occurs when software writes data past the end, or before the beginning, of the intended buffer. In Spring Boot applications, this manifests through several Spring-specific attack vectors that leverage the framework's dynamic features.
1. Thymeleaf Template Injection via Out-of-Bounds Writes
Spring Boot's default template engine, Thymeleaf, can be exploited when user input is used to construct template variable names or array indices. Consider this vulnerable controller:
@Controller
public class VulnerableController {
@GetMapping("/user/{index}")
public String getUser(@PathVariable int index, Model model) {
String[] users = {"Alice", "Bob", "Charlie"};
// Out-of-bounds write if index >= 3
model.addAttribute("username", users[index]);
return "user";
}
}If an attacker requests /user/10, they trigger an ArrayIndexOutOfBoundsException. While this throws an error, more sophisticated attacks can manipulate template variables to cause buffer overflows in the template rendering engine.
2. Multipart File Upload Buffer Overflow
Spring Boot's MultipartFile handling can be exploited when file size limits aren't properly configured:
@RestController
public class FileUploadController {
@PostMapping("/upload")
public ResponseEntity uploadFile(@RequestParam("file") MultipartFile file) {
byte[] bytes = file.getBytes(); // No size validation
// Process file - potential out-of-bounds write if bytes.length exceeds buffer
return ResponseEntity.ok("File uploaded");
}
} An attacker can upload a file larger than the server's buffer capacity, causing memory corruption or denial of service.
3. JSON Deserialization with Spring's ObjectMapper
Spring Boot uses Jackson's ObjectMapper extensively. When deserializing untrusted JSON with array fields, out-of-bounds writes can occur:
@RestController
public class JsonController {
@PostMapping("/process")
public void processJson(@RequestBody MyObject obj) {
int[] numbers = obj.getNumbers();
int[] processed = new int[5];
for (int i = 0; i < numbers.length; i++) {
processed[i] = numbers[i] * 2; // Out-of-bounds if numbers.length > 5
}
}
}
class MyObject {
private int[] numbers;
// getters/setters
}An attacker can craft JSON with more than 5 numbers, causing an out-of-bounds write when processing the array.
4. Spring Data JPA Native Queries with Array Parameters
When using native SQL queries with array parameters, Spring Boot's parameter binding can be exploited:
@Repository
public interface UserRepository extends JpaRepository {
@Query(value = "SELECT * FROM users WHERE id IN (:ids)", nativeQuery = true)
List findUsersByIds(@Param("ids") int[] ids);
}
@Service
public class UserService {
public void processUserIds(List userIds) {
int[] idsArray = userIds.stream().mapToInt(Integer::intValue).toArray();
List users = userRepository.findUsersByIds(idsArray);
// Process users - potential out-of-bounds if array manipulation occurs
}
} If the array size exceeds database column constraints or application buffer limits, out-of-bounds writes can occur during result processing.
Spring Boot-Specific Detection
Detecting CWE-787 in Spring Boot requires both static code analysis and runtime monitoring. Here are Spring-specific detection methods:
1. Static Analysis with Spring Boot Actuator
Spring Boot Actuator provides production-ready features to help you monitor and manage your application. Enable security endpoints to detect potential buffer overflow patterns:
management:
endpoints:
web:
exposure:
include: health, info, env, beans
endpoint:
health:
show-details: alwaysMonitor the /actuator/beans endpoint to identify all beans that handle arrays or buffers, then focus security testing on those components.
2. middleBrick Security Scanner Integration
middleBrick's black-box scanning approach is particularly effective for detecting CWE-787 vulnerabilities in Spring Boot applications without requiring source code access. The scanner tests unauthenticated endpoints for buffer overflow patterns.
Using the middleBrick CLI:
npm install -g middlebrick
middlebrick scan https://your-spring-boot-app.com/api/upload
middlebrick scan https://your-spring-boot-app.com/api/process
middlebrick scan https://your-spring-boot-app.com/api/user/{index}middleBrick specifically tests:
- Array parameter boundaries in REST endpoints
- File upload size limits and buffer handling
- Template engine parameter validation
- JSON deserialization with array fields
- Database query parameter array sizes
3. Spring Boot Security Configuration
Configure Spring Security to detect and prevent buffer overflow attempts:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.headers()
.contentTypeOptions()
.and()
.xssProtection()
.and()
.frameOptions()
.and()
.contentSecurityPolicy("script-src 'self'")
.and()
.authorizeRequests()
.antMatchers("/upload/**").access("hasRole('USER') and #oauth2.hasScope('write')")
.anyRequest().authenticated();
}
}This configuration adds multiple security headers that help detect and prevent certain types of buffer overflow attacks.
4. Runtime Monitoring with Spring Boot Actuator
Enable detailed monitoring to detect buffer overflow patterns at runtime:
@Component
public class BufferOverflowMonitor {
private static final Logger logger = LoggerFactory.getLogger(BufferOverflowMonitor.class);
@EventListener
public void handleException(ExceptionEvent event) {
Throwable ex = event.getThrowable();
if (ex instanceof ArrayIndexOutOfBoundsException ||
ex instanceof StringIndexOutOfBoundsException ||
ex instanceof BufferOverflowException) {
logger.error("Potential buffer overflow detected: {}", ex.getMessage());
// Additional monitoring logic
}
}
}This component listens for buffer-related exceptions and logs them for security analysis.
Spring Boot-Specific Remediation
Remediating CWE-787 in Spring Boot requires a combination of input validation, proper buffer management, and Spring-specific security configurations. Here are concrete solutions:
1. Input Validation with Spring's @Validated
Use Spring's validation framework to prevent out-of-bounds writes:
@Controller
public class SecureController {
@GetMapping("/user/{index}")
public String getUser(@PathVariable @Min(0) @Max(2) int index, Model model) {
String[] users = {"Alice", "Bob", "Charlie"};
model.addAttribute("username", users[index]);
return "user";
}
@PostMapping("/process")
public ResponseEntity processJson(@RequestBody @Valid MyObject obj) {
int[] numbers = obj.getNumbers();
int[] processed = new int[Math.min(5, numbers.length)];
for (int i = 0; i < processed.length; i++) {
processed[i] = numbers[i] * 2;
}
return ResponseEntity.ok("Processed successfully");
}
}
class MyObject {
@Size(max = 5)
private int[] numbers;
// getters/setters
} The @Min, @Max, and @Size annotations ensure array indices and sizes stay within bounds.
2. Safe File Upload Handling
Configure Spring Boot to handle file uploads safely with size limits:
@Configuration
public class FileUploadConfig {
@Bean
public MultipartConfigElement multipartConfigElement() {
MultipartConfigFactory factory = new MultipartConfigFactory();
factory.setMaxFileSize(DataSize.ofMegabytes(10));
factory.setMaxRequestSize(DataSize.ofMegabytes(10));
return factory.createMultipartConfig();
}
@Bean
public MultipartResolver multipartResolver() {
StandardServletMultipartResolver resolver = new StandardServletMultipartResolver();
resolver.setResolveLazily(true);
return resolver;
}
}
@RestController
public class SecureFileUploadController {
@PostMapping("/upload")
public ResponseEntity uploadFile(@RequestParam("file") MultipartFile file) {
if (file.isEmpty() || file.getSize() > 10 * 1024 * 1024) {
return ResponseEntity.badRequest().body("File size must be between 1 byte and 10MB");
}
byte[] bytes = file.getBytes();
if (bytes.length > 1024 * 1024) { // Additional safety check
throw new IllegalArgumentException("File content too large");
}
// Process file safely
return ResponseEntity.ok("File uploaded successfully");
}
} This configuration enforces file size limits at both the servlet container level and application level.
3. Safe JSON Deserialization with Jackson
Configure Jackson to prevent out-of-bounds writes during deserialization:
@Configuration
public class JacksonConfig {
@Bean
public ObjectMapper objectMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.setDeserializationFeature(DeserializationFeature.FAIL_ON_TRAILING_TOKENS, true);
mapper.setDeserializationFeature(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, true);
mapper.setDeserializationFeature(DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY, true);
// Configure array size limits
SimpleModule module = new SimpleModule();
module.addDeserializer(int[].class, new SafeArrayDeserializer());
mapper.registerModule(module);
return mapper;
}
}
class SafeArrayDeserializer extends JsonDeserializer {
@Override
public int[] deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
ArrayNode arrayNode = p.getCodec().readTree(p);
if (arrayNode.size() > 1000) { // Maximum array size
throw new IllegalArgumentException("Array size exceeds maximum allowed size");
}
int[] result = new int[arrayNode.size()];
for (int i = 0; i < arrayNode.size(); i++) {
result[i] = arrayNode.get(i).intValue();
}
return result;
}
} This custom deserializer enforces maximum array sizes during JSON parsing.
4. Spring Data JPA Safe Query Parameters
Implement safe array handling for database queries:
@Repository
public interface UserRepository extends JpaRepository {
@Query(value = "SELECT * FROM users WHERE id IN (:ids)")
@QueryHints(@QueryHint(name = "org.hibernate.fetchSize", value = "50"))
List findUsersByIds(@Param("ids") List ids);
}
@Service
public class UserService {
private static final int MAX_QUERY_PARAMS = 100;
public List getUsersByIds(List userIds) {
if (userIds == null || userIds.isEmpty()) {
return Collections.emptyList();
}
if (userIds.size() > MAX_QUERY_PARAMS) {
throw new IllegalArgumentException("Maximum of " + MAX_QUERY_PARAMS + " IDs allowed");
}
return userRepository.findUsersByIds(userIds);
}
} This approach uses List instead of arrays and enforces maximum parameter counts to prevent out-of-bounds writes.
Frequently Asked Questions
How does middleBrick specifically detect CWE-787 vulnerabilities in Spring Boot applications?
middleBrick performs black-box scanning that tests Spring Boot endpoints for buffer overflow patterns without requiring source code access. The scanner sends boundary-testing requests to array parameters, file upload endpoints, and JSON processing routes. For example, it will test /api/process with JSON arrays larger than expected sizes, /api/upload with oversized files, and /api/user/{index} with out-of-bounds array indices. The scanner analyzes responses for error patterns, stack traces, or abnormal behavior that indicate buffer overflow vulnerabilities. middleBrick's 12 security checks include specific tests for input validation weaknesses and data exposure that commonly accompany CWE-787 issues in Spring Boot applications.
What Spring Boot Actuator endpoints are most useful for detecting buffer overflow vulnerabilities?
The most useful Actuator endpoints for detecting buffer overflow vulnerabilities are /actuator/beans, /actuator/env, and /actuator/heapdump. The /beans endpoint shows all Spring-managed beans, helping you identify components that handle arrays or buffers. The /env endpoint reveals configuration properties that might affect buffer sizes. While /heapdump can help analyze memory usage patterns, it should be protected as it can expose sensitive information. Additionally, enabling the /actuator/httptrace endpoint helps monitor request patterns that might indicate buffer overflow attacks. Always secure these endpoints with authentication and authorization in production environments to prevent information disclosure.