The Dangers of Misconfiguring CORS Headers on a Web API Server

Did your web application security assessment come back with a misconfigured Cross-Origin Resource Sharing (CORS) policy?

Cross Origin Resource Sharing (CORS) allow origin any

When browsers execute code from within a page’s source code, they cannot distinguish malicious code from safe code. Modern browsers (Chrome, Edge, Safari, and FireFox) restrict requests to third-party domains by default unless someone modified the policy.

Web developers occasionally have legitimate reasons to allow third-party domains to retrieve data. Using Cross-Origin Resource Sharing (CORS) headers, you can allow these cross-site requests while mitigating the threat of Cross-Site Request Forgery (CSRF) attacks. Please note that your CORS policy is NOT a substitute for anti-csrf tokens, which should be your first line of defense against CSRF attacks. Both are important and should be properly configured.

 

CORS and CSRF Attacks

In a CSRF attack, an attacker crafts a link or web page to perform a request from a remote server in the context of the authenticated user. The user is tricked into clicking a link or pointing a browser to the attacker-controlled web page, and the malicious code performs an action based on the user’s authenticated account permissions.

 

A common CSRF attack uses GET requests using links that contain specific parameters used by the web application to perform an action. For instance, suppose the following GET request triggers your application to return an authenticated user’s name in a JSON object:

 

yoursite.com/userinfo.php

 

This page might use a cookie or session variable to identify that the user requesting information is the legitimate authenticated user. Using the right parameters, your API could perform an action based on the user’s authenticated permissions. For instance, suppose you have parameters that send an email to a given address in the URL’s query string such as the following:

 

yoursite.com/userinfo.php?sendemail=attacker@attackersite.com

 

If the email generated contains sensitive information, an attacker can obtain it by tricking a user into clicking the above link. Even if you detect authentication using cookies or a session, the attack would be successful.

 

This page could also be used as an API resource for your web application where you use it to retrieve data from another domain or from a mobile application. Using the user’s current credentials, the user is not required to authenticate each time the URL is called.

 

An attacker can use the API URL to retrieve user information in the context of the already authenticated user session. For instance, suppose an attacker links a user to the following URL:

 

attackersite.com/hello.html

 

Within this page, the attacker can include JavaScript that makes a call to your site’s API “userinfo.php” page. Calls to external pages in JavaScript are often done using an Ajax object called “XMLHttpRequest” available from the browser. When a call is made from the attacker’s site page, the browser’s CORS policy will reject the request and return an error. A browser’s CORS policy is meant to block attacks including Cross-Site Scripting (XSS) that could be used to retrieve remote data and send it to a third party. A malicious JavaScript call from the attacker’s site could look like the following:

 

var xhr = new XMLHttpRequest();

xhr.open(“GET”, “yoursite.com/userinfo.php”, true);

var response = xhr.responseText;

 

The “response” variable would contain the user’s information and expose it to the attacker. However, with CORS, this request would be blocked provided the API’s server is not misconfigured.

 

Bypassing CORS Restrictions Using Access-Control-Allow-Origin

 

For a single application, CORS can be a helpful security tool but it’s also a hindrance for legitimate applications. Suppose your application runs on “domain-b.com.” You need to retrieve information about a user from the “yoursite.com/userinfo.php” API endpoint. The call is within your website environment, but CORS will block it due to it being on a third-party domain.

 

Developers decided that there was a need to legitimately bypass CORS, so the “Access-Control-Allow-Origin” server header was introduced. This header provides a whitelist of domains allowed to make calls to the local application from an external domain. The user’s browser verifies that the domain making the call is included in the whitelist and allows an application to bypass CORS restrictions.

 

Using the same scenario above, “yoursite.com” would return the “Access-Control-Allow-Origin” server header telling the browser that a third-party call from “domain-b.com” is permitted. The browser would then allow a call to “yoursite.com” from “domain-b.com.”

 

To allow the CORS bypass, you would configure “yoursite.com” with the following header:

 

Access-Control-Allow-Origin: http://yoursite.com

 

Notice that the HTTP protocol is included. In most cases, you would use HTTPS, which should be used instead of HTTP when making requests for sensitive information on the internet. If you want to allow multiple sites to access data from this domain, your code should identify the requesting domain and add it to the “Access-Control-Allow-Origin” programmatically.

 

Creating a Vulnerability with Misconfigured Headers

The Access-Control-Allow-Origin header allows developers and server administrators to set a wildcard. The header looks like the following:

Access-Control-Allow-Origin: *

This configuration tells the browser that any domain can make a call to the resource. The misconfiguration tells browsers to bypass all CORS restrictions and allow any web application to make a call to the resource. This misconfiguration leaves users open to several attacks including XSS and CSRF.

 

Now, consider the previous scenario where an attacker convinces users to click on a phishing link that points to:

 

attackersite.com/hello.html

 

The web page contains a JavaScript script such as the following:

 

var xhr = new XMLHttpRequest();

xhr.open(“GET”, “yoursite.com/userinfo.php”, true);

var response = xhr.responseText;

 

This is a simple example, but APIs that return extremely sensitive information could be vulnerable to this type of attack, leaving users open to identity theft. The attacker can obtain any users’ personal information without restrictions.

 

