DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workkloads.

Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Java Virtual Threads and Scaling
  • Java’s Next Act: Native Speed for a Cloud-Native World
  • The Energy Efficiency of JVMs and the Role of GraalVM
  • Buildpacks: An Open-Source Alternative to Chainguard

Trending

  • My LLM Journey as a Software Engineer Exploring a New Domain
  • Kubeflow: Driving Scalable and Intelligent Machine Learning Systems
  • *You* Can Shape Trend Reports: Join DZone's Software Supply Chain Security Research
  • Automatic Code Transformation With OpenRewrite
  1. DZone
  2. Coding
  3. Java
  4. The Java Security Manager: Why and How?

The Java Security Manager: Why and How?

You've got questions, we've got answers: Learn more about Java security manager, including how code compiles, if it runs, and what it displays. Then we'll probe the why and how.

By 
Nicolas Fränkel user avatar
Nicolas Fränkel
DZone Core CORE ·
Jan. 20, 16 · Analysis
Likes (11)
Comment
Save
Tweet
Share
26.2K Views

Join the DZone community and get the full member experience.

Join For Free

Generally, security concerns are boring for developers. I hope this article is entertaining enough for you to read it until the end since it tackles a very serious issue on the JVM.

Quiz

Last year, at Joker conference, my colleague Volker Simonis showed a snippet that looked like the following:

public class StrangeReflectionExample {

    public Character aCharacter;

    public static void main(String... args) throws Exception {
        StrangeReflectionExample instance = new StrangeReflectionExample();
        Field field = StrangeReflectionExample.class.getField("aCharacter");
        Field type = Field.class.getDeclaredField("type");
        type.setAccessible(true);
        type.set(field, String.class);
        field.set(instance, 'A');
        System.out.println(instance.aCharacter);
    }
}

Now a couple of questions:

  1. Does this code compile?
  2. If yes, does it run?
  3. If yes, what does it display?

Answers below (dots to let you think before checking them).
.
..
…
….
…..
……
…….
……..
………
……….
………..
…………
………….
…………..
……………
…………….
……………..
This code compiles just fine. In fact, it uses the so-called reflection API (located in the java.lang.reflect package) which is fully part of the JDK.

Executing this code leads to the following exception:

Exception in thread "main" java.lang.IllegalArgumentException: Can not set java.lang.String field ch.frankel.blog.securitymanager.StrangeReflectionExample.aCharacter to java.lang.Character
  at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
  at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
  at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:81)
  at java.lang.reflect.Field.set(Field.java:764)
  at ch.frankel.blog.securitymanager.StrangeReflectionExample.main(StrangeReflectionExample.java:15)
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at java.lang.reflect.Method.invoke(Method.java:497)
  at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

So, despite the fact that we defined the type of the aCharacter attribute as a Character at development time, the reflection API is able to change its type to String at runtime! Hence, trying to set it to 'A' fails.

Avoiding Nasty Surprises with the Security Manager

Reflection is not the only risky operation one might want to keep in check on the JVM. Reading a file or writing one also belong to the set of potentially dangerous operations. Fortunately, the JVM has a system to restrict those operations. Unfortunately, it’s not set by default.

In order to activate the SecurityManager, just launch the JVM with the java.security.manager system property i.e. java -Djava.security.manager. At this point, the JVM will use the default JRE policy. It’s configured in the file located at%JAVA_HOME%/lib/security/java.policy (for Java 8). Here’s a sample of this file:

grant codeBase "file:${{java.ext.dirs}}/*" {
        permission java.security.AllPermission;
};

grant {
        permission java.lang.RuntimePermission "stopThread";
        permission java.net.SocketPermission "localhost:0", "listen";
        permission java.util.PropertyPermission "java.version", "read";
        permission java.util.PropertyPermission "java.vendor", "read";
        ...
}

The first section – grant codeBase, is about which code can be executed; the second – grant, is about specific permissions.

Regarding the initial problem regarding reflection mentioned above, the second part is the most relevant. One can read the source of the AccessibleObject.setAccessible() method:

SecurityManager sm = System.getSecurityManager();
if (sm != null) sm.checkPermission(ACCESS_PERMISSION);
setAccessible0(this, flag);

Every sensitive method to a Java API has the same check through the Security Manager. You can verify that for yourself in the following code:

  • Thread.stop()
  • Socket.bind()
  • System.getProperty()
  • etc.

Using an Alternate java.policy File

Using the JRE’s policy file is not convenient when one uses the same JRE for different applications. Given the current micro-service trend, this might not be the case. However, with automated provisioning, it might be more convenient to always provision the same JRE over and over and let each application provides its own specific policy file.

To add another policy file in addition to the default JRE’s, thus adding more permissions, launch the JVM with:
java -Djava.security.manager -Djava.security.policy=/path/to/other.policy

To replace the default policy file with your own, launch the JVM with:
java -Djava.security.manager -Djava.security.policy==/path/to/other.policy
Note the double equal sign.

Configuring Your Own Policy File

Security configuration can be either based on a:

Black list
In a black list scenario, everything is allowed but exceptions can be configured to disallow some operations.
White list
On the opposite, in a white list scenario, only operations that are explicitly configured are allowed. By default, all operations are disallowed.

If you want to create your own policy file, it’s suggested you start with a blank one and then launch your app. As soon, as you get a security exception, add the necessary permission is the policy. Repeat until you have all necessary permissions. Following this process will let you have only the minimal set of permissions to run the application, thus implementing the least privilege security principle.

Note that if you’re using a container or a server, you’ll probably require a lot of those permissions, but this is the price to pay to secure your JVM against abuses.

Conclusion

I never checked policy files in production, but since I never had any complain, I assume the JVM’s policy was never secured. This is a very serious problem! I hope this article will raise awareness regarding that lack of hardening – especially since with the latest JVM, you can create and compile Java code on the fly, leading to even more threats.

To go further:

  • Default Policy Implementation and Policy File Syntax
  • SecurityManager Javadoc
Java (programming language) security Java virtual machine

Opinions expressed by DZone contributors are their own.

Related

  • Java Virtual Threads and Scaling
  • Java’s Next Act: Native Speed for a Cloud-Native World
  • The Energy Efficiency of JVMs and the Role of GraalVM
  • Buildpacks: An Open-Source Alternative to Chainguard

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!