Bola Idor in Spring Boot with Hmac Signatures
Bola Idor in Spring Boot with Hmac Signatures — how this specific combination creates or exposes the vulnerability
Broken Object Level Authorization (BOLA) is an API security risk where an authenticated subject can access or modify objects they should not be allowed to. When HMAC signatures are used in a Spring Boot application but are implemented only at the transport or message level — without strict per-request or per-object authorization checks — BOLA can still occur. A common pattern is to sign a payload that includes a resource identifier (e.g., /api/invoices/{id}) to ensure integrity and origin, but if the server uses the signature mainly to verify the request has not been tampered with and then directly uses the user-supplied {id} to fetch a domain object without validating ownership or access rights, the authorization boundary is effectively bypassed.
Consider a Spring Boot controller that accepts an invoice ID and an HMAC signature. The signature is computed over the invoice ID and a timestamp using a shared secret. The server validates the signature, extracts the invoice ID, and then loads the invoice via repository.findById(invoiceId). If the user Alice has no permission to view invoice 12345 but knows or can guess another valid invoice ID, and the server does not check that invoice 12345 belongs to Alice (or that Alice has the required role or scope), the HMAC verification passes but the BOLA check is missing. The signature ensures the request was not altered, but it does not enforce authorization at the object level. This is a classic BOLA: authenticated access control without proper ownership or tenant scoping.
In practice, this can be triggered when APIs expose numeric or predictable IDs and rely on signature validation alone. Attackers can enumerate IDs, replay signed requests, or modify parameters within the signed payload if the server is permissive about what it signs (for example, signing only a subset of parameters). Another variant occurs when the signature is validated, but the server then uses an unchecked lookup path (such as ignoring tenant context or using a cached object) leading to Insecure Direct Object References (IDOR). Because HMAC signatures provide integrity and non-repudiation but not authorization, Spring Boot applications must pair HMAC verification with explicit access-control checks per object. Without this, the API remains vulnerable to BOLA despite having cryptographic integrity on the wire.
Hmac Signatures-Specific Remediation in Spring Boot — concrete code fixes
To prevent BOLA when using HMAC signatures in Spring Boot, treat the signature as a transport integrity mechanism and still enforce object-level authorization. Below is a concise, realistic example that shows signature validation and a secure follow-up authorization check using Spring Boot and Java. The example uses javax.crypto for HMAC and Spring Security expressions for authorization, but you can adapt it to your security model.
@Service
public class InvoiceService {
private final InvoiceRepository invoiceRepository;
private final AesKeyProvider keyProvider; // provides the shared secret per tenant or user
public InvoiceService(InvoiceRepository invoiceRepository, AesKeyProvider keyProvider) {
this.invoiceRepository = invoiceRepository;
this.keyProvider = keyProvider;
}
public Invoice getInvoiceForUser(String invoiceId, String requesterUserId, String signature, long timestamp) {
// 1) Verify HMAC integrity (example uses HmacSHA256)
if (!HmacValidator.isValid(invoiceId + timestamp, signature, keyProvider.getKeyForUser(requesterUserId))) {
throw new SecurityException("Invalid signature");
}
// 2) Enforce object-level authorization: ensure the invoice belongs to the requester
Invoice invoice = invoiceRepository.findById(invoiceId)
.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Invoice not found"));
if (!invoice.getUserId().equals(requesterUserId)) {
throw new AccessDeniedException("You do not have access to this invoice");
}
// 3) Additional checks can include tenant or scope validation
return invoice;
}
}
public class HmacValidator {
public static boolean isValid(String data, String providedSignature, byte[] secret) {
try {
Mac mac = Mac.getInstance("HmacSHA256");
SecretKeySpec keySpec = new SecretKeySpec(secret, "HmacSHA256");
mac.init(keySpec);
byte[] rawHmac = mac.doFinal(data.getBytes(StandardCharsets.UTF_8));
String computedSignature = Base64.getEncoder().encodeToString(rawHmac);
return MessageDigest.isEqual(computedSignature.getBytes(StandardCharsets.UTF_8), providedSignature.getBytes(StandardCharsets.UTF_8));
} catch (Exception e) {
return false;
}
}
}
In this pattern, the signature is computed over the resource identifier and a timestamp to prevent replay, and the server validates the signature before loading the object. Immediately after loading, the server enforces that the object’s owning user matches the requester. This two-step approach ensures HMAC provides integrity while Spring Security and explicit checks provide BOLA protection. For more complex permissions, integrate Spring Security expressions or a policy engine to evaluate roles, scopes, or tenant relationships before returning the resource.
When exposing endpoints via OpenAPI, document that signature validation does not replace object-level authorization and require clients to include the resource identifier in the signed payload and to present the identifier in a way that allows server-side ownership checks. Combine this with rate limiting and audit logging to further reduce abuse. The combination of cryptographic integrity and strict per-request authorization is necessary to mitigate BOLA in HMAC-signed Spring Boot APIs.
Related CWEs: bolaAuthorization
| CWE ID | Name | Severity |
|---|---|---|
| CWE-250 | Execution with Unnecessary Privileges | HIGH |
| CWE-639 | Insecure Direct Object Reference | CRITICAL |
| CWE-732 | Incorrect Permission Assignment | HIGH |