| < Free Open Study > |
|
The Java 2 security model provides a fine-grained, policy-based mechanism with which we can control programmatic access to system resources. The level of protection is set by modifying a policy file for individual Java Virtual Machines (JVMs).
Once security is enabled, resources cannot be accessed unless access is explicitly granted in a policy file.
Policy files can be used to:
Only allow connections to the host on which the code was originally loaded from
Prevent access to the local file system
Prevent access to JVM and OS properties
A policy file contains grant statements, which grant permission for a specific type of access by a specific principal:
A security principal is associated with a body of code
A permission encapsulates the action of accessing a protected system resource
The following table describes some of the most frequently used permissions in typical policy files.
Permission | Description |
---|---|
java.lang.RuntimePermission | Controls the runtime execution of vital system calls, such as exitVM(), setSecurityManager(), and createClassLoader() |
java.util.PropertyPermission | Controls access (both read and write) to system properties |
java.io.FilePermission | Controls access (read, write, delete, and execution) to files and directories |
java.net.SocketPermission | Controls access (connect, listen, accept, and resolve) to network sockets |
java.security.AllPermission | Enables access to all protected resources |
You can find a complete list of security permissions in the online documentation at http://java.sun.com/security/.
When we start Tomcat using the default startup script, it is started without security enabled, which is equivalent to a grant of java.security.AllPermission. Tomcat comes with a default policy file that is used when we start Tomcat with security enabled. This policy file is named catalina.policy and is stored in the %CATALINA_HOME%\conf directory.
Let's examine some interesting parts of this policy file, starting with the system code permissions:
grant codeBase "file:${java.home}/lib/-" { permission java.security.AllPermission; };
The Java compiler needs to be called from within Catalina (the servlet container used by Tomcat) and this policy will enable it to access everything (as we trust the Java compiler to consist of benevolent code). The same permission is granted to system extensions:
grant codeBase "file:${java.home}/jre/lib/ext/-" { permission java.security.AllPermission; };
Although the Catalina server code is not system library it is granted all permissions to facilitate its operation:
grant codeBase "file:${catalina.home}/bin/bootstrap.jar" { permission java.security.AllPermission; };
The code in the common library will also be granted all permissions, which means that we should pay be careful about what we place into this directory:
grant codeBase "file:${catalina.home}/common/-" { permission java.security.AllPermission; };
The policy file goes on to grant permissions to the container's core code, the JSP page compiler, the shared web application libraries, and the shared web application classes.
We're now ready to try out a malicious servlet to see how a server-side policy file can protect us from its mischief. Consider the following servlet:
import javax.servlet.*; import javax.servlet.http.*; public class MaliciousServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { System.exit(1); } }
The System.exit(1) system call is designed to stop the execution of the JVM that is hosting the servlet container. This represents the type of mistake that could be made by an inexperienced developer working on a shared servlet hosting environment.
Start Tomcat without security enabled and access our servlet by navigating to http://localhost:8080/policytest/servlet/MaliciousServlet. Tomcat will shutdown because with security not enabled, any servlet can shutdown the JVM that Tomcat is running on.
Next, we'll start Tomcat with security enabled, which by default will grant the permissions specified in catalina.policy. This policy file does not grant java.lang.RuntimePermission for exitVM() to any web application, which means that web applications will not be able to successfully call the exit() method.
Use the following command to start Tomcat in security enabled mode:
catalina start -security
Now, when we navigate to http://localhost:8080/policytest/servlet/MaliciousServlet we'll see something like:
The servlet has committed an access violation, but in this case the server is spared a complete crash.
Let's create another servlet that accesses a known URL, and passes its content to the client. This means that it will require permission to access a specific host and socket:
import java.net.*; import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public class NetAccessServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { PrintWriter out = response.getWriter(); String tpString = null;
The servlet creates a connection to http://localhost:8080/ and then creates a BufferedReader from the content of the URL connection. Once the connection is opened, it simply sends everything to the servlet's response:
try { URL myConn = new URL("http://localhost:8080/"); BufferedReader myReader = new BufferedReader((new InputStreamReader(myConn.openStream()))); while ((tpString = myReader.readLine()) != null) { out.println(tpString); } } catch (Exception ex) { ex.printStackTrace(out); } } }
Start Tomcat without security and navigate to http://localhost:8080/policytest/servlet/NetAccessServlet. You should be redirected to the Tomcat home page, (although without the images as they are located at a different URL).
Shutdown Tomcat, restart it with security, and navigate again to http://localhost:8080/policytest/servlet/NetAccessServlet. Once more, we will see an access exception, which means that by default, servlets are not allowed to directly access to any network resource. In order to enable the specific network access required by our NetAccessServlet, we must add the following entry into catalina.policy:
grant codeBase "file:${catalina.home}/webapps/policytest/WEB- INF/classes/NetAccessServlet.class" { permission java.net.SocketPermission "localhost:8080", "connect"; };
This entry grants NetAccessServlet (but no other class) the privilege of connecting to localhost at port 8080. Make the addition to catalina.policy, restart Tomcat 4 with security, and navigate to http://localhost:8080/policytest/servlet/passthru. This time, you will see Tomcat's home page.
| < Free Open Study > |
|