Skip to content

Possible unauthorised probing for entity existence via error messages #2356

Open
@antoinemzs

Description

@antoinemzs

Description

Unauthorised fetching of an entity is masked as a 404 NOT FOUND error status instead of 401 UNAUTHORIZED, to avoid leaking the existence or not of said entity.

However, the response body is different in shape from a genuine 404, allowing for determining that an entity exists from an unprivilieged stand point.

Impacted endpoints:

👉 May discover valid tokens via unauthenticated request
Practicality: very low: when probing blind, need to figure out long, non sequential alpha-numerical strings to test (assuming their generation is random and crypto-safe); if obtaining a leak, the probing is not useful

@PostMapping("/api/reset/{token}")

👉 May discover valid tokens as an authenticated, non-admin user
Practicality: very low, for the same reason

@PostMapping("/api/me/token/refresh")

👉 May discover injects and related existing simulation or scenario as an authenticated, non-admin user
Practicality: very low: inject IDs are non sequential UUIDv4 so the address space is unpractically large
the value of knowing a specific inject exists via its ID
Risk: injects may contain sensitive data, and knowing valid IDs in advance may help further probing or attacks leading to a possible, eventual leak


Recommendation

The error message given with a 404 response status should always be of the same shape, and not provide a vector for probing.

Details

401 to 404 switch handler code: static "NOT_FOUND" string for body

@ResponseStatus(HttpStatus.NOT_FOUND)
@ExceptionHandler(AccessDeniedException.class)
public ValidationErrorBag handleAccessDeniedExceptions() {
// When the user does not have the appropriate access rights, return 404 Not Found.
// This response indicates that the resource does not exist, preventing any information
// disclosure
// about the resource and reducing the risk of brute force attacks by not confirming its
// existence
return new ValidationErrorBag(HttpStatus.NOT_FOUND.value(), "NOT_FOUND");
}

Genuine 404 handler code: get a message constructed from the actual exception

@ExceptionHandler(ElementNotFoundException.class)
public ResponseEntity<ErrorMessage> handleElementNotFoundException(ElementNotFoundException ex) {
ErrorMessage message = new ErrorMessage("Element not found: " + ex.getMessage());
log.warning("ElementNotFoundException: " + ex.getMessage());
return new ResponseEntity<>(message, HttpStatus.NOT_FOUND);
}

Metadata

Metadata

Assignees

Labels

featureuse for describing a new feature to developtechnical improvementTechnical refactor or improvement is needed

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions