WebApp Sec mailing list archives
Re: [SC-L] By default, the Verifier is disabled on .Net and Java
From: "Michael Silk" <michaelslists () gmail com>
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 () 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.html Thanks 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 () securecoding org List information, subscriptions, etc - http://krvw.com/mailman/listinfo/sc-l List charter available at - http://www.securecoding.org/list/charter.php
------------------------------------------------------------------------- Sponsored by: Watchfire Methodologies & Tools for Web Application Security Assessment With the rapid rise in the number and types of security threats, web application security assessments should be considered a crucial phase in the development of any web application. What methodology should be followed? What tools can accelerate the assessment process? Download this whitepaper today! https://www.watchfire.com/securearea/whitepapers.aspx?id=701300000007t9h --------------------------------------------------------------------------
Current thread:
- Re: [SC-L] By default, the Verifier is disabled on .Net and Java Stephen de Vries (May 11)
- Re: [SC-L] By default, the Verifier is disabled on .Net and Java Stephen de Vries (May 11)
- Re: [SC-L] By default, the Verifier is disabled on .Net and Java Steve Brown (May 11)
- Re: [SC-L] By default, the Verifier is disabled on .Net and Java Michael Silk (May 11)
- Re: [SC-L] By default, the Verifier is disabled on .Net and Java Charles Miller (May 11)
- Re: [SC-L] By default, the Verifier is disabled on .Net and Java Stephen de Vries (May 13)
- Re: [SC-L] By default, the Verifier is disabled on .Net and Java Michael Silk (May 13)
- Re: [SC-L] By default, the Verifier is disabled on .Net and Java Charles Miller (May 14)
- Re: [SC-L] By default, the Verifier is disabled on .Net and Java Steve Brown (May 11)
- Re: [SC-L] By default, the Verifier is disabled on .Net and Java Stephen de Vries (May 11)
- RE: [SC-L] By default, the Verifier is disabled on .Net and Java Jeff Williams (May 11)
- Re: [SC-L] By default, the Verifier is disabled on .Net and Java Michael Silk (May 11)
- <Possible follow-ups>
- Re: [SC-L] By default, the Verifier is disabled on .Net and Java Michael Silk (May 14)
- Re: [SC-L] By default, the Verifier is disabled on .Net and Java leichter_jerrold (May 15)