Did your web application security assessment come back with a misconfigured Cross-Origin Resource Sharing (CORS) policy?
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:
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:
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:
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:
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:
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:
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.
You can configure Apache using
mod_headers. It is enabled by default, however you may want to verify this by running:
Set the following.
<IfModule mod_headers.c> Header set Access-Control-Allow-Origin "INSERT_ALLOWED_ORIGIN_HERE" </IfModule>
Then restart Apache.
Configuration can be accomplished using the IIS CORS Module. More information can be found Here.
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
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:
- 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.
- 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 name="X-Frame-Options" value="SAMEORIGIN" />
How to Configure X-Frame-Options for Apache
- Navigate to /etc/apache2/httpd. conf OR /etc/apache2/apache2
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.
Organizations choose a Pen Testing company based on who has the best marketing material and smoothest salespeople. Obviously they do not realize they are doing it! Most of my career has been spent working at various web application penetration testing companies. So that is the focus of this rant.
After conducting web and mobile application penetration tests for years and billing for my insight, it seemed high time to give a bit advice for free. Other Pen Testing companies are going to hate me for giving you this information, unless they are actually a solid firm.
First of all, and this may be obvious, salespeople are NOT your friends. Legitimate companies automatically promote their own over the years and the managers / most senior pen testers end up doing sales. If there is not an SME on the call…. Hang up.
Before signing anything ask questions and try to trip them up! Come armed with questions and see the depth of their knowledge! Remember, they are likely bringing their best to impress you.
Basic Web App Assessment Questions
- There has been a lot of talk about SSI (server-side include) injection we are wondering how you check for these issues and if you see them very often, how serious are they?
- XXE (XML External Entity) is another area of concern for our developers. Could you tell us a bit more about this potential threat and maybe describe how such a vulnerability could impact our web application?
Web application penetration testing companies use the OWASP (Open Web Application Security Project) checklist. And we all check for the same issues over and over for every web app assessment. Therefore, any senior web application penetration tester will be able to answer basic questions such as these with little to no hesitation. However, if like many pop-up Pen Testing companies they are noobs and cannot answer basic questions….run! Legit web app pen testers will provide your company with more value than their slicked back haircut will.
Web App Testing Certifications
Certifications are great for penetration testers getting into the industry and to some extent show an individual is at least halfway competent, depending on the web app Pen Testing certificate. Though to be honest, most of the best pen testers have no degree or certifications. Think back to high-school and the “passion” many people had. Those were the days. Haha.
GWAPT (GIAC Web Application Penetration Tester)
This certification is as of writing still the most well-known web application Pen Testing certification. Those of us that have been doing app testing for very long have either taken course and the test or unofficially done so via coworkers. This is very basic material; ANYONE can pass this course. Does not mean much. Just that their company was willing to spend a few grand.
OSWE (Offensive Security Web Expert)
An individual with this cert is probably a legitimate web application penetration tester. However, this mostly means the Pen Testing company they work for was more willingly to pay for the course than an individual without it. As stated previously most of the HIGHLY skilled testers have no certifications because they were not needed (or in some cases around) when we started. Why spend thousands of dollars on certifications if we do not need to?
University / College Degree
Meh, this means very little and may even be a negative (joking). Brace yourself here comes a very controversial thought… if they cannot hack the system how can you expect them to hack the planet? Again, somewhat joking, but honestly my colleagues teach and write the college curriculum. Have you ever hired someone fresh out of college? You know what I mean.
Whatever pen testing company you hire, you are giving total control and access to everything. Think about that. If your application is important enough to conduct a web application assessment, then you certainly want to make sure you are not hiring criminals posing as a security firm. For example, here in America computer crimes are not tolerated and ethical hackers make too good of a living pen testing web applications to risk incarceration. Risk vs reward.
When vetting web app PenTesting companies.
- Ask questions
- If they act like a politician and avoid answering the question, they do not know the answer. Run!
- Helpful, but these are just to help pen testers to get their foot in the door when starting out. Sufficiently senior pen testers often do not have them.
- Four-year degree equivalent to six (6) months of experience?
- Offensive security might have made me a bit paranoid. But personally I’d never hire a pen testing company that couldn’t be arrested if they turned out to be criminals.