Secure Coding mailing list archives
By default, the Verifier is disabled on .Net and Java
From: Kevin.Wall at qwest.com (Wall, Kevin)
Date: Tue, 2 May 2006 19:43:56 -0500
[Moderator: Feel free to discard some or all of Dinis' original post below. I wasn't sure how much to trim because I don't know how much people have been paying attention to this particular discussion and I didn't want them to loose context and have to resort to searching the archives.] It might be nice if the Java VM would / could distinguish betw running from a LOCAL disk vs a remote networked disk (NFS, Samba share, etc.) and enable tye byte code verify automagically for any classes loaded remotely. That doesn't seem too different (in terms of attack vectors) of running applets locally using remotely loaded classes. A similar thing might also be done if any jars, zip files, .class files, or the directories in which they reside were writable by anyone other than root (or equivalent on Windows, MacOS, etc.) or the user id executing the Java program. Of course that's not too likely to be too portable across the various supported OSes, so perhaps that's why Sun choose not to do it. Perhaps asking / begging Microsoft to do a similar thing for .NET assemblies might be an easier sell because they wouldn't face the OS portability issue (as much). Dinis: I deliberately did not cross-post to the owasp-dotnet list. You can if you wish. -kevin --- Kevin W. Wall Qwest Information Technology, Inc. Kevin.Wall at qwest.com Phone: 614.215.4788 "The reason you have people breaking into your software all over the place is because your software sucks..." -- Former whitehouse cybersecurity advisor, Richard Clarke, at eWeek Security Summit -----Original Message-----
From: sc-l-bounces at securecoding.org
[mailto:sc-l-bounces at securecoding.org] On Behalf Of Dinis Cruz
Sent: Tuesday, May 02, 2006 7:48 PM To: 'Secure Coding Mailing List' Cc: 'owasp-dotnet at lists.sourceforge.net' 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 unverifiable code (This can be seen in the
example
posted on the blog since you needed to use the low level assembler to hack up a program initially compiled in C#). Given that you can't prevent Fully Trusted code from doing unverifiable things at runtime, there's only a marginal difference between encouraging type safety at compile time vs at runtime for the Fully Trusted code developer. I hope that helps to convey the message on where Microsoft stands with this issue. ..." Unfortunately Java is not much better. By default most Java code is
also executed with -noverify.
Here is a good explanation from this
(http://lists.grok.org.uk/pipermail/full-disclosure/2006-March/044505.ht ml) thread (which I started) :
"...I am not a Java expert, but I think that the Java Verifier is NOT used on Apps that are executed with the Security Manager disabled (which I believe
is the default
setting) or are loaded from a local disk (see "... applets loaded
via the file system
are not passed through the byte code verifier" in
http://java.sun.com/sfaq/)
I believe that as of Java 1.2, all Java code except the core libraries must go through the verifier, unless it is specifically disabled (java -noverify).I had the 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.
I tested this by compiling 2 classes where one accesses a public member of the other. Then recompiled the other and changed the method access to private. Tested on: Jdk 1.4.2 Mac OS X Jdk 1.5.0 Mac OS X Jdk 1.5.0 Win XP all behave the same. [~/data/dev/applettest/src]java -cp . FullApp Noone can access me!! [~/data/dev/applettest/src]java -cp . -verify FullApp Exception in thread "main" java.lang.IllegalAccessError: tried to access field MyData.secret from class FullApp at FullApp.main (FullApp.java:23) Using the same code with an Applet loaded from the filesystem throws an IllegalAccessError exception as it should. ..." Any Comments? Best regards Dinis Cruz Owasp .Net Project www.owasp.net
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.
Current thread:
- By default, the Verifier is disabled on .Net and Java, (continued)
- 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 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 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)
- By default, the Verifier is disabled on .Net and Java David Eisner (May 03)
- By default, the Verifier is disabled on .Net and Java Dinis Cruz (May 03)
- By default, the Verifier is disabled on .Net and Java Tim Hollebeek (May 04)
- 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 03)
- By default, the Verifier is disabled on .Net and Java Dinis Cruz (May 03)
- By default, the Verifier is disabled on .Net and Java David Eisner (May 04)
- By default, the Verifier is disabled on .Net and Java Stephen de Vries (May 04)