Disable Java reflection for the current thread
Asked Answered
F

3

21

I need to call some semi-trustworthy Java code and want to disable the ability to use reflection for the duration of that code's execution.

try{
   // disable reflection somehow
   someObject.method();
}
finally{
   // enable reflection again
}

Can this be done with a SecurityManager, and if so, how?

Clarification/Context: This is a follow-up to another question about restricting the packages that can be called from JavaScript/Rhino. The accepted answer references a blog entry on how to do that, and it requires two steps, the first one using a Rhino API (ClassShutter), the second one turning off reflection and Class.forName(). I was thinking I can do that second step more cleanly using a SecurityManager (learning about SecurityManager, which as has been pointed out, is a complex beast, along the way).

To sum up, I want (from code, not setting file) to turn off Class.forName() and any access to the whole reflection package.

Failure answered 21/4, 2009 at 0:42 Comment(1)
im not sure about how SecurityManager works, but check out this question: https://mcmap.net/q/375890/-how-to-disable-java-security-managerCrotch
T
20

It depends on what you are trying to restrict.

In general, publicly accessible API is not restricted. However, as long as you don't grant the untrustworthy code the ReflectPermission("suppressAccessChecks") permission, it won't be able to get access to non-public API in another package.

If you have a list of packages to which you want to restrict all access, there are two steps. First, in the Security properties, include the restricted package in the package.access list. Then give your trusted code RuntimePermission("accessClassInPackage." + pkg).

A common way to distinguish your untrusted code is to load it from a different location, and refer to the different codebases in your policy file when granting permissions.

The Java security architecture is very powerful, but I know it is also complicated; if you would like a more concrete example, please describe exactly what calls you want to restrict and I'll try to be more explicit.


To do what you want without modifying the java.policy file and/or the java.security file would be very difficult, maybe impossible. The java.security.Policy represents the information in java.policy, but it doesn't offer write access. You could create your own Policy implementation and install it at runtime as long as any existing SecurityManager permits it.

On the other hand, you can specify a custom java.policy file as a command-line option. If you are providing a complete application with some sort of launcher, that might be easily accomplished. It also provides some transparency to your users. A sophisticated user can review the permissions you'd like to have granted to the application.

Tnt answered 21/4, 2009 at 1:1 Comment(1)
I added some context to the question.Failure
S
5

Well, you can override SecurityManager.checkMemberAccess and give a stricter definition. However, it doesn't really work like that. What happens for instance if the code defines a finaliser?

On the clarification: Other APIs use reflection and other APIs. For instance, java.beans, LiveConnect and Rhino. An adversary could from within a script, say, create a new Rhino context without the shutter and thereby bootstrap into the full JRE. With an open system, a blacklist can never be finished.

In summary: to use the Java security model you need to work with it, not against it.

Sixpenny answered 21/4, 2009 at 1:3 Comment(4)
This is a gem of an answer! What happens for instance if the code defines a finaliser? is such a good question when you look at the classloader from an attacker's perspective if execution of "dynamic semi-trusted sources" turned out to be a bad idea. A better idea would be to either get trusted sources (hopefully open sourced), or run the entire java program in it's own JVM instance with programmatic control of that JVM with kernel level APIs (like network, file system APIs, etc).Hiatt
@AkshayaShanbhogue Minimising trust with fine grains is absolutely what you want for security. Unfortunately Java supports global state, an idea known to be bad since at least the early 1960s, which is the root cause of most of Java's security problems. There wouldn't be a SecurityManager if it wasn't for globals.Sixpenny
@tom-hawtin-tackline Looks like you've thought about these issues deeply. Can you think of a legitimate situation where reflection is ever needed? Also, do you think having finer grain control and removing global state could have runtime performance implications?Hiatt
@AkshayaShanbhogue Comments are two small to answer usefully. The vast majority of reflection usage is hacking. Reflection is absolutely needed (once) when dynamically loading code. / Not having global state would be great for performance. Static initalisers? Gone, and therefore it much easier to optimise code loading. Also globals tend to lead to bottlenecks.Sixpenny
O
2

I wrote a replacement of ClassShutter that allows fine grained access control, per instance, per method, per field:

http://riven8192.blogspot.com/2010/07/java-rhino-fine-grained-classshutter.html

Ovule answered 27/7, 2010 at 17:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.