9

Recently, a vulnerability in Facebook's messenger app which allowed attacks to access a users private messages via cross-origin AJAX was patched and disclosed.

Simple Bug allows Hackers to Read all your Private Facebook Messenger Chats

The root of this issue was misconfigured cross-origin header implementation on Facebook's chat server domain, which allowed an attacker to bypass origin checks and access Facebook messages from an external website.

screenshot

The name of "Originull" and screenshot seem to indicate the problem is the following header:

Access-Control-Allow-Origin: null

But this leaves me wondering, how exactly a value of null leads to a vulnerability. This doesn't look like a valid origin, unless you were to somehow visit a website from the domain of null (actually, it would need to be http://null or https://null, as the protocol would need to be included).

I checked, and null is not actually an allowed value in the same way * is, in Chrome or Firefox.

XMLHttpRequest cannot load http://other.localhost/ajax.php. The 'Access-Control-Allow-Origin' header contains the invalid value 'null'. Origin 'http://localhost' is therefore not allowed access.

(Using a value of * does work however, so clearly just being null is not enough for arbitrary pages to access these resources.)

Is there some feature or bug in browsers that read null as *? Or some feature in browsers, like pages opened by a data URI, that allow matching to null? How does this vulnerability work?

Alexander O'Mara
  • 8,774
  • 6
  • 34
  • 38
  • Google returns this: https://www.w3.org/TR/cors/#access-control-allow-origin-response-header "The Access-Control-Allow-Origin header indicates whether a resource can be shared based by returning the value of the Origin request header, "*", or "null" in the response." – schroeder Dec 14 '16 at 20:39

2 Answers2

11

I'm Ysrael and I'm the researcher that found this vulnerability.

Let's divide your question into 2 parts: A. How did the Origin of the browser become null? B. How the null Origin affect Facebook servers?

Let's start with A. The Origin is part of the CORS mechanism and it is intended to tell the server where the request comes from. When the server gets the request, the server can decide to allow this Origin to receive the response. One of the ways to bypass this protection was to find an Open-Redirect within one of the pages, and then to direct the user to dataURI schema. In the past, dataURI received the previous Origin because there was no other Origin to give him. As a security improvement, the modern browser sets the Origin to null so the XHR requests from this dataURI page won't have the proper Origin. In Chrome, this is the situation in any case, and in Firefox it happens only when the page refreshed via meta tag to dataURI.

So this is how the Origin became null.

The 'Originull' attack uses this behavior in order to bypass security checks that are based on the Origin, because most of the time, the programmers won't think of null as the value in this field.

Now let's get to part B. How this affected Facebook.

Facebook uses Access-Control-Allow-Origin on its Messenger servers, because they use a different sub-domain.

Most likely, the Messenger sub-domain has a security filter on the entrance, and then the requests are passed to the internal server that responds to the users. When the server wanted to respond, it took the value from the request's Origin and returned it on the Access-Control-Allow-Origin header. This development design allows Facebook to keep up the allowed Origins in one place only.

The messenger sub-domain also allows regular GET requests. Regular GET requests didn't have an Origin header at all. In many development languages, a non-exist Header returns the value null.

So, the filter has a condition that allows null to pass (so the GET requests will pass correctly), and the server takes the value that it receives in the request's Origin header (null) and returns it to the client in the Access-Control-Allow-Origin header.

Simple, right? ;)

You can find the technical details and screen shots in the full-disclosure document on BusSec's web site at: https://www.bugsec.com/wp-content/uploads/2016/12/Blog-Post-BugSec-Cynet-Facebook-Originull.pdf

Ysrael Gurt
  • 126
  • 2
  • 2
    The original research is of James Kettle from PortSwigger. He'd presented it in OWASP AppSecUSA 2016. Please refer to http://blog.portswigger.net/2016/10/exploiting-cors-misconfigurations-for.html for more details. You should have, at least, cited his blogpost or presentation slides. – 1lastBr3ath Dec 17 '16 at 07:11
3

It's possible to exploit Access-Control-Allow-Origin: null because resources loaded over things like data URI's and sandboxed iframes use the null origin. A PDF documenting the exploit confirms that Originull used a data URI document to exploit this header to achieve cross-origin access.

For this reason, the W3C recommends avoiding returning this value for the header.

7.4. Avoid returning Access-Control-Allow-Origin: "null"

It may seem safe to return Access-Control-Allow-Origin: "null" , but the serialization of the Origin of any resource that uses a non-hierarchical scheme (such as data: or file: ) and sandboxed documents is defined to be "null". Many User Agents will grant such documents access to a response with an Access-Control-Allow-Origin: "null" header, and any origin can create a hostile document with a "null" Origin. The "null" value for the ACAO header should therefore be avoided.

The simple string comparison of CORS as applied to "null" is controversial. Some believe that "null" should be treated as a keyword token indicating the lack of an Origin, which, when tested, should never compare as equal to another "null" Origin. (As is the case with null values in SQL, for example.) It is unwise to build systems which rely on the "null" equals "null" comparison as this behavior may change in the future.

So as it turns out, a value of null currently means nothing special. It's not the same as *, it's just a not-so-special origin which can currently match against origin-less resources.

So if you return this header (even by accident):

Access-Control-Allow-Origin: null

Your resources will currently be accessible cross-origin.

Alexander O'Mara
  • 8,774
  • 6
  • 34
  • 38