Ecosyste.ms: Advisories
An open API service providing security vulnerability metadata for many open source software ecosystems.
Security Advisories: MDE2OlNlY3VyaXR5QWR2aXNvcnlHSFNBLTZ2N3Atdjc1NC1qODl2
HTTP Response Splitting in Styx
Vulnerability
Styx is vulnerable to CWE-113: Improper Neutralization of CRLF Sequences in HTTP Headers ('HTTP Response Splitting').
Vulnerable Component
The vulnerable component is the com.hotels.styx.api.HttpHeaders.Builder
due to disabling the HTTP Header validation built into Netty in these locations:
new DefaultHttpHeaders(false)
disables the built-in validation in Netty. Either use the default constructor or new DefaultHttpHeaders(true
instead.
Additionally, another vulnerable component is the StyxToNettyResponseTranslator due to also disabling the HTTP Header validation built into netty in this location.
DefaultHttpResponse nettyResponse = new DefaultHttpResponse(version, httpResponseStatus, false);
new DefaultHttpResponse(version, httpResponseStatus, false);
disables the built-in validation in Netty. Please use the constructor new DefaultHttpResponse(version, httpResponseStatus, true);
Proof of Concept
The following test plugin proves that there is no header validation occurring.
static class VulnerablePlugin implements Plugin {
@Override
public Eventual<LiveHttpResponse> intercept(LiveHttpRequest request, Chain chain) {
String header = request.queryParam("header-value").get();
LiveHttpRequest newRequest = request.newBuilder()
.header("myRequestHeader", header)
.build();
return chain.proceed(newRequest).map(response ->
response.newBuilder().header("myResponseHeader", header).build()
) ;
}
}
@Test
public void simpleHeaderInjectionVulnerabilityPOC() {
Plugin vulnerablePlugin = new VulnerablePlugin();
// a simple way to mock the downstream system
HttpInterceptor.Chain chain = request -> {
assertThat(request.header("myRequestHeader").orElse(null), is("test\r\nAnother: CRLF_Injection"));
return Eventual.of(response(OK).build());
};
// an example request you expect your plugin to receive
String encodedGet = URLEncoder.encode("test\r\nAnother: CRLF_Injection");
LiveHttpRequest request = get("/foo?header-value=" + encodedGet)
.build();
// since this is a test, we want to wait for the response
LiveHttpResponse response = Mono.from(vulnerablePlugin.intercept(request, chain)).block();
assertThat(response.header("myResponseHeader").orElse(null), is("test\r\nAnother: CRLF_Injection"));
}
Additionally, if you run this LiveHttpResponse from this test through the StyxToNettyResponseTranslator::toNettyResponse
, ideally, it would have caused an exception to be thrown. In its current state, it does not.
Similar Vulnerabilities
There have been reports of similar vulnerabilities in other popular libraries.
GHSA-35fr-h7jr-hh86 -> CVE-2019-16771
GHSA-mvqp-q37c-wf9j -> CVE-2019-17513
Finding
This vulnerability was found due to this query that Jonathan Leitschuh contributed to the Semmle QL project.
https://lgtm.com/rules/1510696449842/alerts/
JSON: https://advisories.ecosyste.ms/api/v1/advisories/MDE2OlNlY3VyaXR5QWR2aXNvcnlHSFNBLTZ2N3Atdjc1NC1qODl2
Source: GitHub Advisory Database
Origin: Unspecified
Severity: Moderate
Classification: General
Published: over 4 years ago
Updated: almost 2 years ago
CVSS Score: 6.5
CVSS vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:N
Identifiers: GHSA-6v7p-v754-j89v, CVE-2020-6858
References:
- https://github.com/HotelsDotCom/styx/security/advisories/GHSA-6v7p-v754-j89v
- https://nvd.nist.gov/vuln/detail/CVE-2020-6858
- https://twitter.com/JLLeitschuh
- https://github.com/advisories/GHSA-6v7p-v754-j89v
Blast Radius: 3.1
Affected Packages
maven:com.hotels.styx:styx-api
Dependent packages: 12Dependent repositories: 3
Downloads:
Affected Version Ranges: <= 1.0.0.beta8
Fixed in: 1.0.0-rc1
All affected versions:
All unaffected versions: 0.0.5, 0.7.3, 0.7.4, 0.7.5, 0.7.6, 0.7.7, 0.7.8, 0.7.9, 0.7.10