T05 · Unauthorized Access and Privilege Escalation
- Location
references/TransactionDAO.java:95- Finding
Tenant Scope Is Missing from ID-Based Transaction Access
- Content
View full analysis
Vulnerability Details
File Location:
references/TransactionDAO.java, lines 95–99 and 168–170
Vulnerability Type: Missing tenant-level authorization in ID-based database operations
Risk Level: HighVulnerable Code
java EntityQueryWrapper queryWrapper = EntityQueryWrapper.columnNameQuery(transactionEntityManager.getEntityTable()); queryWrapper.eq("id", transaction.getId()); if (!expectedStatus.isEmpty()) { queryWrapper.in("transaction_status", expectedStatus.stream().map(TransactionStatus::getStatus).toList()); }java public Transaction findByTransactionId(Long transactionId) { return transactionMapper.selectById(transactionId); }Technical Analysis
The update query and ID-based lookup constrain access using only the transaction ID. Neither operation includes a
tenant_idpredicate derived from a trusted tenant context.The same DAO applies an explicit tenant condition when looking up a transaction by UUID:
java public Transaction findByTransactionUuid(Long tenantId, String transactionUuid) { return transactionMapper.selectOne( Wrappers.lambdaQuery(Transaction.class) .eq(Transaction::getTenantId, tenantId) .eq(Transaction::getTransactionUuid, transactionUuid) ); }This inconsistency indicates that tenant isolation is not uniformly enforced by the DAO. If transaction IDs can be discovered, predicted, leaked, or supplied by a client, ID-only operations may access records belonging to another tenant.
A global, independently verified tenant interceptor could reduce the risk, but no such enforcement mechanism is present in the audited project. DAO methods should therefore enforce tenant ownership explicitly rather than relying on unverified external behavior.
Attack Path
- An authenticated user obtains or guesses the ID of a transaction owned by another tenant.
- The user causes an application endpoint or se ...[truncated 1087 chars]
- Remediation
View remediation
Remediation Suggestions
-
Require a trusted tenant identifier for every transaction read, update, and delete operation.
-
Add the tenant condition directly to all database predicates:
java queryWrapper.eq("id", transaction.getId()); queryWrapper.eq("tenant_id", trustedTenantId); -
Replace
selectByIdwith a tenant-scoped query:java public Transaction findByTransactionId(Long trustedTenantId, Long transactionId) { return transactionMapper.selectOne( Wrappers.lambdaQuery(Transaction.class) .eq(Transaction::getId, transactionId) .eq(Transaction::getTenantId, trustedTenantId) ); } -
Obtain
trustedTenantIdfrom authenticated server-side security context, not from a request DTO or other client-controlled field. -
Apply the same tenant predicate to transaction lines, extension records, history records, and deletion operations.
-
Consider centralized database-level tenant enforcement as defense in depth, but do not use it as a substitute for explicit ownership checks.
-
Add integration tests proving that one tenant cannot read, update, or delete another tenant's records even when a valid foreign transaction ID is supplied.
-
Return a generic not-found or access-denied response without revealing whether a foreign transaction ID exists.
-
