[S]uppose website B set the header
Access-Control-Allow-Origin: *, can this cause any concrete security risk to the user who is browsing website A (suppose website A is malicious)?
The answer is very context-dependent, but by indiscriminately using
Access-Control-Allow-Origin: *, you may expose yourself to some types of attacks. I cover two of them below:
- Server bound to an inaccessible network interface
- Distributed client-side brute-force attack against login
Server bound to an inaccessible network interface
In particular, consider a situation in which site B is accessible by an unauthenticated victim only from a privileged position within the target network (e.g. behind a network firewall). In such cases,
- because no ambient authority (like cookies) is involved, the presence or value of the
Access-Control-Allow-Credentials header is irrelevant; and
- the attacker, by tunnelling through to site B via the victim's browser when she visits site A, can read site B's responses from site A.
A real-life example
A few years ago, a similar vulnerability affecting multiple JetBrains IDEs was disclosed. Those IDEs would start a server bound to
localhost with an excessively permissive CORS policy, which allowed an external attacker to exfiltrate sensitive data. The server in question reflected arbitrary origins in
Access-Control-Allow-Origin (as opposed to using a wildcard
*) but the distinction is irrelevant, in this case.
The OWASP testing guide mentions this risk:
Access-Control-Allow-Origin: *] cannot be used with the
Access-Control-Allow-Credentials: true at the same time, it can be dangerous where the access control is done solely by the firewall rules or the source IP addresses, other than being protected by credentials.
James Kettle (a.k.a. albinowax from PortSwigger), in his AppSec EU 2017 talk about CORS misconfiguration, further discusses CORS misconfigurations that do not involve credentials.
See also James's thoughts on the topic in written form:
Access-Control-Allow-Credentials: true], the victim user's browser will refuse to send their cookies, meaning the attacker will only gain access to unauthenticated content, which they could just as easily access by browsing directly to the target website. However, there is one common situation where an attacker can't access a website directly: when it's part of an organization's intranet, and located within private IP address space. Internal websites are often held to a lower security standard than external sites, enabling attackers to find vulnerabilities and gain further access. [...] If users within the private IP address space access the public internet then a CORS-based attack can be performed from the external site that uses the victim's browser as a proxy for accessing intranet resources.
Private Network Access is a WICG specification whose goal is to protect against attacks issued from "less private" networks (e.g. a server accessible at
example.com) against a "more local" target (e.g. a server running on
localhost). It's already partially implemented in Chromium.
Distributed client-side brute-force attack against login
An attacker could even mount a distributed client-side brute-force attack against login by deploying a command-and-control server that would feed different candidate credentials to different victims (who happen to land on the malicious page). Such a distributed attack could prove difficult to thwart because IP-based or fingerprint-based protection (e.g. rate limiting) wouldn't be viable. Tim Tomes and Kevin Cody described such an attack in their DerbyCon 2019 talk.