ManagedWebAccessUtils.getServer() uses String.startsWith() to match request URLs against configured server URLs for authentication credential dispatch. Because configured server URLs (e.g., http://tx.fhir.org) lack a trailing slash or host boundary check, an attacker-controlled domain like http://tx.fhir.org.attacker.com matches the prefix and receives Bearer tokens, Basic auth credentials, or API keys when the HTTP client follows a redirect to that domain.
The root cause is in ManagedWebAccessUtils.getServer() at org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/http/ManagedWebAccessUtils.java:26:
public static ServerDetailsPOJO getServer(String url, Iterable<ServerDetailsPOJO> serverAuthDetails) {
if (serverAuthDetails != null) {
for (ServerDetailsPOJO serverDetails : serverAuthDetails) {
if (url.startsWith(serverDetails.getUrl())) { // <-- no host boundary check
return serverDetails;
}
}
}
return null;
}
The configured production terminology server URL is defined without a trailing slash in FhirSettingsPOJO.java:19:
protected static final String TX_SERVER_PROD = "http://tx.fhir.org";
This means:
"http://tx.fhir.org.attacker.com/capture".startsWith("http://tx.fhir.org") → true"http://tx.fhir.org:8080/evil".startsWith("http://tx.fhir.org") → trueExploit chain via SimpleHTTPClient (redirect path):
SimpleHTTPClient.get() (SimpleHTTPClient.java:68-105) makes a request to http://tx.fhir.org/ValueSet/$expandgetHttpGetConnection(url, accept) (line 84) → setHeaders(connection) (line 117)setHeaders() (line 122-133) calls authProvider.canProvideHeaders(url) and authProvider.getHeaders(url) on the redirect target URLServerDetailsPOJOHTTPAuthProvider.getServerDetails() (line 83-84) delegates to `ManagedWebAccessUtils.getServer(url.toString(),...6.9.46.9.4Exploitability
AV:NAC:HPR:NUI:NScope
S:UImpact
C:HI:HA:N7.4/CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N