RE: [SC-L] By default, the Verifier is disabled on .Net and Java
Two important clarifications for Java (based on my experiments): 1) The verifier IS enabled for the classes that come with the Java platform, such as those in rt.jar. So, for example, if you create a class that tries to set System.security (the private variable that points to the SecurityManager instance), you get a verification exception. (If this was possible, it would allow a complete bypass of the Java sandbox). 2) The verifier also seems to be enabled for classes running inside Tomcat. Im not sure about other J2EE containers. So I dont think its fair to say that most Java code is running without verification. But Denis is right. There is a real problem with verification, as demonstrated in the message below. This is a clear violation of the Java VM Spec, yet my messages to the team at Sun developing the new verifier have been ignored. And its a real issue, given the number of applications that rely on libraries they didnt compile. I dont think a real explanation of how the Sun verifier actually works is too much to ask, given the risk. --Jeff From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Dinis Cruz Sent: Tuesday, May 02, 2006 7:48 PM To: 'Secure Coding Mailing List' Cc: '[EMAIL PROTECTED]' Subject: [SC-L] By default, the Verifier is disabled on .Net and Java Here is a more detailed explanation of why (in my previous post) I said: 99% of .Net and Java code that is currently deployed is executed on an environment where the VM verifier is disabled, . -- In .Net the verifier (the CLR function that checks for type safety) is only enabled on partial trust .Net environments. For example, in Full Trust .Net you can successfully assign Type A to Type B (also called a Type Confusion attack) which clearly breaks type safety. I have done some research on this topic, and on my spare time I was able to find several examples of these situations: Possible Type Confusion issue in .Net 1.1 (only works in FullTrust) (http://owasp.net/blogs/dinis_cruz/archive/2005/11/08/36.aspx) Another Full Trust CLR Verification issue: Exploiting Passing Reference Types by Reference (http://owasp.net/blogs/dinis_cruz/archive/2005/12/28/393.aspx) Another Full Trust CLR Verification issue: Changing Private Field using Proxy Struct (http://owasp.net/blogs/dinis_cruz/archive/2005/12/28/394.aspx) Another Full Trust CLR Verification issue: changing the Method Parameters order (http://owasp.net/blogs/dinis_cruz/archive/2005/12/26/390.aspx) C# readonly modifier is not enforced by the CLR (when in Full Trust (http://owasp.net/blogs/dinis_cruz/archive/2005/12/26/390.aspx) Also related: JIT prevents short overflow (and PeVerify doesn't catch it) (http://owasp.net/blogs/dinis_cruz/archive/2006/01/10/422.aspx) and ANSI/UNICODE bug in System.Net.HttpListenerRequest (http://www.owasp.net//blogs/dinis_cruz/archive/2005/12/17/349.aspx) Here is Microsoft's 'on the record' comment about this lack of verification (and enforcement of type safety) on Full Trust code (note: I received these comments via the MSRC): ... Some people have argued that Microsoft should always enforce type safety at runtime (i.e. run the verifier) even if code is Fully Trusted. We've chosen not to do this for a number of reasons (e.g. historical, perf, etc). There are at least two important things to consider about this scenario: 1) Even if we tried to enforce type safety using the verifier for Fully Trusted code, it wouldn't prevent Fully Trusted from accomplishing the same thing in 100 other different ways. In other words, your example accessed an object as if it were a different incompatible type - The verifier could have caught this particular technique that allowed him to violate type safety. However, he could have accomplished the same result using private reflection, direct memory access with unsafe code, or indirectly doing stuff like using PInvoke/native code to disable verification by modifying the CLR's verification code either on disk or in memory. There would be a marginal benefit to insuring people wrote cleaner more type safe code by enforcing verification at runtime for Full Trust, but you wouldn't get any additional security benefits because you can perform unverifiable actions in dozens of ways the verifier won't prevent if you are Fully Trusted. 2) As mentioned at the end of #1 above, one argument is that it's good for programmers (even fully trusted ones) to follow type safety rules, and doing runtime verification would keep people writing cleaner code. However, we don't need to do the verification at runtime in order to encourage good type safety hygiene. Instead, we can rely on our languages to do this for us. For example, C# and VB by default ensure that you produce verifiable code. If you've written your code in a language like C#, you're not going to run into cases where you've accidentally created
Re: [SC-L] By default, the Verifier is disabled on .Net and Java
Wall, Kevin wrote: same intuition about the verifier, but have just tested this and it is not the case. It seems that the -noverify is the default setting! If you want to verify classes loaded from the local filesystem, then you need to explicitly add -verify to the cmd line. Is this (still) true? The -verify and -noverify flag are no longer documented [1], although they are still accepted. I did a little experiment (with my default 1.5 VM). I compiled a HelloWorld program, then changed a few byes in the class file with a hex editor. -8-- $ java -cp . HelloWorld Exception in thread main java.lang.ClassFormatError: Interface name has bad constant pool index 13056 in class file HelloWorld at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:620) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124) at java.net.URLClassLoader.defineClass(URLClassLoader.java:260) at java.net.URLClassLoader.access$100(URLClassLoader.java:56) at java.net.URLClassLoader$1.run(URLClassLoader.java:195) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:188) at java.lang.ClassLoader.loadClass(ClassLoader.java:306) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:268) at java.lang.ClassLoader.loadClass(ClassLoader.java:251) at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319) $ java -cp . -verify HelloWorld Exception in thread main java.lang.ClassFormatError: Interface name has bad constant pool index 13056 in class file HelloWorld at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:620) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124) at java.net.URLClassLoader.defineClass(URLClassLoader.java:260) at java.net.URLClassLoader.access$100(URLClassLoader.java:56) at java.net.URLClassLoader$1.run(URLClassLoader.java:195) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:188) at java.lang.ClassLoader.loadClass(ClassLoader.java:306) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:268) at java.lang.ClassLoader.loadClass(ClassLoader.java:251) at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319) $ java -cp . -noverify HelloWorld # # An unexpected error has been detected by HotSpot Virtual Machine: # # EXCEPTION_ACCESS_VIOLATION (0xc005) at pc=0x6d7415fb, pid=3512, tid=2260 # # Java VM: Java HotSpot(TM) Client VM (1.5.0_06-b05 mixed mode) # Problematic frame: # V [jvm.dll+0x615fb] # # An error report file with more information is saved as hs_err_pid3512.log # # If you would like to submit a bug report, please visit: # http://java.sun.com/webapps/bugreport/crash.jsp # -8-- -David [1] http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/java.html ___ Secure Coding mailing list (SC-L) SC-L@securecoding.org List information, subscriptions, etc - http://krvw.com/mailman/listinfo/sc-l List charter available at - http://www.securecoding.org/list/charter.php
RE: [SC-L] By default, the Verifier is disabled on .Net and Java
David Eisner wrote... Wall, Kevin wrote: The correct attribution for bring this up (and the one whom you are quoting) is Dinis Cruz. same intuition about the verifier, but have just tested this and it is not the case. It seems that the -noverify is the default setting! If you want to verify classes loaded from the local filesystem, then you need to explicitly add -verify to the cmd line. Is this (still) true? The -verify and -noverify flag are no longer documented [1], although they are still accepted. I did a little experiment (with my default 1.5 VM). I compiled a HelloWorld program, then changed a few byes in the class file with a hex editor. Perhaps no longer true (at least one could hope), but I can't take credit for the part you quoted above. That was Dinis. Also, from the results of your test, it seems to indicate that SOME TYPE of verification is taking place, but if all you did was change a few ARBITRARY bytes in the .class file, I don't think that proves the byte code verifier is being being run in it's entirety. IIRC, the discussion was around the issue of 'type safety'. It's hard to see how a HelloWorld program would show that. It's entirely possibly that the (new 1.5) default just does some surface level of byte code verification (e.g., verify that everything is legal op codes / byte code) before HotSpot starts crunching on it and that this works differently if either the '-verify' or '-noverify' flags are used. E.g., suppose that '-verify' flag, does some deeper-level analysis, such as checks to ensure type safety, etc, whereas the '-noverify' doesn't even validate the byte codes are legal op codes or that the .class file has a legal format. This might even make sense because checking for valid file format and valid Java op codes ought to be fairly cheap checks compared to the deeper analysis required for things like type safety. You didn't discuss details of what bits you tweaked, so I'm not quite yet ready to jump up and down for joy and conclude that Sun has now seen the light and has made the 1.5 JVM default to run the byte code through the *complete* byte code verifier. I think more tests are either necessary or someone at Sun who can speak in some official capacity steps up and gives a definitive word one way or another on this. -kevin --- Kevin W. Wall Qwest Information Technology, Inc. [EMAIL PROTECTED] Phone: 614.215.4788 Linux *is* user-friendly. It's just choosy about its friends. - Robert Slade, http://sun.soci.niu.edu/~rslade/bkl3h4h4.rvw This communication is the property of Qwest and may contain confidential or privileged information. Unauthorized use of this communication is strictly prohibited and may be unlawful. If you have received this communication in error, please immediately notify the sender by reply e-mail and destroy all copies of the communication and any attachments. ___ Secure Coding mailing list (SC-L) SC-L@securecoding.org List information, subscriptions, etc - http://krvw.com/mailman/listinfo/sc-l List charter available at - http://www.securecoding.org/list/charter.php
Re: [SC-L] By default, the Verifier is disabled on .Net and Java
Ok, I just did some further tests and I think I can say that Java (version 1.5.0_06) has similar verification issues to the ones I discovered on the .Net Framework (see links in my previous post). Here is a full description of my test (which is a variation of the one done by Stephen de Vries in the original discussion about type safety). - Objective: Call a private method directly that belongs to a different class (something that should not be possible to do) Test environment: Mac OS X10.4.6 java -version java version 1.5.0_06 Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_06-112) Java HotSpot(TM) Client VM (build 1.5.0_06-64, mixed mode, sharing) Step by Step description of test: Start by creation the File: publicPrivate.java ** class publicPrivate { public static void main(String[] args) { System.out.println(Hello World!); //Display the string. externalClass.publicMethod(); externalClass.publicMethod(); } } class externalClass { public static void publicMethod() { System.out.println(Inside the Public Method); } private static void privateMethod() { System.out.println(Inside the Private Method); } } ** Compile this using javac publicPrivate.java and you get two class files: publicPrivate.class and externalClass.class execute java publicPrivate and you will get Hello World! Inside the Public Method Inside the Public Method Note that if I change on the publicPrivate.java file the lines externalClass.publicMethod(); externalClass.publicMethod(); to externalClass.publicMethod(); externalClass.privateMethod(); I will get the following compilation error: publicPrivate.java:7: privateMethod() has private access in externalClass externalClass.privateMethod(); ^ 1 error This makes sense since this is the compiler detecting that we are trying to access a private member directly (note: this is also what happens in .Net's C# compiler). It also means that (like in my .Net examples) I will have to manipulate directly the bytecode of the class that I want to change Using jEdit Oolong plug-in I disassembled the publicPrivate.class file, creating the file: publicPrivate.j (this is a slightly edited version of the Oolong disassemble result since the original version didn't compile) ** .class public publicPrivate .super java/lang/Object .method public init()V .limit stack 1 .limit locals 1 aload_0 invokespecial java/lang/Object/init()V return .end method .method public static main([Ljava/lang/String;)V .limit stack 2 getstatic java/lang/System/out Ljava/io/PrintStream; ldc Hello World! - After Oolong disassemble invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V invokestatic externalClass/publicMethod()V invokestatic externalClass/publicMethod()V return .end method ** note the change: from: ldc Hello World! to: ldc Hello World! - After Oolong disassemble I also had some problems with getting the jEdit Oolong plug-in to assemble the publicPrivate.j file, so I used jasmin instead: java -jar jasmin-2.2/jasmin.jar PublicPrivate.j Generated: publicPrivate.class Executing java publicPrivate shows: Hello World!- After Oolong disassemble Inside the Public Method Inside the Public Method Now, in jEdit, on the publicPrivate.j file, I make the following change from: invokestatic externalClass/publicMethod()V invokestatic externalClass/publicMethod()V to: invokestatic externalClass/publicMethod()V invokestatic externalClass/privateMethod()V Then save it and run jasmin again java -jar jasmin-2.2/jasmin.jar PublicPrivate.j Generated: publicPrivate.class execute java publicPrivate and: Hello World!- After Oolong disassemble Inside the Public Method Inside the Private Method Bingo! We successfully invoked the private method. Now, just to confirm that this is against verification (and that the verifier is disabled by default) java -noverify publicPrivate (produces the same result) Hello World!- After Oolong disassemble Inside the Public Method Inside the Private Method java -verify publicPrivate (throws an verification error) Hello World!- After Oolong disassemble Inside the Public Method Exception in thread main java.lang.IllegalAccessError: tried to access method externalClass.privateMethod()V from class publicPrivate at publicPrivate.main(PublicPrivate.j) This should prove that the verifier is not enabled by default on java files loaded from the local computer. What is interesting about this example is that we are not even doing a Type Confusion attack and trying to break type
Re: [SC-L] By default, the Verifier is disabled on .Net and Java
Verifier in 1.5 is definately OFF by default: to confirm this do the following: 1. Create this class: == public class Foo { public static int k = 23; static { System.out.println(initially k: + k); } public static void m(){ System.out.println(m() k: + k); } } == 2. Compile it. 3. Create this class == public class Test { public static void main(String[] args){ Foo.k = 34; Foo.m(); } } == 4. Compile it. 5. Run it like so: 5a. java Test 5b. java -verify Test 6. Change Foo.java like so: == public class Foo { private static int k = 23; static { System.out.println(initially k: + k); } public static void m(){ System.out.println(m() k: + k); } } == (note k is now private). 7. recompile Foo.java (DO NOT recompile Test.java) 8. run Test.java like so: 8a. java Test 8b. java -verify Test Note the differences ... Tested with === java version 1.5.0_06 Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_06-b05) Java HotSpot(TM) Client VM (build 1.5.0_06-b05, mixed mode) === -- Michael On 5/4/06, Wall, Kevin [EMAIL PROTECTED] wrote: David Eisner wrote... Wall, Kevin wrote: The correct attribution for bring this up (and the one whom you are quoting) is Dinis Cruz. same intuition about the verifier, but have just tested this and it is not the case. It seems that the -noverify is the default setting! If you want to verify classes loaded from the local filesystem, then you need to explicitly add -verify to the cmd line. Is this (still) true? The -verify and -noverify flag are no longer documented [1], although they are still accepted. I did a little experiment (with my default 1.5 VM). I compiled a HelloWorld program, then changed a few byes in the class file with a hex editor. Perhaps no longer true (at least one could hope), but I can't take credit for the part you quoted above. That was Dinis. Also, from the results of your test, it seems to indicate that SOME TYPE of verification is taking place, but if all you did was change a few ARBITRARY bytes in the .class file, I don't think that proves the byte code verifier is being being run in it's entirety. IIRC, the discussion was around the issue of 'type safety'. It's hard to see how a HelloWorld program would show that. It's entirely possibly that the (new 1.5) default just does some surface level of byte code verification (e.g., verify that everything is legal op codes / byte code) before HotSpot starts crunching on it and that this works differently if either the '-verify' or '-noverify' flags are used. E.g., suppose that '-verify' flag, does some deeper-level analysis, such as checks to ensure type safety, etc, whereas the '-noverify' doesn't even validate the byte codes are legal op codes or that the .class file has a legal format. This might even make sense because checking for valid file format and valid Java op codes ought to be fairly cheap checks compared to the deeper analysis required for things like type safety. You didn't discuss details of what bits you tweaked, so I'm not quite yet ready to jump up and down for joy and conclude that Sun has now seen the light and has made the 1.5 JVM default to run the byte code through the *complete* byte code verifier. I think more tests are either necessary or someone at Sun who can speak in some official capacity steps up and gives a definitive word one way or another on this. -kevin --- Kevin W. Wall Qwest Information Technology, Inc. [EMAIL PROTECTED]Phone: 614.215.4788 Linux *is* user-friendly. It's just choosy about its friends. - Robert Slade, http://sun.soci.niu.edu/~rslade/bkl3h4h4.rvw This communication is the property of Qwest and may contain confidential or privileged information. Unauthorized use of this communication is strictly prohibited and may be unlawful. If you have received this communication in error, please immediately notify the sender by reply e-mail and destroy all copies of the communication and any attachments. ___ Secure Coding mailing list (SC-L) SC-L@securecoding.org List information, subscriptions, etc - http://krvw.com/mailman/listinfo/sc-l List charter available at - http://www.securecoding.org/list/charter.php ___ Secure Coding mailing list (SC-L) SC-L@securecoding.org List information, subscriptions, etc - http://krvw.com/mailman/listinfo/sc-l List charter available at - http://www.securecoding.org/list/charter.php