This post was originally published in French only. We translated it in 2026 so the archive reads the same in both languages. Read the original →

Over the past few days, some development teams have clearly had a little too much of their beloved brew... Organized crime, for its part, had the immense pleasure of abusing Java itself. This article walks through the sequence of events over the last few months that led to the delightful week we had from August 27 to 31, 2012, along with a critical look at how the situation unfolded. The article doesn't stay up in the clouds for long, though: an analysis of the proof-of-concept exploit available online for one of the Java 7 flaws can be found at the end of the article.

Much of the information in the following timeline is available on the Security Explorations website. (http://www.security-explorations.com/en/SE-2012-01-status.html).

April 2, 2012:


Security Explorations, a Polish IT security research firm, publishes a press release (http://www.security-explorations.com/en/SE-2012-01-press.html) announcing that its team has found 19 security flaws in Java 7. The team contacted Oracle to report the discovery. The next day, Oracle confirms receipt of the information. What's interesting is that the company's announcement gives no technical details on the flaws in question. The team simply states that most of the flaws exist because Java secure coding best practices were not followed.

April 4 to 27, 2012


12 more vulnerabilities are reported to Oracle by the same research firm. This brings the total to 31.

August 23, 2012


Oracle informs the Security Exploration team that 19 flaws have been fixed and that a patch will be ready for the next Java update cycle (October 16, 2012). The remaining issues are still under investigation and will eventually be fixed.

This is where things get interesting. The research team, well aware of the impact of the vulnerabilities it had found, was careful not to give out too many technical details about them. Yet toward the end of the week of August 20 to 24, 2012, a significant increase in malware being spread through malicious Java applets was observed. On August 26, a proof-of-concept exploit (http://pastie.org/4594319) for one of the vulnerabilities reported by the team turns up freely on the Internet. Several blogs (http://blog.fireeye.com/research/2012/08/zero-day-season-is-not-over-yet.html) talk about the exploit and the news spreads like wildfire through the security community.

The major problem with these Java flaws: there is no way to secure user workstations. The only option being to disable Java, which can't always be done, users are left to fend for themselves against one of the biggest security issues of the year. And as if that weren't enough, this flaw affects Java. Let's not forget that the whole point of Java... is to be platform independent. So the number of potential targets (http://www.securityfocus.com/bid/52016) is huge.

Within hours of the proof of concept being published, the exploit had already been integrated into the Blackhole exploit kit (http://en.wikipedia.org/wiki/Blackhole_exploit_kit) and into Metasploit (http://www.metasploit.com/). Clearly, the interested parties weren't sitting idle! Shortly afterwards, several domains ( http://blog.fireeye.com/research/2012/08/java-zero-day-first-outbreak.html?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed:+FE_research+(FireEye+Malware+Intelligence+Lab) ) took part in infection schemes using the Java 7 flaws.

Eventually, in a dramatic twist, on August 30, while many thought they would really have to wait until October 16 for a Java update, Oracle announces that an update (Java 7 update 7) is available (http://www.oracle.com/technetwork/topics/security/alert-cve-2012-4681-1835715.html) for download. Amen.

However... Let me ask you a question:

How many of you actually went ahead and updated your system right away so it wouldn't be vulnerable? Interesting...

Although several issues have been resolved, the work isn't over yet... Not all of the flaws reported by Security-Explorations have been fixed. What's more, as of August 31, 2012, the date this article was written, a new flaw has been reported by the same team...

Analysis of the proof of concept


Which brings us to the proof of concept itself. This analysis simply explains how the proof of concept works.

On a Microsoft Windows system affected by the vulnerability, running the code simply results in the Windows calculator opening. The code presented here (http://www.hackfest.ca/wp-content/uploads/2012/09/JavaPOC.txt.zip) has been analyzed and can be run safely on your systems.

Figure 1 shows lines 69 to 73 of the Gondvv.java file (the proof-of-concept file). You can see a call to the disableSecurity() method. You can also see a call to the exec() method of the Runtime class, which launches the Windows calculator. Note that the exploit code is actually a Java applet. As such, the applet should not have the rights required to launch calc.exe, since the applet is supposed to be confined by the Java sandbox.

-Figure 1

disableSecurity();
Process localProcess = null;
localProcess = Runtime.getRuntime().exec("calc.exe");
if(localProcess != null);
    localProcess.waitFor();

So the disableSecurity() method is used in the exploit to bypass the security measures normally enforced on Java applets. Figure 2 shows the code of the disableSecurity() method, found between lines 33 and 41 of the exploit.

-Figure 2

Statement localStatement = new Statement(System.class, "setSecurityManager", new Object[1]);
Permissions localPermissions = new Permissions();
localPermissions.add(new AllPermission());
ProtectionDomain localProtectionDomain = new ProtectionDomain(new CodeSource(new URL("file:///"), new Certificate[0]), localPermissions);
AccessControlContext localAccessControlContext = new AccessControlContext(new ProtectionDomain[] { localProtectionDomain });
SetField(Statement.class, "acc", localStatement, localAccessControlContext);
localStatement.execute();

The author starts by declaring and initializing the localStatement object, of type Statement. The Statement class is normally used to make an on-demand call to a method of a class, with a list of parameters specified when the Statement is executed. In this case, executing the Statement will call the setSecurityManager() method with an empty object as its parameter. This method is used to change the SecurityManager used by the system. SecurityManager is a class responsible, among other things, for checking rights when methods are called. So when an application attempts an unauthorized action, a SecurityException is raised by the SecurityManager.

Next, the author declares and initializes a localPermissions object of type Permissions. This object holds a list of permissions that can be used to... validate permissions. In this case, the localPermission object contains the AllPermission() permission. So every permission there is is contained in this object. After that, the localProtectionDomain object of type ProtectionDomain is created and initialized. It's important to know that the ProtectionDomain class is used to configure the level of rights on a domain. Here, you can see that the protection domain specified is file:///, which means the root of the host system. In addition, the localPermission object is used to assign permissions to the protection domain. The result is a protection domain with "AllPermissions". Then the localAccessControlContext object of type AccessControlContext is created using the protection domain created earlier. The AccessControlContext class is used to make access decisions based on the domain/context associated with it. Since it is associated with a domain that holds every permission on the system root, any action whose rights are checked against localAccessControlContext and that takes place from the system root will be allowed. But this context still has to actually be used for the rights check... So the author calls the SetField method, found between lines 54 and 63 of the exploit. The method's code is shown in Figure 3.

-Figure 3

Object arrayOfObject[] = new Object[2];
arrayOfObject[0] = paramClass;
arrayOfObject[1] = paramString;
Expression localExpression = new Expression(GetClass("sun.awt.SunToolkit"), "getField", arrayOfObject);
localExpression.execute();
((Field)localExpression.getValue()).set(paramObject1, paramObject2);

The first three lines of this method create an array of objects with "Statement.class" as the first object and "acc" as the second. Once the array is ready, the author creates an object named localExpression of type Expression. The Expression class inherits directly from the Statement class and can therefore be used the same way. In this case, however, the class targeted when the expression is executed is sun.awt.SunToolkit. This class is obtained by calling the GetClass() method written by the exploit's author. When the expression is executed, it will return a Field object referencing the "acc" attribute of the Statement class. It turns out, however, as Figure 4 shows with the declaration of the acc attribute of the Statement class from the Statement.java file (http://www.docjar.org/html/api/java/beans/Statement.java.html), that this attribute is private. A user should therefore not be able to reach the attribute directly.

-Figure 4

private final AccessControlContext acc = AccessController.getContext();

The acc field is therefore the field holding the AccessControlContext object responsible for validating permissions when the statement is executed. Figure 5 shows the code that runs when the getField() method is called. This code comes from the SunToolkit.java file (http://www.docjar.com/html/api/sun/awt/SunToolkit.java.html).

-Figure 5

return AccessController.doPrivileged(new PrivilegedAction() {
  public Field run() {
      try {
        Field field = klass.getDeclaredField(fieldName);
              assert (field != null);            
              field.setAccessible(true);        
              return field;
       } catch (SecurityException e) {
               assert false;
       } catch (NoSuchFieldException e) {
               assert false;
       }
      return null;
  }//run
});

You can see that a privileged action is performed to gain access to the acc field of the Statement class. Once access is obtained, the field is made accessible to the user. This code runs when the execute() method of the localExpression object is called on line 61 of the exploit. The user can therefore control the AccessControlContext that will be used to validate their permissions. Then, on line 62, the getValue() method of the localExpression object is used to retrieve the Field object returned by the code shown above. This Field object is set using the paramObject1 and paramObject2 objects, which reference the localStatement and localAccessControlContext objects respectively. The result is that the programmer controls the rights of the localStatement object. The user is thus able to trigger a privilege escalation that lets them change the execution rights of a statement of their choosing. Execution then returns to the disableSecurity() method, where the statement is executed. So when the statement runs, since the user has elevated their rights, the system's SecurityManager is replaced by an object with no ability whatsoever to manage rights, effectively giving the Java code running in that applet every right available on the system. So if you get caught on a site running this kind of code... and you're on a Windows system... and, like... nearly every Windows user, you have administrator rights... the attacker gets administrator rights on your system.

So we can see that this flaw is possible because of a design error in Java and because the product's developers didn't follow best practices.

The case of this flaw's proof of concept also raises some questions about the practice of publishing proof-of-concept code for security flaws. Indeed, as you can imagine, all an attacker has to do is modify line 71 of the proof of concept to run code of their choosing and turn the proof of concept into an exploit usable in a large-scale attack. In fact, this exploit's code is so easy to weaponize that that's exactly what the developers of the Blackhole kit did (http://www.f-secure.com/weblog/archives/00002414.html).

The conclusion of this article is simple. We have seen that, unfortunately, flaws remain on systems long after they've been discovered. Moreover, contrary to popular belief, it has been shown that many important flaws are often extremely easy to exploit.

Note: Between the time I started and finished writing this article, a new flaw... in Java 7 update 7 (the patch for the flaw presented here... released less than 36 hours earlier) was discovered (http://www.securityfocus.com/archive/1/524073) by the same team, bringing the total number of flaws to 32.