Yassine ABOUKIR

Web App Security Consultant & ISCAEist


Security impact of a misconfigured CORS implementation

novembre 1, 2015Yassine ABOUKIR10 Comments

It has been quiet some time I have not blogged about anything new, so I hope this blog post is sufficient to catch up my inactivity 🙂 It is also worth mentionning that this vulnerability has earned me quiet few good rewards from bug bounty programs.

HTML5 brought us some great new features to power the web by providing support for latest multimedia and server communication. Besides, all the latest versions of modern browsers have their support for HTML5. The features are designed to make it easy to include, and handle multimedia and graphical content on the web without having to use any third-party plug-ins or APIs. Cross Origin Resource Sharing is one of the implementations that HTML5 brought into light.

Wikipedia defines Cross-origin resource sharing (CORS) as «  a mechanism that allows restricted resources (e.g. fonts) on a web page to be requested from another domain outside the domain from which the resource originated. ». So, CORS came essentially to eliminate some restrictions imposed by the Same-origin policy which would block a AJAX requests from accessing data on a web page unless it is coming from the same origin.

In simple words, Imaging the example.com wants to access some data on another website, suppose site.com. This type of request traditionally wouldn’t be allowed under the browser’s Same Origin Policy. However, by supporting CORS requests, site.com can add a few special response headers that allows example.com to access the data.

I would love to explain how CORS is implemented but, unfortunately, the topic of this blog post will not cover that particular point. We would rather focus on the security aspect of this functionnality.

You can use Curl to check if the website has CORS enabled or not. You can simply type the following command :

The -H « Origin: http://evil.com » flag is the third party domain making the request. Substitute in whatever your domain is.

The –verbose flag prints out the entire response so you can see the request and response headers.

Capture d’écran 2015-10-30 à 23.58.36

The server may respond with:

  • An Access-Control-Allow-Origin header in its response indicating which origin sites are allowed. For example:

  • An error page if the server does not allow the cross-origin request :

  • An Access-Control-Allow-Origin (ACAO) header with a wildcard that allows all domains:

Now, a wildcard same-origin policy is appropriate when a page is considered completely public content and it is intended to be accessible to everyone such as assets on CDN. However, the security misconfiguration that most developers skip is allowing cross-domain requests from all origins to pages that contains sensitive content. For example, setting Access-Control-Allow-origin response header with a wildcard in a page where user API key is stored, which means that all websites are allowed to access that page via ajax calls. Consequently, any attacker can retrieve the content of the page and particularly extract the API Key from the source code.

To illustrate how a misconfigured CORS can be exploited, we will take the example of a web application that stores user authenticity token in meta tag.

CSRF token

After I have intercepted a few http responses I noticed that the application have CORS enabled and set Access-Control-Allow-Origin header with a wildcard *

To extract the CSRF token, we are going to send the website an AJAX request that will crawl the code and copy the token.

You can insert the above code in an HTML page and send the link to the victim. The extracted value will be sent in the background to a PHP file grab.php that will catch the token and store it in a text file (Scenario 1). Don’t forget to modify the name of the meta tag, length of the token, PHP file link.

You can either store it in a text file and later craft a CSRF attack against the victim. Otherwise, the attacker could have already set up a page that will catch the token and, simultaneously, send a forged request to the application on behalf of the user (Scenario 2)

Scenario 1 : The Php file will catch the token and store it in pwn.txt

 

Scenario 2 : The php file will catch the CSRF token and imediately send a forged request to the application in order to add the attacker’s address mail.

The most interesting capability exposed by both XmlHttpRequest and Access Control is the ability to make « credentialed » requests that are aware of HTTP Cookies and HTTP Authentication information. But, when responding to a credentialed request,  server must specify a domain, and cannot use wild carding. Consequently, You should also note that if the CSRF token is associated with user session, then the extracted token will not be authenticated and cannot be used to craft a working CSRF exploit. However, based on my experience in penetration testing and bug hunting there are some web application that lacks best security practices and do not regenerate the token once the user is authenticated. Consequently, the previously extracted token can be reused to attack the user.

The following video is the proof of concept of a similar vulnerability discovered on Maximum.com and that I successfully exploited to grab the users’ authenticity token :

Although CORS can be very useful, its use carries some security implications that users should be aware of. A few tips on the use and configuration of CORS extracted from the OWASP website.

  • Ensure that URLs responding with Access-Control-Allow-Origin: * do not include any sensitive content or information that might aid attacker in further attacks.
  • Allow only selected, trusted domains in the Access-Control-Allow-Origin header. Prefer whitelisting domains over blacklisting or allowing any domain (do not use * wildcard nor blindly return the Origin header content without any checks).
  • Don’t rely only on the Origin header for Access Control checks. Browsers always send this header in CORS requests, but it may be spoofed outside the browser. Application-level protocols should be used to protect sensitive data.

References :

https://en.wikipedia.org/wiki/Cross-origin_resource_sharing

http://www.html5rocks.com/en/tutorials/cors/

https://www.dionach.com/blog/a-case-of-a-misconfigured-cors-implementation

This article has 10 comments
  1. Rui Silva
    1 novembre 2015

    Thanks for tutorial 🙂
    It’s helps a lot
    Thank you again 😉

  2. Haji
    1 novembre 2015

    Very well explained brother.

  3. Sam
    1 novembre 2015

    Thanks for sharing !

  4. VinothKumar
    1 novembre 2015

    Nice Article Bro 🙂

  5. Ayoub FATHI
    2 novembre 2015

    Great article. And great way to go 🙂 Keep on dude!

  6. Sam
    2 novembre 2015

    @Yassine can be catch the response of post request (response body) also ? instead of just Crawling things via GET ??

  7. Abdellah Oukrchet
    2 novembre 2015

    Thank you so much fot tutorial.. 🙂
    L3z

  8. robert
    3 février 2017

    Is it possible to exploit font files somehow? Why are font files same origin in some browsers? Is it really because of security or something else?

    your captcha is the worst piece of shit i have ever seen btw. please use google captcha.

  9. Srikanth GM
    9 février 2017

    As per my understanding this will only work as long as the
    Access-Control-With-Credentials is not set to TRUE. Since as per the statement by mozilla

    « When responding to a credentialed request, the server must specify an origin in the value of the Access-Control-Allow-Origin header, instead of specifying the « * » wildcard. »

    And if done so, the request would fail. Now practical application of the above method would not be feasible since CSRF attacks need the user to be authenticated and send their cookie along with the forged request.

    Unless there is an XSS vulnerability in the vulnerable site, the above method does not seem practical. Kindly explain if I have mis-understood.


Leave a Reply

Prove you are not a Bot * Le temps imparti est dépassé. Merci de saisir de nouveau le CAPTCHA.