Broken Access Control in Spring Boot with Hmac Signatures
Broken Access Control in Spring Boot with Hmac Signatures — how this specific combination creates or exposes the vulnerability
Broken Access Control occurs when authorization checks are missing or incorrectly enforced, allowing attackers to access resources or perform actions they should not. In Spring Boot applications that use Hmac Signatures for request authentication, misconfiguration or inconsistent validation can weaken access control and enable unauthorized API interactions.
Hmac Signatures typically involve a client signing a request (often a canonical string of method, path, headers, and body) with a shared secret. The server recomputes the signature and compares it to the one provided. When this process is implemented incompletely, it can lead to BOLA/IDOR and BFLA/Privilege Escalation findings, which are part of the 12 parallel security checks in middleBrick scans.
A common pattern is to include the Hmac signature in a custom header (e.g., x-api-signature) alongside an identifier such as an API key or user ID. If the server uses the identifier to fetch a secret but then fails to re-validate scope or permissions on the resource being accessed, the access control boundary can be bypassed. For example, an attacker who knows or guesses another user’s ID might reuse a valid signature, and if the server only checks signature validity without confirming that the associated principal is allowed to access the target resource, the authorization check is effectively skipped.
Spring Boot applications often use filters or interceptors to validate Hmac Signatures before requests reach controllers. If these filters do not consistently apply to all sensitive endpoints, or if they resolve the principal but do not enforce method-level or path-level authorization, the unauthenticated attack surface expands. This can be especially risky when OpenAPI/Swagger specs are not aligned with runtime behavior, as $ref resolution may miss authorization requirements that should apply to specific operations.
Another vector arises from inconsistent data handling. If the signature base string includes only partial headers or omits critical context such as the request body or query parameters, an attacker may manipulate those omitted elements without invalidating the signature. In Spring Boot, failing to bind and validate all relevant parameters in the controller or DTO layer can lead to Property Authorization issues, where a user can modify parameters that should be immutable or restricted.
middleBrick tests these scenarios by running multiple security checks in parallel, including Authentication, BOLA/IDOR, BFLA/Privilege Escalation, and Property Authorization. The scanner compares the runtime behavior against the declared OpenAPI spec to detect gaps. For instance, if an endpoint that should require specific scopes returns a successful response without proper authorization, this results in a finding with severity and remediation guidance in the report.
Hmac Signatures-Specific Remediation in Spring Boot — concrete code fixes
To address Broken Access Control when using Hmac Signatures in Spring Boot, implement consistent signature validation and enforce authorization checks at both the controller and method levels. Below are concrete code examples that demonstrate a robust approach.
First, define a utility to compute the Hmac signature using a shared secret associated with the client. This ensures the server can reliably verify the request origin.
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
public class HmacUtil {
private static final String HMAC_ALGORITHM = "HmacSHA256";
public static String calculateSignature(String data, String secret) {
try {
SecretKeySpec keySpec = new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), HMAC_ALGORITHM);
Mac mac = Mac.getInstance(HMAC_ALGORITHM);
mac.init(keySpec);
byte[] rawHmac = mac.doFinal(data.getBytes(StandardCharsets.UTF_8));
return Base64.getEncoder().encodeToString(rawHmac);
} catch (Exception e) {
throw new RuntimeException("Failed to calculate HMAC", e);
}
}
}
Next, implement a filter that validates the signature before the request reaches the business logic. The filter extracts the client identifier, retrieves the secret (for example from a secure store), rebuilds the canonical string, and compares signatures in a timing-attack safe manner.
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Base64;
@Component
public class HmacValidationFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
String signatureHeader = request.getHeader("x-api-signature");
String apiKey = request.getHeader("x-api-key");
String body = request.getReader().lines().reduce("", String::concat);
String method = request.getMethod();
String path = request.getRequestURI();
// Build canonical string (method, path, selected headers, body)
String canonical = String.join("\n", method, path, apiKey, body);
if (signatureHeader != null && apiKey != null) {
String expectedSignature = resolveSecretAndSign(apiKey, canonical);
if (!constantTimeEquals(expectedSignature, signatureHeader)) {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Invalid signature");
return;
}
} else {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Missing signature or key");
return;
}
filterChain.doFilter(request, response);
}
private String resolveSecretAndSign(String apiKey, String canonical) {
String secret = SecretStore.getSecret(apiKey); // implement secure secret retrieval
return HmacUtil.calculateSignature(canonical, secret);
}
private boolean constantTimeEquals(String a, String b) {
return MessageDigest.isEqual(a.getBytes(StandardCharsets.UTF_8), b.getBytes(StandardCharsets.UTF_8));
}
}
In your controller, ensure that the authenticated principal is checked against the requested resource. Avoid relying solely on signature validation for authorization; combine it with Spring Security expressions or method-level annotations.
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class DocumentController {
private final DocumentService documentService;
public DocumentController(DocumentService documentService) {
this.documentService = documentService;
}
@GetMapping("/documents/{documentId}")
@PreAuthorize("hasPermission(#documentId, 'DOCUMENT', 'READ')")
public ResponseEntity getDocument(@PathVariable String documentId) {
Document doc = documentService.findById(documentId);
return ResponseEntity.ok(doc);
}
}
Additionally, validate all inputs that influence signature construction and resource access. Ensure query parameters and body fields are bound to DTOs with proper constraints to prevent tampering that could bypass intended access controls.
By combining reliable Hmac validation with method-level authorization and consistent resource-level checks, you reduce the risk of Broken Access Control in Spring Boot applications using Hmac Signatures. middleBrick can help verify these configurations by comparing runtime behavior against your OpenAPI spec and highlighting gaps in Authentication, BOLA/IDOR, BFLA/Privilege Escalation, and Property Authorization.