How to Define a Security Policy

Posted by Serge Truth on September 6, 2011 at 10:54 AM

Define a Security PolicyApplies to

Applications written using Servlets or JSP.

What to Do

Define a security policy for your application while applying the principle of least privilege. Restrict application execution to allow only the minimum set of necessary actions.

Why

Defining a Java security policy is a defense in-depth mechanism for restricting your application from performing tasks that the operating system would otherwise allow. This is especially important in the event your application becomes compromised by an attacker.

When

Always define a security policy for your application. This process should take place during your application's design stage.

How

Although Java applications run inside a virtual machine, do not execute your application in the context of a privileged user. Consider tightening the restrictions on your application by employing Java Policies.

Use the following steps to successfully utilize Java Permissions:

  1. Identify the system resources that your application uses. Enumerate all resources that your application will need to access. Identify the types of permissions that your application requires to access those resources. For example, your application will need to connect to your database via a socket connection or write to your logs.

  2. Identify your application. Your application can be identified via two ways inside a Java policy — code signing or code base.

    • Code signing. Always sign your code whenever possible. This ensures the authenticity of your code. Use Java's KeyTool when signing your code.

    • Code base. Identify the location of your code. Example:

      codeBase "file:e:/myapp/bin/"
  3. Create the appropriate policy. Once all required resources are enumerated, create a Java policy that reflects the type of access that is required for each resource. Example:

    grant codeBase "file:e:/myapp/bin/-" 
    {
    // A placeholder for all appropriate permissions
    };

    Assign a permission for each required resource. Java provides different types of permissions, each of which can be customized to meet your application's needs:

    • java.security.AllPermission: AllPermission grants all other permissions to the code. It should seldom be used. Example:

      permission java.security.AllPermission;

      For more information, consult the documentation for Class AllPermission in the Java SDK.

    • javax.sound.sampled.AudioPermission: AudioPermission grants access rights to the system's audio components. It should be used only when the application is required to play or record audio. Example:

      permission javax.sound.sampled.AudioPermission "play";

      For more information, consult the documentation for Class AudioPermission in the Java SDK.

    • javax.security.auth.AuthPermission: AuthPermission is used during authentication procedures. The AuthPermission's only argument is the name of the security configuration parameter. This permission class is used to guard access to the Policy, Subject, LoginContext, and Configuration objects. Example:

      permission javax.security.auth.AuthPermission "modifyPrincipals";

      For more information, consult the documentation for Class AuthPermission in the Java SDK.

    • java.awt.AWTPermission: AWTPermission grants access to the system's user experience and graphical interface. For example, the following permission would allow the application to access the system's clipboard:

      permission java.awt.AWTPermission "accessClipboard";

      For more information, consult the documentation for Class AWTPermission in the Java SDK.

    • javax.security.auth.kerberos.DelegationPermission: DelegationPermission restricts the usage of the Kerberos delegation model. Example:

      permission javax.security.auth.kerberos.DelegationPermission
      "\"host/foo.example.com@EXAMPLE.COM\" \"krbtgt/EXAMPLE.COM@EXAMPLE.COM\"";

      For more information, consult the documentation for Class DelegationPermission in the Java SDK.

    • java.io.FilePermission: FilePermission grants access to files on the local system. Access right are read, write, execute, delete. Note that FilePermission always grants read access to files within the code's directory and any subdirectories. Example:

      permission java.io.FilePermission "e:/myapp/logs/20061016.log", "write";

      For more information, consult the documentation for Class FilePermission in the Java SDK.

    • java.util.logging.LoggingPermission: LoggingPermission is associated with Java's standard logging mechanism. Because Java's logging mechanism does not meet the recommendation for logging security events, please consult the Log Important Security Operations guideline if your application performs logging. Currently LoggingPermission grants only the right to control Java's logging configuration. Example:

      permission java.util.logging.LoggingPermission "control";

      For more information, consult the documentation for Class LoggingPermission in the Java SDK.

    • java.net.NetPermission: NetPermission grants access to various network permissions. For example, the following permission allows the ability to specify a stream handler when constructing a URL:

      permission java.net.NetPermission "specifyStreamHandler";

      For more information, consult the documentation for Class NetPermission in the Java SDK.

    • javax.security.auth.PrivateCredentialPermission: PrivateCredentialPermission protects access to the private Credentials belonging to a particular Subject. Example:

      permission javax.security.auth.PrivateCredentialPermission
      "javax.resource.spi.security.PasswordCredential * \"*\"","read";

      For more information, consult the documentation for Class PrivateCredentialPermission in the Java SDK.

    • java.util.PropertyPermission: PropertyPermission specifies the read/write access to an object's or System's properties. Example:

      permission java.util.PropertyPermission "java.home", "read";

      For more information, consult the documentation for Class PropertyPermission in the Java SDK.

    • java.lang.reflect.ReflectPermission: ReflectPermission grants access to reflective operations. Currently it only allows suppressing the standard Java language access checks (i.e. public, protected and private) by reflected objects at their point of use. Example:

      permission java.lang.reflect.ReflectPermission "suppressAccessChecks";

      For more information, consult the documentation for Class ReflectPermission in the Java SDK.

    • java.lang.RuntimePermission: RuntimePermission grants access to runtime operations such as loading external libraries and halting the JVM. Example:

      permission java.lang.RuntimePermission "accessDeclaredMembers";

      For more information, consult the documentation for Class RuntimePermission in the Java SDK.

    • java.security.SecurityPermission: SecurityPermission is used any security related events. Example:

      permission java.security.SecurityPermission "createAccessControlContext";

      For more information, consult the documentation for Class SecurityPermission in the Java SDK.

    • java.io.SerializablePermission: SerializablePermission grant access to more advanced features of Java's serialization model. For example, the following permission allows the substitution of one object for another during serialization:

      permission java.io.SerializablePermission "enableSubstitution";

      For more information, consult the documentation for Class SerializablePermission in the Java SDK.

    • javax.security.auth.kerberos.ServicePermission: ServicePermission protects the access to Kerberos services and any supplemental credentials. Example:

      permission javax.security.auth.kerberos.ServicePermission
      "krbtgt/EXAMPLE.COM@EXAMPLE.COM", "initiate";

      For more information, consult the documentation for Class ServicePermission in the Java SDK.

    • java.net.SocketPermission: SocketPermission grants access to the network via sockets. It allows your application to connect to a host, accept connections from a host, listen on a given port, or resolve the other host's IP/hostname. Example:

      permission java.net.SocketPermission "serv02.example.com:3306", "connect";

      For more information, consult the documentation for Class SocketPermission in the Java SDK.

    • java.sql.SQLPermission: SQLPermission grants access to operations executed during database access. Currently all standard Java methods that use SQLPermission are deprecated. For more information, consult the documentation for Class SQLPermission in the Java SDK.

    • javax.net.ssl.SSLPermission: SSLPermission grants access to SSL related operations. For example, an SSLPermission would be required to get the SSLSessionContext of an SSLSession:

      permission javax.net.ssl.SSLPermission "getSSLSessionContext";

      For more information, consult the documentation for Class SSLPermission in the Java SDK.

  4. Load the policy at runtime. By default Java provides two policy files: a system policy file ({java.home}/lib/security/java.policy) and a user policy file ({user.home}/.java.policy). Use the -Djava.security.policy(={policy file}) flag to load your policy during the start-up routine of your application's server. Make sure you use only a single = to append your policy to the JVM's default policies as == will force the JVM to load your policy only. Example:

    -Djava.security.policy=e:/myapp/config/myapp.policy
  5. Enforce your application's policy. To fully enforce your application's policy, attach a SecurityManager to the System object. Because most standard Java packages come with built-in permission checks that are linked to the System's SecurityManager, enforcing a certain set of permissions is a fairly easy task. Example:

    if (System.getSecurityManager() == null)
    {
    System.setSecurityManager(new SecurityManager());
    }

    or

    -Djava.security.manager

    Be aware that enforcing a security policy may restrict access to various resources that are essential to the application's environment. Examples of such resources include, but are not limited to, use of network sockets, application server's local files, etc. Use the following steps to resolve such problems:

    1. Enumerate all permissions that are granted to your application's environment. Enumerating all granted permissions to your application's environment helps identify the basic functionality that it requires for its normal operations. The following code helps you identify all permissions that your application inherits from its environment:

      public void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException
      {
      PrintWriter out = response.getWriter();
      CodeSigner[] cSign = null;
      CodeSource cSource = new CodeSource(null, cSign);
      Principal[] principals = new Principal[0];
      ProtectionDomain pDomain = new ProtectionDomain(cSource,
      null, null, principals);
      java.security.Policy policy = java.security.Policy.getPolicy();
      PermissionCollection permCollect = policy.getPermissions(pDomain);
      Enumeration permList = permCollect.elements();
      while (permList.hasMoreElements())
      {
      out.println( "<br>" + permList.nextElement().toString());
      }
      }

      Note that the code snippet will perform its intended action only if the System's SecurityManager is set to null.

    2. Check if your application's environment performs unauthorized actions. Enable the SecurityManager during the start-up routine of your application's environment. Monitor the environment's logs for any access denied errors. For instance, Tomcat will not function properly if the administrator does not grant a SocketPermission to connect and resolve 127.0.0.1 on port 8005:

      Exception in thread "ContainerBackgroundProcessor[StandardEngine[Catalina]]"
      java.security.AccessControlException: access denied
      (java.lang.RuntimePermission setContextClassLoader)
      ...
      Caused by: java.security.AccessControlException: access denied
      (java.net.SocketPermission 127.0.0.1:8005 connect,resolve)
    3. Grant the essential permissions for your application's environment. Grant all essential permissions into the security policy for your application's environment to allow the environment to function properly.

  6. Protect security policy files. Make sure that appropriate security measures are taken when storing the security policy files.

    • Choose a security policy directory: Dedicate a directory for storing your application's security policy files. Make sure the directory is not web-accessible. This limits the scope of users who can potentially compromise the contents inside the directory.
    • Set appropriate permissions: Apply the appropriate filesystem permissions such that the security policy files can be only accessed by your application and its administrators.
  7. Avoid common mistakes.

    • Delegate a Policy Manager: Java allows its applications to alter the JVM's policies during runtime. If your application needs to alter its policies during runtime, create a custom Policy Manager and delegate it the task of altering Java policies. Using the SecurityPermission class, enforce strict access control to the manager's functionality such that only authorized components can request modifications to the JVM's policies.

      The following permissions must be granted to the Policy Manager's code:

      java.security.SecurityPermission "getPolicy";
      java.security.SecurityPermission "setPolicy";
    • Enforce the security policy as early as possible: Delaying the enforcement of the security policies provides a bigger window of opportunity for an attacker to execute a payload through your compromised application.

Topics: developer guidance, application security, application risk & compliance

Serge Truth

Written by Serge Truth

Serge is a Content Lead here at Security Innovation. He is an IT and Information Security professional, certified by the Committee on National Security Systems Instruction.