Using the asterisk in the Access-Control-Allow-Origin header is worse than eliminating the header altogether. The wildcard gives all sites permission to retrieve data. This is one of the most common vulnerabilities on the web because developers are in a rush to meet deadlines.

 

How to Configure Your CORS Policy

The better way to handle this situation is to to simply maintain a whitelist of allowed domains. Remember that the domain URL should include the protocol and HTTPS (TLS) should be used if you’re delivering sensitive information.

The Access-Control-Allow-Origin header is beneficial for developers that have several applications on separate domains, but when it’s misconfigured it can create a dangerous vulnerability. When auditing your application for security concerns, use this header properly to ensure that it does not leave it open to exploits.

For Apache

You can configure Apache using mod_headers. It is enabled by default, however you may want to verify this by running:

 a2enmod headers

Set the following.

 <IfModule mod_headers.c>
   Header set Access-Control-Allow-Origin "INSERT_ALLOWED_ORIGIN_HERE"
 </IfModule>

Then restart Apache.

 

For IIS

Configuration can be accomplished using the IIS CORS Module. More information can be found Here.

 

 

Using X-Frame-Options to Avoid Clickjacking In Your Web Application

Perhaps you just had a web security test performed and clickjacking was a finding in your report. It’s not uncommon for web developers to hide elements on a web page until the user performs an action, but like other web programming functionality that seems innocent, it can also be used for malicious purposes. Using CSS and JavaScript, an attacker can use an iframe to display your website pages and use it to perform malicious activity called clickjacking. Clickjacking isn’t a new concept, but many web developers don’t take the necessary precautions to protect user accounts from this cyber security attack.

 

How It Works

Before explaining the issue of clickjacking, it’s important to understand how it works. Web developers use CSS and layers building pages with pixel placements. Layers are the building blocks for elements that lie on the Z axis. The X axis is a line that runs from the left side of the screen to the right. The Y axis runs from the top of the screen to the bottom. Now imagine a line that starts at the monitor and expands towards your face. This is the Z axis.

 

When a developer lays out a page using CSS, layers can be placed at the bottom to the top of the Z axis. For instance, an image placed on the Z axis at 2 would be placed on top of an image placed on the Z axis at 1. Elements placed on lower value properties sit “behind” elements set at higher values. This is how a developer can stack elements on a web page and design a layout using CSS.

 

The Clickjacking Setup

Another option for the developer is opacity. Opacity sets the way an element fades in or out of the page. Imagine a ghost when it fades in and out from view. Opacity set at lower values will fade out of view. When opacity reaches 0, it’s invisible to the user. The element is still accessible. Should a user click an element with an opacity set to 0, a click event still occurs even though the user can’t see it. This is the foundation for clickjacking — tricking users into clicking an invisible element.

 

Now, imagine placing an iframe on a page with opacity set to 0 and a button placed underneath. Since the iframe’s opacity is set to 0, the user cannot see the content placed over its elements. Should a user click a hidden element within the iframe, the event is passed to the iframe content. This might not seem terribly effective, but the right clickjacking event can cause several issues for the reader.

 

Using clickjacking, an attacker was able to distribute malware using Twitter in 2009 (http://shiflett.org/blog/2009/twitter-dont-click-exploit). The Twitter retweet button was hidden over another button that said, “Don’t click me.” The attacker tricked users into clicking the visible button, which really retweeted the URL to a malicious web page.  In 2008, Adobe was forced to update its popular Flash software when an attacker used clickjacking to trick users into providing permissions to a computer’s camera and microphone.

 

Protecting Your Web Pages

http response x-frame-options remediate clickjacking

Hijacking user clicks allows an attacker to perform numerous attacks on a user that lands on a web page with hidden elements, but the key issue with these attacks is the iframe. The iframe contains the hidden content, which can be used maliciously. Website owners can disallow their content in an iframe using the X-Frame-Options HTTP response header. This header should be used as a cyber security effort to protect your users.

With custom server headers, you can set the response from your hosting application such as IIS or Apache. Any pages that change user security settings or perform instant actions from a button should always have X-Frame-Options configured.

X-Frame-Options has three options, so you can still allow content in an iframe if you need it. The three options are:

X-Frame-Option: deny 

    • This option disallows the page from loading in an iframe regardless of the domain. If you never want the content in an iframe, this is the option you should set.

X-Frame-Option: sameorigin

    • This option tells the browser that it can load content in an iframe if the iframe’s domain is the same as the outer page. Use this option if you need to place content in an iframe on your own site.

X-Frame-Options: allow-from https://sampledomain.com 

    • Allow the “sampledomain.com” site to frame your content in an iframe. Use this option if you have a third-party domain that uses your site in an iframe.

 

How to Configure X-Frame-Options for IIS

  • Navigate to the web.config file (usually at %systemroot%\system32\inetsrv\config)
    • Add <add name="X-Frame-Options" value="SAMEORIGIN" />
      x-frame options iis web config

 

 

How to Configure X-Frame-Options for Apache

  • Navigate to /etc/apache2/httpd. conf OR /etc/apache2/apache2
    • Add:
      Header set X-Frame-Options "DENY"

 

Alternatively, the Content-Security-Policy response header has a frame-ancestors flag which can work in place of this header for supporting browsers.