Synapse CORS Configuration - January 2023
This document was created for review by the Synapse engineering team to respond to
Findings
A recent penetration test performed by NCC has found a vulnerability in our Cross-Origin Resource Sharing (CORS) configurations for synapse.org (Portal services) and repo-prod.prod.sagebase.org (Repo services). The report describes how an XSS attack could be orchestrated to exfiltrate user credentials from an arbitrary subdomain of *.synapse.org. The scenario is unlikely, but high impact; a successful attack would fully compromise the Synapse account of each affected user.
Our Portal services' CORS configuration enables us to retrieve and re-use authentication credentials across all *.synapse.org sites, so users don’t have to authenticate multiple times. NCC recommends that we restrict this functionality to a whitelist of known subdomains of synapse.org. Because this functionality is only provided on *.synapse.org, our whitelist would not need to contain any origins that are not subdomains of synapse.org.
To follow this recommendation, we must estimate the level of effort of, and perform the following:
Regularly or programmatically compile a list of valid
synapse.orgsubdomains.Add functionality to the portal to utilize this list of subdomains to restrict valid
.synapse.orgorigins.
The domain for the repository services (repo-<stack>.prod.sagebase.org) were also specified in the report, but the services are not vulnerable to the same attack, and specific findings were not provided. There is a related misconfiguration that does not expose us to any vulnerability, but we should address it to reduce the risk of vulnerabilities introduced by future changes.
Both of our applications allow any origin to handle the responses of non-credentialed requests. Taking similar action against non-credentialed requests would require a much greater technical burden. We should seek further correspondence with NCC to determine if the above would be sufficient action to resolve the issue.
Background
This section will summarize the purpose of CORS, the HTTP response headers relevant to the penetration test findings, and outline the threat model that a “proper” CORS configuration is supposed to protect against.
Relevant CORS headers
By default, browsers restrict JavaScript code from accessing the response of an HTTP request to an origin different from that of the open window or frame. For certain types of requests, browsers send a “preflight” request to determine if the request would be allowed before it is sent. The server can set values in certain headers to loosen these restrictions. This document will focus only on the headers referenced in the penetration test and issue for the sake of brevity.
The Access-Control-Allow-Origin response header is used by the browser to determine if the JavaScript environment should be able to read the response of a cross-origin request. The value may be "*", an Origin (e.g. https://www.synapse.org), or null.
The Access-Control-Allow-Credentials response header is used by the browser to determine if a response can be exposed to the JavaScript that initiated the request in cases where the request includes credentials automatically attached by the browser (e.g. cookies). The value may be "true" or null. Note that the browser will always reject responses to requests with credentials if Access-Control-Allow-Origin is "*" (reference). Additionally, some modern browsers currently block, or plan to block, third-party cookies by default.
There are also additional response headers that can be used to restrict which request headers and methods are permitted, and which headers can be exposed in JavaScript.
Aside: CORS does not guarantee that a request will not be sent. Certain requests may trigger a preflight check that will cause a browser to not send a request, but this does not apply for all types of requests. For this reason, a strict CORS configuration does not eliminate the risk of CSRF attacks. A more appropriate solution for this threat model is to reject requests on the server based on the origin.
Current behavior of affected web applications
The penetration test reported this vulnerability across two different web applications that have server-side components: the repository app hosted on repo-<stack>.prod.sagebase.org, and the servlet for the web portal hosted on <stack>.synapse.org.
Service | Domain | Access-Control-Allow-Origin | Access-Control-Allow-Credentials | Implications |
|---|---|---|---|---|
Synapse-Repository-Services |
|
|
| Any origin can access response data. Cross-origin sites cannot access response data sent with credentials. |
SynapseWebClient |
|
|
| Any origin can access response data. Only *.synapse.org origins can access response data sent with credentials. |
Portal
For requests originating outside of .synapse.org, Access-Control-Allow-Origin is *. This is appropriate because some portal services provide content specifically designed to be rendered on other sites (e.g. snippets on social media).
At the time of writing, the portal has served content to 863 unique origin values in the past 30 days. Full data omitted, methods shown below.
The value for Access-Control-Allow-Credentials changes based on the origin. If the origin ends with .synapse.org, then we set the header to be true and set the value of Access-Control-Allow-Origin to match the request origin, so that the browser will permit using requests with credentials.
The only known scenario that depends on this configuration is that we persist authentication state across *.synapse.org domains. When logging in to Synapse on a .synapse.org site, a cookie is stored that contains the access token. The cookie is HttpOnly, so to get this access token into JavaScript, the browser will call the Portal service GET /Portal/sessioncookie with the cookie. The service responds with the access token in the response body, which can be stored in-memory in JavaScript. Because of our current CORS configuration, this functionality only works from .synapse.org domains. The proposed change from NCC does not compromise this behavior.
No changes would be required with respect to the dev environment because the Portal dev instance (portal-dev.dev.sagebase.org) is not configured to provide a shared authentication session.
As shown in the expandable section below, there are 22 unique .synapse.org origins that are utilizing the service that provides credentials in a cross-origin context. To follow NCC’s recommendation, we must be able to compile this list of valid subdomains, and then pass them to the portal to selectively filter the subdomains that are allowed to use credentials.
Repo
Today, the Access-Control-Allow-Origin header for the repository services is always *. This means that JavaScript code running on any origin may view the responses in cross-site requests to the repository services.
Restricting the Access-Control-Allow-Origin header to a whitelist would have substantial technical cost. Within a recent 30 day window, we have allowed requests from 46 different origins: