Supplemental Material: doPrivileged()

Privileged access was added to the Security objective for Oracle’s Java 11 1Z0-819 Exam, but was not part of the objectives for the now retired 1Z0-816 Exam. We created this Supplemental Material and are releasing it free of charge for all those readers who purchased one of our Java 11 Study Guides. You should read this section carefully before taking the 1Z0-819 Exam. See other changes on The 1Z0-819 Exam page.

Overview

Some Java programs run in an environment where the user does not have full control over the program. In other words, the program runs a privileged action on behalf of the user. The idea for the developer is straight-forward:

  • I have a privileged action I need run for a user
  • I need to verify the user has the proper permission before running the action
  • I need to make sure they are limited in what actions they can run
  • I need to make sure they don’t using caching or other tricks to skip the permission check

Java performs a privileged action using the AccessController.doPrivileged() method found in the java.security package. While using this method is not commonly used by most Java developers, it is required knowledge for the 1Z0-819 Exam.

1. The doPrivileged() method

A common example Oracle likes to use is reading a system property. The idea is that the programmer is only allowed to read a specific predefined system property.

import java.security.*;
public class MySecretReader {
   private static final String KEY = "secret.option";
   public String getSecret() {
      return AccessController.doPrivileged(
         new PrivilegedAction<String>() {
            public String run() {
               return System.getProperty(KEY);
            }
         });
   }
}

Here KEY is a constant that cannot be changed by the user. The idea here is that a user’s privilege is temporarily elevated so they can read the secret.option value within the system.

2. Ensure Principle of Least Privilege

When executing a privileged action, it is important to ensure that only the minimum access is granted. This is known as the principle of least privilege. Can you spot what’s wrong with the following example?

import java.security.*;
public class MySecretReader {
   public String getSecret(String magicWord) {
      return AccessController.doPrivileged(
         new PrivilegedAction<String>() {
            public String run() {
               return System.getProperty(magicWord);  // DON'T DO THIS!
            }
         });
   }
}

In this example, the caller is able to specify which value they want to read. This is considered a poor practice as it allows them to read any property within the system. Oracle refers this as a tainted input. Put simply, don’t trust anything the user provides when dealing with security. Also use a constant or predefined list to confirm they are accessing only what the original developer intended.

For the exam, be wary of any code that allows the user to access data that they specify, rather than the original programmer.

3. Don’t Expose Sensitive Information

Another important aspect of using doPrivileged() is ensuring sensitive data is protected. For example, can you spot the security risk in this code?

import java.security.*;
import java.util.*;
public class MySecretReader {
   private final List<Integer> codes = ...
   public List<Integer> getSecret() {
      return AccessController.doPrivileged(
         new PrivilegedAction<List<Integer>>() {
            public List<Integer> run() {
               return codes;  // DON'T DO THIS!
            }
         });
   }
}

Even though codes is marked final, the content can still be modified after the doPrivileged() is complete. This poses an unacceptable security risk. A much safer version would be to return an immutable copy of the list, such as:

      return AccessController.doPrivileged(
         new PrivilegedAction<List<Integer>>() {
            public List<Integer> run() {
               return Collections.unmodifiableList(codes);
            }
         });

Note that this works because Integer values are immutable. If the contents of the List were mutable, such as List<StringBuilder>, you want to copy them as well.

4. Don’t Elevate Permissions

Privilege elevation or escalation occurs when a user is mistakenly given access to a higher privilege than they should have access to. One way to prevent privilege elevation is to use to the AccessController.checkPermission() method before calling doPrivileged(), then execute the command with limited permissions.

import java.security.*;
public class MySecretReader {
   public void readData(Runnable task, String path) {
      // Check permission
      Permission permission = new java.io.FilePermission(path,"read");
      AccessController.checkPermission(permission);

      // Execute task with limited permission
      final var permissions = permission.newPermissionCollection();
      permissions.add(permission);
      AccessController.doPrivileged(
         new PrivilegedAction<Void>() {
            public Void run() {
               task.run();
               return null;
            }
         },
         // Using a limited context prevents privilege elevation
         new AccessControlContext(
            new ProtectionDomain[] {
               new ProtectionDomain(null, permissions)
            })
         );
   }
}

Don’t worry if you can’t write code like this, most developers never have to. For the exam, though, you should understand that the permission is being checked and the action is executed with a specific context.

5. Be wary of Permission Caching

The last rule you need to know for the exam is to be weary of cached permissions. It is perfectly acceptable to cache permission information, but the permission needs to be checked every time the user accesses it.

For example, assuming there’s a User class with appropriate attributes, methods and constructors, can you spot the problem in this code?

import java.security.*;
import java.util.*;
public class SecretFile {
   private static Map<String, User> data = new HashMap<>();
   public static SecretFile get(String key) {
      var cacheRecord = data.get(key);
      if (cacheRecord != null) {
         // DON'T DO THIS!
         return cacheRecord.getValue();
      }
      
      final var permission = Permission permission 
         = new PropertyPermission(key,"read");
      AccessController.checkPermission(permission);

      final var permissions = permission.newPermissionCollection();
      permissions.add(permission);
      var secret = AccessController.doPrivileged(
         new PrivilegedAction<SecretFile>() {
            public SecretFile run() {
               return new SecretFile();
            }
         }, new AccessControlContext(new ProtectionDomain[] {
               new ProtectionDomain(null, permissions) }));
      data.put(key, new User(secret, permission));
      return secret;
   }
}

Did you spot it? It might be hard to see, but there’s no permission check when the data is read from the cache! The permission is checked when the data is first read from the cache but not on subsequent calls. We can easily fix this though by checking the permission when it is read from the cache:

      var cacheRecord = data.get(key);
      if (cacheRecord != null) {
         AccessController.checkPermission(cacheRecord.getPermission());
         return cacheRecord.getValue();
      }

In this example, we see that cached permissions can be safe to use but we have to make sure the permission is validated when it is read the first time and on each request from the cache.

Conclusion

There, you’re done! This post covered the overall topics around Privileged Access that you need to know for the 1Z0-819 Exam. The following bullet points summarize the kinds of things you should be watching for on the 1Z0-819 Exam:

  • Always validate user input and never allow it to grant access to arbitrary data
  • Never give the user unlimited access to the system
  • Prevent privilege elevation by validating security
  • Never return privileged objects directly or in a way that they can be modified
  • Ensure cached permissions are validated on every call

If you enjoyed this section, you can read more about it in Oracle’s Secure Coding Guidelines for Java SE document.

Jeanne’s experience taking the 1Z0-819 in the time of COVID-19

Update (11/05/2020): Read The 1Z0-819 Exam page to learn how you can easily our Java 11 Study Guides to prepare for Oracle’s 1Z0-819 Exam, as well as the 1Z0-817 Upgrade Exam.

I took the 1Z0-819 exam today. I guess that makes me “triple qualified” having already passed the 1Z0-817 upgrade exam and the 1Z0-815/1Z0-816. I took the AWS Associate Architect exam two weeks ago.

COVID-19 logistics

I’m not willing to take the exam online so I signed up at a local testing center. I took this exam at a different center than where I took the AWS one since it wasn’t offered there. This exam center is a short bus ride away. (The AWS one was walking distance.) Overall, I think this center handled it better. They have more space so I was naturally further away from other people. I was also given hand sanitizer immediately on entry.

I was asked to take off my mask twice (once to verify I match my id and once to take a photo). That seems like it could have been combined.

Writing instruments

I haven’t been offered pencil/paper at an Oracle exam in years. This was the first time I wasn’t given an eraser for the erasable board. The proctor did come by towards the middle to see if I needed a second one though. (I did not).

Getting the score

I received my score immediately on completing the exam. It appeared right when I clicked finish. I was then given a printout saying “Your exam results are not available at this time… 30 minutes”. It looks like they are transitioning how it works. I’m happy to get a real time score again though! It’s been a while. (My score was 72%. That’s just barely passing. But that’s a story for another blog post)

Exam timing

You get 90 minutes to answer 50 questions. I can easily imagine someone running out to time on the exam. I finished going through a first pass of all the questions with 30 minutes left. However, I essentially skipped two (aka I guessed.) They weren’t hard – about control/flow. But they were time consuming. And I wanted to use the remaining time to go through the questions again to make sure I could say that our Complete Study Guide prepares you for the 819 exam. And it does.

Test taking skills are definitely important on this exam. For example, I looked at the answers before reading questions with a bunch of code. This gave me a clue what to look for. And also told me that I could read faster if there was “do not compile” option.

Question Distribution

When taking an exam, you have to agree not to share what was on it. So no details about what was covered. Sharing the distribution of questions by objective is fair game though!

Objective# Questions
Working with Java Data TypesAbout 5
Controlling Program Flow3
Java Object-Oriented Approach10-15
Exception Handling4
Working with Arrays and CollectionsAbout 4
Working with Streams and Lambda Expressions10
Java Platform Module System4
Concurrency2
Java I/O API3
Secure Coding in Java SE Application2
Database Applications with JDBC1
Localization1
Annotations1

(The counts don’t add up to 50 because a few questions covered multiple objectives for the early objectives)

815 vs 816 topics

Our books are labeled with 815 and 816. On the 819, it was split almost evenly. However, the difficulty of questions was uniform. It was just the topics that got distributed.

Where the topics what expected?

Almost. Enthuware wrote that doPrivileged was on the exam. We had used the Secure Coding Guide when writing our security chapter. Oracle updated the guide since the 816 came out. They also revised the exam. The word “privileged” was not in the objectives for the 816!

Should I take the 817 or 819?

Those who hold a Java 6, 7 or 8 certification are eligible for their choice of the 817 or 819 exams. They cost the same. The 819 allows half the time, but has a little over half the questions. So you have less time per question on the 819. Additionally, the 817 passing score cutoff is a bit lower.

While the 817 has a lot on modules (3/10 objectives), there are a lot of topics on the 819 not on the 817 (concurrency, secure coding, JDBC, localization, and annotations). Combined with the longer time for the 817, you are likely to find it an easier exam.

And important disclaimer about randomness

With only 50 questions, randomness is a bigger factor. This means you could easily not see questions on a topic. Or get more than someone else on another topic. Be careful as you read the experiences of people who have taken the exam. Just because they didn’t get a question on X doesn’t mean that you won’t! So you don’t get to skip studying topics.

How many questions are on the Java 11 certification exam?

Update (11/05/2020): Read The 1Z0-819 Exam page to learn how you can easily our Java 11 Study Guides to prepare for Oracle’s 1Z0-819 Exam, as well as the 1Z0-817 Upgrade Exam.

Here’s where things stand for the Java 11 exams.

Exam1Z0-8191Z0-817 (upgrade)
# questions5080
exam duration1.5 hours3 hours
passing score68%61%

Notice you have a little more time per questions on the upgrade exam. However, the passing score is higher.

As a point of reference, the 1Z0-819 is replacing the 1Z0-815 and 1Z0-816 exams which had also had 180 minutes to answer 80 questions and a passing score of 63%.

Remember that you can use our Java 11 Combined Study Guide to study for either the 817 or 819 exams. You can also buy the part 1 and part 2 separately which are the same content