This part is titled "Keys". The intention is to list the key items that must remain elusive to the attacker in order for the JVM to remain unharmed. Compromising any of these will probably give the attacker full privileges. I'll also show, at least in theory, how each of them could be used for this.
The Security Manager
The Security Manager is at the very core of the Java Security Model. It essentially decides whether any given operation is allowed or not. While the JVM is running, the "current" or "installed" Security Manager is defined by the static java.lang.System.security field. The type of the field is java.lang.SecurityManager which is a concrete, non-final class, so the SecurityManager is either an instance of that class, or a subclass. A null value in the field is interpreted as security being turned off, thus: if that field can be set to null, security will be turned off.
The field is private, though, so one can’t just waltz in and try to set it to null.
There's a public static method for defining a new Security Manager:
System.setSecurityManager(SecurityManager)
If that method is called with a null parameter, the underlying field will be set to null and security will be turned off. In order for that call to succeed though, the current Security Manager is consulted to see if the caller has the setSecurityManager RunTime permission. Thus, possessing the setSecurityManager permission effectively gives code full privileges.
It would not be necessary to set a null SecurityManager to defy security. If the attacker can define his own SecurityManager and set it as the current SecurityManager, he can allow all operations and elevate his privileges. Aside from accessing the System class, a Security Manager class can be defined with the JVM startup argument
-Djava.security.manager=EvilUnsecureManager
Also, compromising the (class) definition of the SecurityManager class or that of any of its subclasses would probably give the attacker full control. More about compromising class definitions in a later item.
ClassLoader
The ClassLoader is responsible for loading class definitions. It also ultimately controls the privileges of each class that's being loaded. The ClassLoader.defineClass(...) methods have the access modifier protected, so only subclasses can access them. If you can create a valid subclass of the ClassLoader, you can call the protected methods and define classes with full privileges. This is essentially how CVE-2008-5353 leverages the privileged deserialization.
An example of how to define a new class with full privileges when you have access to the defineClass method:
byte[] evilBytecode = …
AllPermission allPerm = new AllPermission();
PermissionCollection allPermissions = allPerm.newPermissionCollection();
allPermissions.add(allPerm);
Class cls = defineClass(null, evilBytecode, 0,
evilBytecode.length, new ProtectionDomain(null, allPermissions));
cls.newInstance();
Java access modifiers
The Java access modifiers (private/protected/"default"/public) for classes, fields and methods are probably the one single most important thing keeping the whole security together. I've personally used protected and default very little in code I've written for any normal project. However, the security architecture heavily relies on them.
A lot of things are kept inaccessible for an attacker by marking methods, fields and classes with the default access modifier. It means that only the classes from the same package can access those items. Same package here refers to same package within the same classloader. Thus, it doesn't aid the attacker to define his applet class to be in the same package as some trusted Sun class, because the packages are classloader specific - if your class in package abc was defined in a different classloader than another class in package abc, it is effectively in a different package as far as access control goes.
If the attacker gained access to private members, it would be possible to set null to java.lang.System.security and disable Java security.
If the attacker gained access to protected members, it would be possible to call defineClass on the default applet ClassLoader and define classes with full privileges.
If the attacker gained access to default members, there'd be a lot of members in any number of classes that could be accessed to gain full privileges. There are almost 40 different versions of a package-private class SecuritySupport (or SecuritySupport12) that does privileged file reading, property access, URL access and so on.
Reflection may be used to circumvent some of the access control restrictions. More about reflection in its own item.
The final keyword
As I discussed in a previous post, "final" has very distinct functions when used in conjunction with classes, methods and fields.
If the final modifier of a class could be overridden, in other words, if the attacker managed to subclass a final class, he might subclass java.lang.String and create his own mutable Strings. More about String immutability in its own item.
Overriding final methods and modifying the value of final field could also possibly be abused, but I have no concrete examples of those cases.
Type system integrity
Yet another crucial part of the security architecture is the Java type system integrity. If the attacker can pass his own Foo class where a String class is expected he can probably create the effect of mutable Strings.
Or reversely, if the attacker is able to put a Java system class in a variable whose type is Bar (a user controlled class), he can probably gain access to private members.
Reflection
Java Reflection API gives dynamic access to classes, fields and methods. If one is able to call setAccessible(true) on Field and Method objects, Java access control can be somewhat bypassed. If you call setAccessible(true) on an otherwise inaccessible field or method (private/protected/default) you gain access to it. Example:
Field security = System.class.getDeclaredField("security");
security.setAccessible(true);
security.set(null, null);
However, many of the Reflection API calls require privileges and if a Security Manager is installed the attacker won't get far. To successfully run the above example, one would need to possess the accessDeclaredMembers and suppressAccessChecks privileges.
If the attacker succeeds in obtaining a Field object for java.lang.System.security and calling setAccessible(true) on it, he can turn off Java security by calling field.set(null, null).
Privileged Deserialization
Privileged Deserialization can be leveraged by the attacker in (possibly) many ways, probably the simplest being the creation of a custom Serializable ClassLoader which can then be used to define classes with full privileges. This was at the core of CVE-2008-5353.
A privileged block which does deserialization from a stream which can be manipulated by the attacker can probably be leveraged in other ways, too, since the serialization/deserialization protocol is quite complex and flexible.
SecurityManager protected packages (sun., com.sun.deploy., etc)
These packages have a more relaxed security. The security manager and applet ClassLoader do not allow applets to access these packages directly. If the attacker was able to access them, there'd probably be several ways to leverage it. It seems to me that currently it is not allowed to reference the following packages:
com.sun.deploy.*
com.sun.imageio.*
com.sun.javaws.*
com.sun.jnlp.*
com.sun.xml.internal.bind.*
com.sun.xml.internal.ws.*
sun.*
System Properties
The System Properties (System.getProperties()) contain a lot of influential stuff. If an attacker was able to manipulate the System Properties he could probably elevate his privileges.
System.getProperties(), despite of the name which suggest read access, returns a reference to the internal Properties object, so any modification to this object will alter the system properties.
Read access to the properties has the implication of privacy. The attacker can find out the logged on username and several system paths:
java.class.path = C:\PROGRAM~1\Java\jre6\classes
java.endorsed.dirs = C:\Program Files\Java\jre6\lib\endorsed
java.ext.dirs = C:\Program Files\Java\jre6\lib\ext;C:\WINDOWS\Sun\Java\lib\ext
java.home = C:\Program Files\Java\jre6
java.io.tmpdir = C:\DOCUME~1\ADMINI~1\CONFIG~1\Temp\
java.library.path = ...
sun.boot.library.path = C:\Program Files\Java\jre6\bin
user.dir = …
user.home = C:\Documents and Settings\Administrator
user.name = Administrator
There are known cases where for example being able to alter the java.ext.dirs lead to a vulnerability. I imagine this type of an attack only works if you can provide the property at JVM startup.
sun.misc.Unsafe
Unsafe is in a sun. package and therefore inaccessible to applets. It also has a private constructor, and the singleton getter method checks that the caller's classloader is null (system class) before handing out the object, so one could say it is very well guarded. And for a reason, since it truly is the Chuck Norris of Java classes.
Unsafe allows direct access to fields and memory. It allows, for example, for you to put an int value into an object field. No security checks and no access control takes place when using Unsafe. So it would be trivial to leverage Unsafe for privilege escalation. I’ll leave the how as a mental exercise for the reader.
Field usf = Unsafe.class.getDeclaredField("theUnsafe");
usf.setAccessible(true);
Unsafe unsafe = (Unsafe) usf.get(null);
Field stringChars = String.class.getDeclaredField("value");
long offset = unsafe.objectFieldOffset(stringChars);
String test = "test";
char[] value = (char[]) unsafe.getObject(test, offset);
value[2] = 'n';
System.out.println(test);
String immutability
String immutability is the basis for many operations. String objects contain a private char array that normally cannot be accessed. Should the attacker be able to access the char array and modify String objects, a lot of things could be broken, probably the security, too.
There is no defensive programming in the core classes against mutable Strings, and for a reason; it’d require a lot of code. A mutable String could thus be used in a timing attack, having a set of contents for verification and another set of contents for the actual operation. String instances are also pooled and reused, so the attacker could probably put his instance on the pool and have it be reused by code that’s inaccessible to him.
doPrivileged
If the attacker can control a trusted doPrivileged block, or code called by it, through means of controlling input, accessed fields, overriding methods, subclassing, deserialization and classloading, etc, the attacker may be able to elevate his privileges.
(Re)defining core classes
If the attacker can compromise the class definitions of not just the most obvious classes (System, ClassLoader, SecurityManager), but any number of menial classes that participate in privileged blocks of code, the attacker could easily elevate his privileges. I'm currently working on a twist of this type of an attack which should lead to a privilege escalation.
Key Permissions
Every class has a set of permissions associated with it. The permissions depend on where the code comes from (CodeSource) and what the java.security defines as the permissions for that source. There are several permissions that, if an attacker can obtain them for his code, will (probably) lead to privilege escalation:
AllPermission: The permission to do anything.
setSecurityManager: The permission to define a new security manager, set the security manager to null and all code has full permissions.
charsetProvider: Allows for creating mutable strings.
accessDeclaredMembers & suppressAccessChecks: With the combination of these two permissions, you can obtain any field or method, make it accessible and access it (call method, read/write field value). The most straightforward way to leverage this would be to set a null security manager.
Showing posts with label applets. Show all posts
Showing posts with label applets. Show all posts
Saturday, February 27, 2010
Saturday, December 19, 2009
FilePermission class leaks sensitive information
Somebody might consider it ironic that the security class which is responsible mapping access permission to files (java.io.FilePermission) is actually leaking information about the filesystem.
FilePermission uses a doPrivileged block to obtain a canonical path to the file/folder given as a parameter to the constructor. The canonical path is then stored in a private and transient field (called cpath) which has no accessor method.
The canonical path is security-sensitive, because if you give it the input of "." it will become the full (canonical) path to the current execution directory.
Also, in windows, if I give it a path, such as "c:\windows" it becomes "C:\WINDOWS" on my machine, as both the drive letter and windows folder are uppercase. If I give it a path that does not exist, such as "C:\whatever" it does not get altered. Thus I can test the existence of files and folders.
The cpath is not directly accessible, but the FilePermission class has a hashCode method, and the implementation is:
So the hashcode of the String of the canonical path is available. I looked into the possibility of reversing the string hash, but it's not really practical. The simple algorith (which is explained here) is easy to reverse, but as it's extremely lossy, the number of strings that have any given hash is very big.
File or folder existence on Windows can be easily tested by giving a toLowerCase and toUpperCase versions of any path to FilePermission and then comparing the hashcodes. If the hashcodes are equal, the file/folder exists, if they're unequal, it doesn't exist.
For example, on my machine, the following:
Yields the output:
true
false
In similar fashion, you could compare the hashes of FilePermissions for ".", "..", "../..", "../../.." until the hashcode stops changing, which means you've hit the root (Drive-Letter:\ on windows or / on linux/unix/etc). The depth of the execution folder can thus be determined and it is possible to try to guess each of the folders of the path individually.
It's not a very serious problem at all, but it's one I found to be amusing both for the simplicity of it and the fact that it's in the very class that is used to map access to files.
FilePermission uses a doPrivileged block to obtain a canonical path to the file/folder given as a parameter to the constructor. The canonical path is then stored in a private and transient field (called cpath) which has no accessor method.
The canonical path is security-sensitive, because if you give it the input of "." it will become the full (canonical) path to the current execution directory.
Also, in windows, if I give it a path, such as "c:\windows" it becomes "C:\WINDOWS" on my machine, as both the drive letter and windows folder are uppercase. If I give it a path that does not exist, such as "C:\whatever" it does not get altered. Thus I can test the existence of files and folders.
The cpath is not directly accessible, but the FilePermission class has a hashCode method, and the implementation is:
384 public int hashCode() {
385 return this.cpath.hashCode();
386 }
So the hashcode of the String of the canonical path is available. I looked into the possibility of reversing the string hash, but it's not really practical. The simple algorith (which is explained here) is easy to reverse, but as it's extremely lossy, the number of strings that have any given hash is very big.
File or folder existence on Windows can be easily tested by giving a toLowerCase and toUpperCase versions of any path to FilePermission and then comparing the hashcodes. If the hashcodes are equal, the file/folder exists, if they're unequal, it doesn't exist.
For example, on my machine, the following:
001 import java.io.FilePermission;
002
003 public class FP {
004 public static void main(String[] args) throws Exception {
005 System.out.println(fileExists("C:/windows"));
006 System.out.println(fileExists("C:/filedoesnotexist"));
007 }
008
009 static boolean fileExists(String name) {
010 return new FilePermission(name.toLowerCase(), "read").hashCode() == new FilePermission(name.toUpperCase(), "read").hashCode();
011 }
012 }
Yields the output:
true
false
In similar fashion, you could compare the hashes of FilePermissions for ".", "..", "../..", "../../.." until the hashcode stops changing, which means you've hit the root (Drive-Letter:\ on windows or / on linux/unix/etc). The depth of the execution folder can thus be determined and it is possible to try to guess each of the folders of the path individually.
It's not a very serious problem at all, but it's one I found to be amusing both for the simplicity of it and the fact that it's in the very class that is used to map access to files.
Tuesday, October 13, 2009
com.sun.corba.se.impl.orbutil.ObjectUtility
Back to security.
Sun's strategy of prioritizing backwards compatibility is something I always appreciated as a developer. Less headaches. Yet, from a security perspective the ensuing "bloatedness" is rather challenging: The attack surface keeps on growing all the time.
So it's not all that surprising to find an applet security problem in an obscure CORBA class buried in the dark depths of the standard libraries.
On the other hand, it's the problems you find in the public java.util, java.io, etc classes that make you really appreciate how very difficult it is to build something secure.
But let's look at one of the aforementioned, obscure CORBA classes today :)
com.sun.corba.se.impl.orbutil.ObjectUtility
It has a problem I found rather interesting, but as far as I could tell, at least in the applet world, it is not exploitable in any serious way. Of course it could be just my lack of ingenuity.
ObjectUtility has two basic functionalities:
-Offer toString functionality to classes that don't implement toString. It recursively lists all the instance field names and their values using reflection and formats the output neatly. I actually use it sometimes as a quick-and-dirty debug to vomiting out object contents. When there is no security manager present it lists all the fields, but with a security manager present it sticks to the public fields (less useful).
-Offer equals functionality to classes that don't implement an equals method. It recursively compares all the instance fields of two objects following somewhat complicated rules.
Let's look at the equals functionality a little bit closer. The logic goes something like this: You give it two objects and it returns true or false depending on perceived equality, with the following details.
-in the case of object fields, recursion is used to compare the two values
-static fields are ignored
-Maps, Sets, Lists and arrays have special handling, where the Collection/array contents are compared individually
-objects x and y of the exact same class (ie. x.getClass() == y.getClass() ) are compared by comparing all the non-static fields individually
-doPrivileged is used to allow access to private fields even with a security manager enabled
-objects x and y of different classes (for example, Object instance and a String instance) are compared by calling equals of the first object, ie. x.equals(y)
Pause for a moment. Absorb the logic. Do you see a problem?
...
This implementation leaks private information. If you compare a malicious object to a sensitive object, in specific cases you can extract references to objects stored in private fields of said sensitive object.
Here's a semi-concrete example. Let's preface it a bit: If you've ever written a Java applet, you'll have noticed that when you use System.out to print some debug information, the output goes to the Java console. How does this happen? The type of System.out is PrintStream. The applet environment sets the System.out as a PrintStream instance which contains contains a Java plugin class TracePrintStream instance, which takes everything written to it and forwards it to be printed in the console.
PrintStream has no method for accessing the inherited (from superclass FilterOutputStream) "out" field, but we can create a new PrintStream and put our own OutputStream inside it. Then compare our PrintStream to System.out. Like this:
So we can get our hands on the TracePrintStream object contained within the PrintStream. I did a quick PoC using this and a thread which kept polling the buffer of the TracePrintStream and on my other laptop with two processors it worked pretty good, it was an incredible CPU hog, but it intercepted everything written to the console by any applet. So if you'd happen to be running a sensitive applet at the same time in the same browser that printed sensitive data in the console it'd be a bad thing. I guess this turned out to be a rather theoretical example anyway.
Other examples that I've tried this on with success: The Collections class has utility methods which return immutable versions of Lists, Maps and Sets. The way they work is that they keep a copy of the original list hidden away in a private field and the getter methods operate on this list and the setter methods throw exceptions. But comparing these immutable collections to malicious collections it is possible to access the collection contained within and modify it. However I couldn't find anything in the core Java where the security depended on the immutability of these collections.
Sun's strategy of prioritizing backwards compatibility is something I always appreciated as a developer. Less headaches. Yet, from a security perspective the ensuing "bloatedness" is rather challenging: The attack surface keeps on growing all the time.
So it's not all that surprising to find an applet security problem in an obscure CORBA class buried in the dark depths of the standard libraries.
On the other hand, it's the problems you find in the public java.util, java.io, etc classes that make you really appreciate how very difficult it is to build something secure.
But let's look at one of the aforementioned, obscure CORBA classes today :)
com.sun.corba.se.impl.orbutil.ObjectUtility
It has a problem I found rather interesting, but as far as I could tell, at least in the applet world, it is not exploitable in any serious way. Of course it could be just my lack of ingenuity.
ObjectUtility has two basic functionalities:
-Offer toString functionality to classes that don't implement toString. It recursively lists all the instance field names and their values using reflection and formats the output neatly. I actually use it sometimes as a quick-and-dirty debug to vomiting out object contents. When there is no security manager present it lists all the fields, but with a security manager present it sticks to the public fields (less useful).
-Offer equals functionality to classes that don't implement an equals method. It recursively compares all the instance fields of two objects following somewhat complicated rules.
Let's look at the equals functionality a little bit closer. The logic goes something like this: You give it two objects and it returns true or false depending on perceived equality, with the following details.
-in the case of object fields, recursion is used to compare the two values
-static fields are ignored
-Maps, Sets, Lists and arrays have special handling, where the Collection/array contents are compared individually
-objects x and y of the exact same class (ie. x.getClass() == y.getClass() ) are compared by comparing all the non-static fields individually
-doPrivileged is used to allow access to private fields even with a security manager enabled
-objects x and y of different classes (for example, Object instance and a String instance) are compared by calling equals of the first object, ie. x.equals(y)
Pause for a moment. Absorb the logic. Do you see a problem?
...
This implementation leaks private information. If you compare a malicious object to a sensitive object, in specific cases you can extract references to objects stored in private fields of said sensitive object.
Here's a semi-concrete example. Let's preface it a bit: If you've ever written a Java applet, you'll have noticed that when you use System.out to print some debug information, the output goes to the Java console. How does this happen? The type of System.out is PrintStream. The applet environment sets the System.out as a PrintStream instance which contains contains a Java plugin class TracePrintStream instance, which takes everything written to it and forwards it to be printed in the console.
PrintStream has no method for accessing the inherited (from superclass FilterOutputStream) "out" field, but we can create a new PrintStream and put our own OutputStream inside it. Then compare our PrintStream to System.out. Like this:
001
002
003 import java.applet.Applet;
004 import java.io.IOException;
005 import java.io.OutputStream;
006 import java.io.PrintStream;
007
008 import com.sun.corba.se.impl.orbutil.ObjectUtility;
009
010 public class StealConsole extends Applet {
011
012 public void start() {
013 PrintStream syso = System.out;
014 PrintStream stealer = new PrintStream(new OutputStream() {
015
016 public void write(int b) throws IOException {
017 }
018
019
020 public boolean equals(Object obj) {
021 System.out.println("Stole: " + obj.getClass());
022 return super.equals(obj);
023 }
024 }, false);
025
026 boolean eq = ObjectUtility.equals(stealer, syso);
027 }
028
029 }
So we can get our hands on the TracePrintStream object contained within the PrintStream. I did a quick PoC using this and a thread which kept polling the buffer of the TracePrintStream and on my other laptop with two processors it worked pretty good, it was an incredible CPU hog, but it intercepted everything written to the console by any applet. So if you'd happen to be running a sensitive applet at the same time in the same browser that printed sensitive data in the console it'd be a bad thing. I guess this turned out to be a rather theoretical example anyway.
Other examples that I've tried this on with success: The Collections class has utility methods which return immutable versions of Lists, Maps and Sets. The way they work is that they keep a copy of the original list hidden away in a private field and the getter methods operate on this list and the setter methods throw exceptions. But comparing these immutable collections to malicious collections it is possible to access the collection contained within and modify it. However I couldn't find anything in the core Java where the security depended on the immutability of these collections.
Wednesday, August 05, 2009
java.net.Proxy and (Im)mutability
Java 6 update 15 fixed some stuff regarding to java.net.Proxy
Quoting:
I'm assuming Sun is referring to something I'd come across a couple months ago myself. I was looking into some things at java.net and came across the Proxy class. The Proxy class javadoc says
Yet the class is public and non-final. It's methods are non-final, too. If you don't see the problem, go a few posts back to the bit that talks about immutability.
Didn't look at the fix yet, but Proxy was very much mutable and so it was possible to create a Proxy object which uses TOCTOU to connect to a host other than the originating host. The proxy has a method which returns the address and a mutable Proxy can be made to return the originating host to the security check and some other address for the actual connection.
I'd done an ultraquick PoC, but hadn't gotten around to warning Sun (not that they needed my help from the look of it), because I was working on some more interesting things.
Quoting:
A security vulnerability in the Java Runtime Environment proxy mechanism implementation may allow an untrusted applet or Java Web Start application to make non-authorized socket or URL connections to hosts other than the origin host.
I'm assuming Sun is referring to something I'd come across a couple months ago myself. I was looking into some things at java.net and came across the Proxy class. The Proxy class javadoc says
A Proxy is an immutable object.
Yet the class is public and non-final. It's methods are non-final, too. If you don't see the problem, go a few posts back to the bit that talks about immutability.
Didn't look at the fix yet, but Proxy was very much mutable and so it was possible to create a Proxy object which uses TOCTOU to connect to a host other than the originating host. The proxy has a method which returns the address and a mutable Proxy can be made to return the originating host to the security check and some other address for the actual connection.
I'd done an ultraquick PoC, but hadn't gotten around to warning Sun (not that they needed my help from the look of it), because I was working on some more interesting things.
Tuesday, August 04, 2009
No Anniversary for JDK13Services
Java 6 update 15 fixes the simplest Java security bug I've found so far. And just before its anniversary (August 18th), so no cake.
It's also the least serious of the bugs so I'm not terribly upset that it took close to a year to fix.
com.sun.media.sound.JDK13Services has a public, static method called getDefaultProviderClass which takes a Class object as a parameter and it returns the system property which corresponds with the full class name. The problem is (was) that you can create your own classes whose names coincide with security sensitive property names, such as user.home, user.name, etc.
The implication is one of privacy.
An example of reading the user.home property and outputting it to System.out in an applet.
This'll only work in a pre-update-15 Java. From the quick look into the new rt.jar bytecode, it looks like they're doing a bunch of if's now to limit the properties you can request.
It's also the least serious of the bugs so I'm not terribly upset that it took close to a year to fix.
com.sun.media.sound.JDK13Services has a public, static method called getDefaultProviderClass which takes a Class object as a parameter and it returns the system property which corresponds with the full class name. The problem is (was) that you can create your own classes whose names coincide with security sensitive property names, such as user.home, user.name, etc.
The implication is one of privacy.
An example of reading the user.home property and outputting it to System.out in an applet.
001 package user;
002
003 public class PropertyThief extends java.applet.Applet {
004
005 public void start() {
006 String usrHome = com.sun.media.sound.JDK13Services.getDefaultProviderClassName(user.home.class);
007 System.out.println(usrHome);
008 }
009 }
010
011 class home {}
This'll only work in a pre-update-15 Java. From the quick look into the new rt.jar bytecode, it looks like they're doing a bunch of if's now to limit the properties you can request.
Thursday, July 30, 2009
Java SE Security - Part II (Immutability)
Since I named the first bit as "Part I" in February, I'm long overdue for the second part. The problem is that my hands are tied by the fact that Sun still hasn't fixed a lot of the things I wanted to write about, so I'm short on material.
Immutability (@wikipedia)
Aside from being a software design pattern, immutability plays a big role in security, as well. At least in an environment such as the Java security sandbox. The Sun Secure Coding Guidelines section about input and ouput talks about making immutable copies of inputs and outputs.
Even if you've never put serious thought into this, the importance of immutability quickly becomes obvious.
Steve: Let's say my method takes a (java.util) List of Strings as a parameter, performs some security validation on the list and then performs some privileged action on the list.
Bob: The problem is that java.util.List is in interface and can be implemented in a mutable way. Also virtually all the public List implementations included in Java are mutable, so one wouldn't even have to go through the trouble of creating a mutable version - one could just use java.util.ArrayList.
The problem with the mutability is that an ill intentioned caller of the method could pass a list which contains different values while the method does its validation, and then another set of harmful values for the actual processing after the validation has passed. This could be done via timing, or by crafting one's own List implementation for a more exact attack. If the method uses .iterator() to iterate through the list, the first call to .iterator() (used by validation) could be made to return one set of Strings and the 2nd call to .iterator() (used by the post-validation processing) could be made to return another set of Strings.
It's a well known, generic problem.
Let's look at some ways to protect your method and what could go wrong with them. Forgive the silliness of some of these examples, it's just to give the notion of how easy it is to get it wrong.
Steve: I could change the method signature to only accept a more specialized StevesImmutableList.
Steve: I'd then define StevesImmutableList as a class whose constructor receives a String array and stores it in a private String array field and only has a getter method which returns the array.
Bob: Arrays are always mutable. The size can't be changed, but the contents (given its size is greater than zero) are free game. And your method is returning a reference to its internal array.
Steve: What if I define my private internal array as final?
Bob: That doesn't help. It'll guarantee that your private field always points to the same array, but the array contents are free game.
Steve: Better have the method call .clone() on the array and return a copy of the array instead of the internal array.
Bob: Your constructor is receiving an array and storing it as the internal array. A caller with bad intentions could create an array, keep a reference to it, pass it to your object and later on modify it.
Steve: Ok, let's call .clone() on the incoming array as well.
Steve: Let's also add an overloaded constructor that receives a List to improve the usability of this class.
Bob: Now you're calling toArray() on a List object that you can't really trust. It could return an array and keep a reference to that array for itself for future modification.
Steve: Ok, let's do a manual conversion of the List to an array.
Steve: It'd also be nice to be able to serialize this object for passing between JVMs and/or storing object state somewhere. So let's make the class implement Serializable.
Bob: Serial data can be constructed in such a way that when read, will contain a String array, followed by a StevesImmutableList containing the same String array in the private field, thus making the object mutable.
Steve: Let's make the private field transient and create a readObject method which reads the array from the stream and then clones it before assigning it to the field. Also create a compatible writeObject method.
Now some examples from core Java classes
java.lang.reflection.Proxy
Proxy has a method (getProxyClass) which takes a ClassLoader and an array of Class objects, that are supposed to be interfaces, as parameters. It performs some validation on the Class array, and then it dynamically defines and returns a new Class for a dynamic Proxy class which implements all the interfaces of the Class array. If the validation fails, the method throws an Exception (and obviously doesn't return anything).
The getProxyClass uses the user-suplied Class array for the validation and later on for the construction of the Proxy class, so it could be called with an array which has one set of classes for the validation and another set of classes for the Proxy construction.
However, the validation here, as far as I can tell, is strictly for usability. Without the validation, if you gave the method an invalid set of parameters it would sometimes fail with some strange class verification exception. With the validation, the caller gets feedback which is more readily understandable.
java.lang.String
Strings are supposed to be immutable. A lot of things depend on the immutability of Strings. There is no defensive programming in the core classes against mutable Strings (which makes sense, because it'd take a lot of work).
The immutability of Strings hinges on the fact that one cannot access the char array in which the String contents are stored. Now, String does leak the internal array to any registered CharSet who wants it. However, registering a CharSet requires a CharSetProvider and that, in turn, requires the charsetProvider permission.
Unsigned applets don't have that permission and can't create their own registered CharSets. But it is something to keep in mind. If you're granting the charsetProvider permission, you're pretty much implicitly giving away full access.
Immutability (@wikipedia)
Aside from being a software design pattern, immutability plays a big role in security, as well. At least in an environment such as the Java security sandbox. The Sun Secure Coding Guidelines section about input and ouput talks about making immutable copies of inputs and outputs.
Even if you've never put serious thought into this, the importance of immutability quickly becomes obvious.
Steve: Let's say my method takes a (java.util) List of Strings as a parameter, performs some security validation on the list and then performs some privileged action on the list.
001 public class PrivilegedClass {
002
003 public void processStrings(java.util.List<String> strings) {
004 for (String str : strings) {
005 if (!isOk(str)) {
006 throw new SecurityException();
007 }
008 }
009
010 for (String str : strings) {
011 doPrivilegedOperation(str);
012 }
013 }
014
015 private void doPrivilegedOperation(String str) {
016 // privileged stuff
017 // code omitted
018 }
019
020 private boolean isOk(String str) {
021 // security check for string
022 // code omitted
023 return false;
024 }
025
026 }
Bob: The problem is that java.util.List is in interface and can be implemented in a mutable way. Also virtually all the public List implementations included in Java are mutable, so one wouldn't even have to go through the trouble of creating a mutable version - one could just use java.util.ArrayList.
The problem with the mutability is that an ill intentioned caller of the method could pass a list which contains different values while the method does its validation, and then another set of harmful values for the actual processing after the validation has passed. This could be done via timing, or by crafting one's own List implementation for a more exact attack. If the method uses .iterator() to iterate through the list, the first call to .iterator() (used by validation) could be made to return one set of Strings and the 2nd call to .iterator() (used by the post-validation processing) could be made to return another set of Strings.
It's a well known, generic problem.
Let's look at some ways to protect your method and what could go wrong with them. Forgive the silliness of some of these examples, it's just to give the notion of how easy it is to get it wrong.
Steve: I could change the method signature to only accept a more specialized StevesImmutableList.
003 public void processStrings(StevesImmutableList strings) {
Steve: I'd then define StevesImmutableList as a class whose constructor receives a String array and stores it in a private String array field and only has a getter method which returns the array.
001 package version1;
002
003 public class StevesImmutableList {
004
005 private String[] strings;
006
007 public StevesImmutableList(String[] strings) {
008 this.strings = strings;
009 }
010
011 public String[] getStrings() {
012 return this.strings;
013 }
014
015 }
Bob: Arrays are always mutable. The size can't be changed, but the contents (given its size is greater than zero) are free game. And your method is returning a reference to its internal array.
Steve: What if I define my private internal array as final?
Bob: That doesn't help. It'll guarantee that your private field always points to the same array, but the array contents are free game.
Steve: Better have the method call .clone() on the array and return a copy of the array instead of the internal array.
001 package version2;
002
003 public class StevesImmutableList {
004
005 private String[] strings;
006
007 public StevesImmutableList(String[] strings) {
008 this.strings = strings;
009 }
010
011 public String[] getStrings() {
012 return this.strings.clone();
013 }
014
015 }
Bob: Your constructor is receiving an array and storing it as the internal array. A caller with bad intentions could create an array, keep a reference to it, pass it to your object and later on modify it.
Steve: Ok, let's call .clone() on the incoming array as well.
001 package version3;
002
003 public class StevesImmutableList {
004
005 private String[] strings;
006
007 public StevesImmutableList(String[] strings) {
008 this.strings = strings.clone();
009 }
010
011 public String[] getStrings() {
012 return this.strings.clone();
013 }
014
015 }
Steve: Let's also add an overloaded constructor that receives a List to improve the usability of this class.
001 package version4;
002
003 public class StevesImmutableList {
004
005 private String[] strings;
006
007 public StevesImmutableList(java.util.List<String> stringList) {
008 this.strings = stringList.toArray(new String[stringList.size()]);
009 }
010
011 public StevesImmutableList(String[] strings) {
012 this.strings = strings.clone();
013 }
014
015 public String[] getStrings() {
016 return this.strings.clone();
017 }
018
019 }
Bob: Now you're calling toArray() on a List object that you can't really trust. It could return an array and keep a reference to that array for itself for future modification.
Steve: Ok, let's do a manual conversion of the List to an array.
001 package version5;
002
003 public class StevesImmutableList {
004
005 private String[] strings;
006
007 public StevesImmutableList(java.util.List<String> stringList) {
008 this.strings = new String[stringList.size()];
009 for (int i = 0; i < stringList.size(); i++) {
010 this.strings[i] = stringList.get(i);
011 }
012 }
013
014 public StevesImmutableList(String[] strings) {
015 this.strings = strings.clone();
016 }
017
018 public String[] getStrings() {
019 return this.strings.clone();
020 }
021
022 }
Steve: It'd also be nice to be able to serialize this object for passing between JVMs and/or storing object state somewhere. So let's make the class implement Serializable.
001 package version6;
002
003 public final class StevesImmutableList implements java.io.Serializable {
004
005 private String[] strings;
006
007 public StevesImmutableList(java.util.List<String> stringList) {
008 this.strings = new String[stringList.size()];
009 for (int i = 0; i < stringList.size(); i++) {
010 this.strings[i] = stringList.get(i);
011 }
012 }
013
014 public StevesImmutableList(String[] strings) {
015 this.strings = strings.clone();
016 }
017
018 public String[] getStrings() {
019 return this.strings.clone();
020 }
021
022 }
Bob: Serial data can be constructed in such a way that when read, will contain a String array, followed by a StevesImmutableList containing the same String array in the private field, thus making the object mutable.
Steve: Let's make the private field transient and create a readObject method which reads the array from the stream and then clones it before assigning it to the field. Also create a compatible writeObject method.
001 package version7;
002
003 public final class StevesImmutableList implements java.io.Serializable {
004
005 private transient String[] strings;
006
007 public StevesImmutableList(java.util.List<String> stringList) {
008 this.strings = new String[stringList.size()];
009 for (int i = 0; i < stringList.size(); i++) {
010 this.strings[i] = stringList.get(i);
011 }
012 }
013
014 public StevesImmutableList(String[] strings) {
015 this.strings = strings.clone();
016 }
017
018 public String[] getStrings() {
019 return this.strings.clone();
020 }
021
022 private void readObject(java.io.ObjectInputStream s)
023 throws java.io.IOException, ClassNotFoundException {
024 String[] streamStrings = (String[]) s.readObject();
025 this.strings = streamStrings.clone();
026 }
027
028 private void writeObject(java.io.ObjectOutputStream s)
029 throws java.io.IOException {
030 s.writeObject(this.strings);
031 }
032 }
Now some examples from core Java classes
java.lang.reflection.Proxy
Proxy has a method (getProxyClass) which takes a ClassLoader and an array of Class objects, that are supposed to be interfaces, as parameters. It performs some validation on the Class array, and then it dynamically defines and returns a new Class for a dynamic Proxy class which implements all the interfaces of the Class array. If the validation fails, the method throws an Exception (and obviously doesn't return anything).
The getProxyClass uses the user-suplied Class array for the validation and later on for the construction of the Proxy class, so it could be called with an array which has one set of classes for the validation and another set of classes for the Proxy construction.
However, the validation here, as far as I can tell, is strictly for usability. Without the validation, if you gave the method an invalid set of parameters it would sometimes fail with some strange class verification exception. With the validation, the caller gets feedback which is more readily understandable.
java.lang.String
Strings are supposed to be immutable. A lot of things depend on the immutability of Strings. There is no defensive programming in the core classes against mutable Strings (which makes sense, because it'd take a lot of work).
The immutability of Strings hinges on the fact that one cannot access the char array in which the String contents are stored. Now, String does leak the internal array to any registered CharSet who wants it. However, registering a CharSet requires a CharSetProvider and that, in turn, requires the charsetProvider permission.
Unsigned applets don't have that permission and can't create their own registered CharSets. But it is something to keep in mind. If you're granting the charsetProvider permission, you're pretty much implicitly giving away full access.
Monday, July 27, 2009
Java security bugs revisited
A couple of weeks back, I heard that Sun's probably releasing new updates at the end of July, so it might be a good time to update my bug fix table.
Let's see if they've gotten around to look at some of these issues, as well. I'm obviously very biased here and think all vulnerabilities I've found are important and should be very promptly fixed, but the anniversaries of some these bugs are already around the corner.
Let's see if they've gotten around to look at some of these issues, as well. I'm obviously very biased here and think all vulnerabilities I've found are important and should be very promptly fixed, but the anniversaries of some these bugs are already around the corner.
Reported | Status | Fixed | Days Open | |
---|---|---|---|---|
FileSystemView allows read access to file system structure | May 11th, 2008 | Fixed | Dec 2nd, 2008 | 204 |
Read access to System Properties | Aug 18th, 2008 | Not Fixed | N/A | 342* |
Calendar.readObject allows elevation of privileges | Aug 1st, 2008 | Fixed | Dec 2nd, 2008** | 122 |
Undisclosed vectors allow elevation of privileges | Oct 19th, 2008 | Not Fixed | N/A | 280* |
Undisclosed vectors allow directory listing and file renaming/moving | Oct 26th, 2008 | Not Fixed | N/A | 273* |
Generic security architecture problem | Nov 2nd, 2008 | Not Fixed | N/A | 266* |
Undisclosed vectors allow folder creation | Oct 20th 2008 | Not Fixed | N/A | 279* |
Sunday, April 12, 2009
Timeline of Sun Microsystems fixing Java security bugs
Reported | Status | Fixed | Days Open | |
---|---|---|---|---|
FileSystemView allows read access to file system structure | May 11th, 2008 | Fixed | Dec 2nd, 2008 | 204 |
Read access to System Properties | Aug 18th, 2008 | Not Fixed | N/A | 251* |
Calendar.readObject allows elevation of privileges | Aug 1st, 2008 | Fixed | Dec 2nd, 2008** | 122 |
Undisclosed vectors allow elevation of privileges | Oct 19th, 2008 | Not Fixed | N/A | 189* |
Undisclosed vectors allow directory listing and file renaming/moving | Oct 26th, 2008 | Not Fixed | N/A | 182* |
Generic security architecture problem | Nov 2nd, 2008 | Not Fixed | N/A | 175* |
Undisclosed vectors allow folder creation | Oct 20th 2008 | Not Fixed | N/A | 188* |
Subscribe to:
Posts (Atom)