Summary
A Server-Side Template Injection was identified in Corona Warn App Server enabling attackers to inject arbitrary Java EL expressions, leading to un-auth Remote Code Execution (RCE) vulnerability.
Product
Corona Warn App Server
Tested Version
latest commit to the date of testing: 3fd6baf
Details
Remote Code Execution - JavaEL Injection
It is possible to run arbitrary code on the server (with Submission service account privileges) by injecting arbitrary Java Expression Language (EL) expressions.
Submission server uses Java Bean Validation (JSR 380) custom constraint validators such as ValidSubmissionPayload
:
When building custom constraint violation error messages, it is important to understand that they support different types of interpolation, including Java EL expressions. Therefore if an attacker can inject arbitrary data in the error message template being passed to ConstraintValidatorContext.buildConstraintViolationWithTemplate()
argument, they will be able to run arbitrary Java code. Unfortunately, it is common that validated (and therefore, normally untrusted) bean properties flow into the custom error message. In this case there are, at least, two paths where attacker controlled strings are included in custom constraint error validation messages:
private boolean checkVisitedCountriesAreValid(SubmissionPayload submissionPayload,
ConstraintValidatorContext validatorContext) {
if (submissionPayload.getVisitedCountriesList().isEmpty()) {
return true;
}
Collection<String> invalidVisitedCountries = submissionPayload.getVisitedCountriesList().stream()
.filter(not(supportedCountries::contains)).collect(toList());
if (!invalidVisitedCountries.isEmpty()) {
invalidVisitedCountries.forEach(country -> addViolation(validatorContext,
"[" + country + "]: Visited country is not part of the supported countries list"));
}
return invalidVisitedCountries.isEmpty();
}
and
private boolean checkOriginCountryIsValid(SubmissionPayload submissionPayload,
ConstraintValidatorContext validatorContext) {
String originCountry = submissionPayload.getOrigin();
if (submissionPayload.hasOrigin() && !originCountry.isEmpty()
&& !supportedCountries.contains(originCountry)) {
addViolation(validatorContext, String.format(
"Origin country %s is not part of the supported countries list", originCountry));
return false;
}
return true;
}
The ValidSubmissionPayload
annotation is used to validate data received by the Submission service controller exposed in /version/v1/diagnosis-keys
:
/**
* Handles diagnosis key submission requests.
*
* @param exposureKeys The unmarshalled protocol buffers submission payload.
* @param tan A tan for diagnosis verification.
* @return An empty response body.
*/
@PostMapping(value = SUBMISSION_ROUTE, headers = {"cwa-fake=0"})
@Timed(description = "Time spent handling submission.")
public DeferredResult<ResponseEntity<Void>> submitDiagnosisKey(
@ValidSubmissionPayload @RequestBody SubmissionPayload exposureKeys,
@RequestHeader("cwa-authorization") String tan) {
submissionMonitor.incrementRequestCounter();
submissionMonitor.incrementRealRequestCounter();
return buildRealDeferredResult(exposureKeys, tan);
}
Spring security policies are defined to protect the endpoints but, in this case, all requests to the Submission endpoint are allowed with no authentication/authorization:
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.mvcMatchers(HttpMethod.GET, HEALTH_ROUTE, PROMETHEUS_ROUTE, READINESS_ROUTE, LIVENESS_ROUTE).permitAll()
.mvcMatchers(HttpMethod.POST, SUBMISSION_ROUTE).permitAll()
.anyRequest().denyAll()
.and().csrf().disable();
http.headers().contentSecurityPolicy("default-src 'self'");
}
Impact
This issue leads to Remote Code execution
Coordinated Disclosure Timeline
- 10/21/2020: Reported through SAP Trust Center
- 10/22/2020: Issue reception is acknowledged
- 10/23/2020: Issue is fixed in public repo
- 10/28/2020: SAP confirms that the issue is fixed in release 1.5.1 which was deployed on 10/27/2020. SAP also informs GHSL that BSI (Bundesamt für Sicherheit in der Informationstechnik is currently testing the fix and asks to keep the issue confidential till BSI has done their tests and has confirmed that the fix is okay.
- 11/01/2020: A more robust fix is merged.
- 11/09/2020: SAP told us that BSI has confirmed the fix.
Resources
SAP ID SR-20-00362
Credit
This issue was discovered and reported by GHSL team member @pwntester (Alvaro Muñoz).
Contact
You can contact the GHSL team at securitylab@github.com
, please include a reference to GHSL-2020-204
in any communication regarding this issue.