February 13, 2013
This article was contributed by Linda Jacobson
Since August 2012, there has been increasing buzz about security holes in
Oracle's Java implementation. The hubbub reached such proportions that
US National Public Radio (NPR) stations
were heard repeating recommendations (originating from CERT)
that people disable all Java plugins on
their systems. The noise started when Security Explorations (SE), a
one-person Polish company run by Adam Gowdiak, went public about security
vulnerabilities after
malware was detected that exploited two issues SE had reported to
Oracle in April 2012.
On February 1, 2013, Oracle released a new version
of Java that fixed most of the issues that SE uncovered, with the
exception of one, identified as "issue #51." This article describes the
history of this process, where the security vulnerabilities were detected,
an explanation of the different kinds of vulnerabilities detected, and how
all of these relate to OpenJDK.
SE has been examining security issues in Java, and detecting points of
attack, since 2002. It has worked closely and, for the most part,
amicably with Sun and Oracle, and has exercised what has been called
"responsible disclosure," (i.e. notifying companies about their
vulnerabilities, and refusing to release details about known holes,
until the companies have had time to fix them). This relationship was
strained during 2012 after Oracle failed to address all of the issues that SE
had reported to it in the patches to Java over a six-month period. After the
malware attack of August 2012, SE went public, presenting
at Devoxx [PDF], and releasing a
technical report [PDF] in November
2012. These disclosures claim that, as far back as 2005, SE reported to Sun
on many of the
weaknesses that led to the current issues. Both disclosures detail the
specific issues
detected by SE and ways to exploit
them to effect a complete security compromise of a Java installation.
Around the same time, SE stepped up its research, finding not only
31 issues in Oracle's Java, but 17 in IBM's version, and 2 in Apple's.
Of these, 17 Oracle bugs could result in a full compromise of the Java
security sandbox, which is the means by which Java isolates potentially
untrustworthy software. Since OpenJDK uses the same code base as Oracle's
Java, those issues were present in OpenJDK as well. SE's November
technical report lists 50 known
issues in total. Several more were reported to Oracle by SE since that report,
but are not yet public. After Oracle's February update of Java only one issue,
issue #51, remains unresolved.
Most of the issues discovered relate to the Java
Reflection API. This is
a powerful tool that provides for dynamic loading of classes, as well as
access to their members, and is what makes component architectures, like
Java Beans, possible. However, there is inherent risk in the very
nature of allowing access across unknown classes.
The kinds of access allowed include:
- Obtaining an object of a given
class, given the name of the class, via forName().
- obtaining the methods of a class using getMethods()
- Invoking a method in another class via the method invoke(),
which allows the caller to provide the arguments to the called
methods.
There are Field and Method classes that correspond to the
underlying fields and
methods, as well as a Constructor class
that allows you to create new instances of classes. These all inherit from the
java.lang.reflect.AccessibleObject class, which has a private
field called "override". If override is true then
operations and accesses are allowed to the caller regardless of the
caller's privileges.
In its research, SE found numerous places where combinations of
misuses of forName() and invoke(), along with improper
access to
the override field
allowed systems to become vulnerable. In addition, there is a type field
of the Field object that represents the type of an underlying object.
In the technical report, Gowdiak imagined a scenario where:
the type of the field denoting java.lang.Object value is changed to
int. In such a case, access to fields of the object may lead to
memory accesses from the base pointer denoted by the integer value
as it will be confused with the object reference.
SE further asserts that one can impersonate trusted callers
via controlling the parameters of Reflection API calls made by system
classes.
In Java 7, Oracle added another level of security, via indirection,
called a "lookup class." What SE found was that the lookup classes
themselves were vulnerable. The security check is conducted in
the MethodHandles.Lookup class prior to any method handle creation. This
check allows for access to arbitrary members (methods, constructors, and
fields) of restricted classes if the lookup object and a target class
are from the same class loader namespace. Also, by default, a lookup
object instance uses a caller of the MethodHandles.Lookup() method as a
lookup class. Therefore, a security breach can be effected by calling
this method from system code to create a lookup object with a system class.
In SE's technical report there are numerous examples of all the
exploitation vectors that they used to compromise the
Java security sandbox. All were combinations of the weaknesses described
above, since no one weakness by itself was sufficient to escape the sandbox.
There are a number of consequences of these exploits, including: an
attacker could define a
class and cause it to be loaded into a privileged class loader
namespace; security checking could be completely turned off (via calling
SetSecurityManager() with a NULL argument); permissions of an unsafe
object could be changed at will; malicious classes could inherit from
privileged classes and redefine trusted methods with malicious ones; or
any combination of those.
The relationship of OpenJDK to Oracle's Java Standard Edition (SE) is
complex. OpenJDK is
the reference implementation for Oracle's Java SE. However, bug fixes do
not automatically propagate from one to the other (in either direction),
since they the projects are developed independently. That said, one week after Oracle
released its fixes to Java, OpenJDK 7 was updated to
reflect all of the fixes. OpenJDK users will want to upgrade at the
first opportunity.
In its report, SE noted that it searched for holes in Java precisely
because Java's
security is so good. A more timely response from Oracle might have been
desirable. However, at this point, nine months from when Oracle learned of
the deficiencies, it issued a release that fixed all of the bugs detailed
in SE's technical report, as well as
several that were only identified in the last couple months.
[The author wishes to thank the many
contributors to the Fedora project's Java developers list, who provided
valuable information on the upgrades to OpenJDK and their
relationship to Oracle's releases. A special shout out goes to Omair
Majid, who provided links to the information as well.]
(
Log in to post comments)