Detect the Same-Origin Redirection with a bug in Firefox's CSP Implementation
Firefox’s bug in CSP implementation, which will be fixed in Firefox 62, provides us the way to detect the redirection of any given URL when accessed with the victim’s Firefox. Practically, OAuth is one of interesting features which requires redirections. Here is a PoC (Fingerprinting with CSP violation) which detects the following points:
- whether you have logged in Facebook with your Firefox.
- (if you are logged in FB,) whether you have logged in a site (in this case, foursquare.com, cybozulive.com, www.ikyu.com) with Facebook Login. It works only with Firefox (<= 61).
Content-Security-Policy and the redirection
Some years ago @homakov reported the malicious use case of CSP (Content-Security-Policy) in his blog: Using Content-Security-Policy for Evil. It uses the behavior of CSP when a redirection occurs. Content Security Policy Level 2 provides some mitigations for this problem, but even now we can detect a Cross-Origin redirection from another Origin with CSP; Origin A can know whether Origin B redirects to Origin C.
In more detail, let’s observe how the following code acts with
Content-Security-Policy: script-src a.example.com b.example.com/foo:
The behavior of the code will be classified into the following 4 patterns:
//a.example.com/examplereturns the status code 200, nothing interesting happens and it will be loaded..
//a.example.com/exampleredirects to //a.example.com/anotherexample.php`, nothing interesting happens and it will be loaded.
//a.example.com/exampleredirects to //b.example.com/bar
, no violation occurs and it will be loaded even if the policy allowsb.example.com/foo`. This is a countermeasure for path information leakage reported by @homakov.
//a.example.com/exampleredirects to //c.example.com/bar`, a violation occurs and the redirect will be blocked.
In other words, we can detect the redirect through CSP’s report (
report-uri directives work). For example, when you want to know whether
https://a.example.com/path/file redirects to other Origin, all you have to do is to prepare the following HTML with
Content-Security-Policy: script-src a.example.com; report-to /report:
If it redirects to other Origin in the browser that loads this code, a violation will be sent to
/report. This allows us to know that the Cross-Origin redirection occurs from another Origin.
However, a Same-Origin redirection cannot be detected with this technique. First, whitelist-based policy (e.g.
script-src a.example.com/path/file) allows all the Same-Origin redirection even if the path is specified because the path in the policy is ignored as to the redirection. Besides, the nonce-based redirection won’t cause any violation even if some Cross-Origin and Same-Origin redirection occurs; it is reasonable for the policy with
nonce. So, Origin A cannot observe that a content provided in Origin B redirects other content inside the Same-Origin (B).
A bug in Firefox’s CSP implementation (FIXED in Firefox 62)
Recently, a bug in Firefox’s CSP implementation was reported: CSP: Scripts with valid nonce get blocked if URL redirects. This bug allows us to detect the redirection to a Same-Origin content.
For example, how does Firefox work with the following HTML code (now let
nonce be a legitimate one)?
<script nonce="foobar" src="https://a.example.com/file1">
Now let’s think the case when
https://a.example.com/file1 redirects to a Cross-Origin content (e.g.
https://b.example.com/otherorigin). Unlike other browsers, Firefox reports a violation with the policy
script-src 'nonce-foobar' and block it. Additionally, Firefox blocks loading the script when
https://a.example.com/file1 redirects to a Same-Origin content (e.g.
To sum up, Firefox’s CSP implementation reports a violation when nonce-based policies are adopted and a redirect occurs! This enables us to detect the all redirection of a content from an Origin different to the one of the content.
If even a Same-Origin redirection can cause a CSP violation, they can be reported with
Case Study: Facebook Login
OAuth is one of interesting features which requires redirections. One of the examples is Facebook Login, which is provided in many web services.
Let’s look how an application with Facebook work carefully. Once a user requested the OAuth process, a HTTP request to Facebook (like
https://facebook.com/dialog/oauth?scope=email&redirect_uri=https%3A%2F%2Fexample.com&client_id=[the App's client ID]) will occurs. Then, Facebook reacts differently depending on the user’s state:
- If the user has ever permitted the use of the application and the Re-Authentication is disabled, it redirects to the page specified with
redirect_uri(in almost all the cases it is a Cross-Origin redirection).
- If the user has ever permitted the use of the application and the Re-Authentication is enabled, it redirects to
- If the user has never permitted the use of the application, it returns a webpage with a status code 200.
- If the user is not logged in, it redirects to
Some Cross-Origin and Same-Origin redirection occurs.
Now we can prepare a application (now we call that App A) which nobody has never permitted, which enables us to detect the state 4 (because the user cannot permit App A, so if the redirection occurs it must be the case 4). Besides, the violation report of CSP includes the host name which was blocked by CSP. It means that when the Same-Origin redirection are blocked by CSP, the report says
www.facebook.com is blocked; this allows us to tell the case 1 from the case 2. If no violation report is sent, we can know the case 3 occurs.
Here is a PoC (Fingerprinting with CSP violation) which detects the following points with this technique:
- whether you have logged in Facebook with your Firefox.
- (if you are logged in FB,) whether you have logged in a site (in this case, foursquare.com, cybozulive.com, www.ikyu.com) with Facebook Login.
Please note that it works only with Firefox (<= 61). Have a happy CSP! :-)