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: