Secure Coding mailing list archives
By default, the Verifier is disabled on .Net and Java
From: michaelslists at gmail.com (Michael Silk)
Date: Sat, 13 May 2006 21:35:58 +1000
Stephen, I think the reason you get the IllegalAccessError is because the VM thinks you are loading from a remote url. I don't think the user of a classloader per-se forces the verification of the class. (I wrote a class loader like yours that just loads a file with no package in the current dir and was able to access the private method). You can also note that your class isn't verified if -noverify is passed (perhaps this is obvious :) -- Michael On 5/13/06, Stephen de Vries <stephen at corsaire.com> wrote:
On 12 May 2006, at 09:10, Charles Miller wrote:It's not reflection: you're confusing IllegalAccessException and IllegalAccessError. For any non-Java nerd still listening in: there are two fundamental types of "Throwable" exception-conditions in Java: Exceptions and Errors[1]. Exceptions represent application-level conditions -- things an application is likely to be able to recover from, like network timeouts, trying to read beyond the end of a file, and so on. Errors, on the other hand, represent VM-level problems that an application can't really do anything about, like running out of memory, not finding a required native library, or encountering corrupted class files. IllegalAccessException happens when reflective code attempts to access some field or method it's not supposed to. Because it's a result of reflection, it's considered an application-level problem and it's assumed your code can recover gracefully. Amusingly enough, you can get around most IllegalAccessExceptions in java just by calling {field|method}.setAccessible(true). So long as there's no explicit SecurityManager installed, as soon as you've done that you're free to modify the field or call method to your heart's content[2]. IllegalAccess_Error_, on the other hand, happens when some non- reflective code issues a bytecode instruction that attempts to access a field or method it shouldn't be able to see. If you look at its class hierarchy, the meaning of the class is pretty clear: IllegalAccessError is a subclass of IncompatibleClassChangeError, which is a subclass of LinkageError. Because this is a problem at the bytecode/classloading level, and literally something that could happen on _any_ method-call or field-access, it's flagged as an error. The Error generally occurs when class A has been compiled against a version of class B where a method is public, but that method is private in the version of the same class it encounters at runtime. This sort of thing happens quite often in Java, you're frequently stuck in "jar file hell", in a twisty turny maze of library interdependencies, all with slightly different version numbers. More about the circumstances of IllegalAccessError here: http://java.sun.com/docs/books/vmspec/2nd-edition/html/ ConstantPool.doc.html Dynamic classloading isn't really at fault here. There are all sorts of pits you can fall into when you start rolling your own classloader (the Java webapp I develop supports dynamic runtime- deployable plugins, and the classloading issues are a HUGE headache), but IllegalAccessError isn't one of them. Charles [1] Exceptions are further divided into checked exceptions and runtime exceptions, but that's beyond the scope of this email [2] See also: http://www.javaspecialists.co.za/archive/ Issue014.htmlThanks for clearing this up Charles. I've created another example that uses a class loader to load the classes, and this time, it throws an IllegalAccessError just like Tomcat does: Loading class: /Users/stephen/data/dev/classloader/myclass/ somepackage/MyTest.class Loading class: /Users/stephen/data/dev/classloader/myclass/java/lang/ Runnable.class Loading class: /Users/stephen/data/dev/classloader/myclass/java/lang/ Object.class Loading class: /Users/stephen/data/dev/classloader/myclass/ somepackage/MyData.class Loading class: /Users/stephen/data/dev/classloader/myclass/java/lang/ System.class Exception in thread "main" java.lang.IllegalAccessError: tried to access method somepackage.MyData.getName()Ljava/lang/String; from class somepackage.MyTest at somepackage.MyTest.run(MyTest.java:15) at classloader.Main.main(Main.java:26) Java Result: 1 This error is thrown irrespective of the -verify flag. So it looks like using a classloader causes the VM to perform verification, whether or not the "verifier" was enabled. Michael Silk made a similar statement earlier in this thread. Would you agree? PoC code below: package classloader; public class Main { public Main() { } public static void main(String[] args) { //Illegal Access Error try { CustomLoader cl = new CustomLoader(System.getProperty ("user.dir")+"/myclass/"); Class myClass = cl.loadClass("somepackage.MyTest"); Runnable r = (Runnable)myClass.newInstance(); r.run(); } catch (Exception e) { e.printStackTrace(); } } } package classloader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; public class CustomLoader extends ClassLoader { private String path = null; public CustomLoader(String path) { this.path = path; } private byte[] getBytes( String filename ) throws IOException { File file = new File( filename ); long len = file.length(); byte raw[] = new byte[(int)len]; FileInputStream fin = new FileInputStream( file ); int r = fin.read( raw ); if (r != len) throw new IOException( "Can't read all, "+r+" != "+len ); fin.close(); return raw; } public Class loadClass( String name, boolean resolve ) throws ClassNotFoundException { Class clas = null; String fileStub = name.replace( '.', '/' ); String classFilename = path+fileStub+".class"; System.out.println("Loading class: "+classFilename); File classFile = new File( classFilename ); try { byte raw[] = getBytes( classFilename ); clas = defineClass( name, raw, 0, raw.length ); } catch( IOException ie ) { } if (clas==null) { clas = findSystemClass( name ); } if (resolve && clas != null) resolveClass( clas ); if (clas == null) throw new ClassNotFoundException( name ); return clas; } } In current directory create a folder ./myclass/somepackage with the following two files: package somepackage; public class MyData { private String name; public MyData() { name = "No one can read me"; } public String getName() { System.out.println("private method called"); return (name); } } package somepackage; public class MyTest implements Runnable { MyData m; public MyTest() { m = new MyData(); } public void run() { System.out.println(m.getName()); } } Compile both these classes, then change the MyData.getName method to private access, and recompile MyData. Stephen _______________________________________________ Secure Coding mailing list (SC-L) SC-L at securecoding.org List information, subscriptions, etc - http://krvw.com/mailman/listinfo/sc-l List charter available at - http://www.securecoding.org/list/charter.php
Current thread:
- By default, the Verifier is disabled on .Net and Java Dinis Cruz (May 02)
- By default, the Verifier is disabled on .Net and Java Jeff Williams (May 02)
- By default, the Verifier is disabled on .Net and Java Dinis Cruz (May 04)
- [Owasp-dotnet] Re: By default, the Verifier is disabled on .Net and Java Michael Silk (May 04)
- By default, the Verifier is disabled on .Net and Java Jeff Williams (May 04)
- Message not available
- Message not available
- Message not available
- By default, the Verifier is disabled on .Net and Java Stephen de Vries (May 12)
- By default, the Verifier is disabled on .Net and Java Michael Silk (May 13)
- By default, the Verifier is disabled on .Net and Java Dinis Cruz (May 04)
- By default, the Verifier is disabled on .Net and Java Jeff Williams (May 02)
- By default, the Verifier is disabled on .Net and Java Michael Silk (May 08)
- By default, the Verifier is disabled on .Net and Java Dinis Cruz (May 12)
- By default, the Verifier is disabled on .Net and Java Michael Silk (May 12)
- By default, the Verifier is disabled on .Net and Java Dinis Cruz (May 08)
- By default, the Verifier is disabled on .Net and Java Michael Silk (May 08)
- By default, the Verifier is disabled on .Net and Java Stephen de Vries (May 10)
- By default, the Verifier is disabled on .Net and Java Dinis Cruz (May 12)
- By default, the Verifier is disabled on .Net and Java Stephen de Vries (May 13)