Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Unrestricted deserializing from a privileged context allows an attacker to supply crafted input which that, upon deserialization, can yield objects that the attacker does not have would otherwise lack permissions to construct. Construction of One example is the construction of a sensitive object such as a custom class loader is an example (See SEC10-J. Do not allow the unauthorized construction of sensitive classes). Consequently, avoid deserializing from a privileged context. When deserializing requires privileges, programs must strip all permissions other than the minimum set required for the intended usage.

Noncompliant Code Example

...

(CVE-2008-5353: ZoneInfo)

CVE-2008-5353 describes a Java vulnerability discovered in August 2008 by Sami Koivu [CVE 2008]. Julien Tinnes subsequently In Aug 2008 a vulnerability in the JDK was discovered by Sami Koivu. Julien Tinnes wrote an exploit that allowed arbitrary code execution on multiple platforms that ran running vulnerable versions of Java. The problem arose primarily due to resulted from deserializing untrusted input from within a privileged context. The vulnerability involves the ZoneInfo object (sun.util.Calendar.Zoneinfo)ZoneInfo class, which, being a serializable class, is by design deserialized by the readObject() method of the ObjectInputStream class.

Consider the The default security model of an applet that does not allow access to sun.util.calendar.ZoneInfo since all classes because applets cannot be permitted to invoke any method from any class within the "sun" package are treated as untrusted. Thus. As a result, prior to JDK 1.6 u11, the acceptable method for an unsigned applet to deserialize a Zoneinfo ZoneInfo object was to execute the call from a privileged context, such as a doPrivileged() block. This constitutes a vulnerability since A vulnerability results because there is no surefire guaranteed method of knowing whether the serialized stream contains a Zoneinfo object and not bona fide ZoneInfo object rather than a malicious serializable class. The vulnerable code casts the malicious object to the ZoneInfo type, which typically causes a ClassCastException if the actual deserialized class is not a ZoneInfo object. This exception, however, is of little consequence as because it is possible to store a reference to the newly created object in some a static context so that the garbage collector does not cannot act upon it.

A non-serializable or serializable nonserializable class can be extended and its subclass can be made serializable or becomes so automatically. Also, a subclass automatically becomes serializable if it derives from a serializable class. During deserialization of the subclass, the Java Virtual Machine (JVM) calls the no-argument constructor of the most derived superclass that does not implement java.io.Serializable either directly or indirectly. Calling the no-argument constructor allows it to fix the state of this superclass.

In the following code snippet, class A's no-argument constructor is called when C is deserialized because A does not implement Serializable. Subsequently, Object's constructor is invoked. This procedure cannot be carried out programmatically, so the JVM generates the equivalent bytecode at runtime. Typically, when the superclass's constructor is called by a subclass, the subclass remains on the stack. However, in deserialization this does not happen. Only the unvalidated bytecode is present, which allows any security checks within the superclass's constructor to be bypassed because the complete execution chain is not scrutinized.

Code Block
class A { // Has Object as superclass
  A(int x) { }
  A() { }
}

class B extends A implements Serializable {
  B(int x) { super(x); }
}
 
class C extends B {
  C(int x) { super(x); }
}

's constructor (for instance, if class A derives from class B which in turn derives from class C, class C's constructor will be executed when A is deserialized. If B implements Serializable then A may not implement it) and proceeds to call Object's constructor. Subsequently, the fields of the subclass are deserialized. At this point, there is no subclass code on the stack and the most derived superclass's constructor is executed with no restrictions since because doPrivileged() allows the immediate caller to exert its full privileges. Since Because the immediate caller java.util.Calendar is trusted, it exhibits full system privileges.

For exploiting this condition, often, a A custom class loader is desirablecan be used to exploit this vulnerability. Instantiating a class loader object requires special permissions that are made available by the security policy that is enforced by the SecurityManager. An unsigned applet cannot carry out this step by default. If However, if an unsigned applet can execute a custom class loader's constructor, it can effectively bypass all the security checks (since it has the requisite privileges as a direct consequence of the vulnerability). A custom class loader can be designed to extend the System Class Loadersystem class loader, undermine security, and carry out forbidden functions prohibited actions such as reading or deleting files on the user’s filesystemuser's file system. Moreover, any legitimate security checks in the constructor are meaningless as because the code is granted all privileges. The following noncompliant code example illustrates the vulnerability:

Code Block
bgColor#FFcccc

try {
  ZoneInfo zi = (ZoneInfo) AccessController.doPrivileged(
    new PrivilegedExceptionAction() {
      public Object run() throws Exception {
        return input.readObject();
      }
  });
  if (zi != null) {
    zone = zi;
  }
 } catch (Exception e) 
{
  // Handle error
}

Compliant Solution (CVE-2008-5353: Zoneinfo)

This vulnerability was fixed in JDK v1.6 u11 by defining a new AccessControlContext INSTANCE, with a new ProtectionDomain. The ProtectionDomain encapsulated a RuntimePermission called accessClassInPackage.sun.util.calendar. ThereforeConsequently, the code was granted just about enough permissions the minimal set of permissions required to access the sun.util.calendar class. This whitelisting approach guaranteed that a security exception would be thrown in all other cases of invalid access. The code also uses the two-argument form of doPrivileged(), which strips all permissions other than the ones specified in the ProtectionDomain.

Code Block
bgColor#ccccff

private static class CalendarAccessControlContext {
  private static final AccessControlContext INSTANCE;
    static {
      RuntimePermission perm =
          new RuntimePermission("accessClassInPackage.sun.util.calendar");
      PermissionCollection perms = perm.newPermissionCollection();
      perms.add(perm);
      INSTANCE = new AccessControlContext(new ProtectionDomain[] {
          new ProtectionDomain(null, perms)
      });
    }
  }

// ...
try {
  zi = AccessController.doPrivileged(
       new PrivilegedExceptionAction<ZoneInfo>() {
         public ZoneInfo run() throws Exception {
           return (ZoneInfo) input.readObject();
         }
       }, CalendarAccessControlContext.INSTANCE);
} catch (PrivilegedActionException pae) { /* ... */ }
} catch (Exception e) { }
if (zi != null) {
  zone = zi;
}

Risk Assessment

Deserializing objects from a an unrestricted privileged context can lead to result in arbitrary code execution.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

SER37SER08-J

high High

unlikely Likely

medium Medium

P6

L2

Automated Detection

...

P18

L1

Related

...

Guidelines

MITRE CWE

CWE-250, Execution with Unnecessary Privileges

Bibliography

 

...

Image Added Image Added Image Added

Search for vulnerabilities resulting from the violation of this rule on the CERT website.

References

Wiki Markup
\[[API 06|AA. Java References#API 06]\] 
TODO

SER36-J. Do not use the default serialized form for implementation defined invariants      11. Serialization (SER)      11. Serialization (SER)