18
Nov
This entry is part 1 of 4 in the series Securing Java Web Applications

Web applications are exposed to a number of threats all the time by their very nature of serving content to the public. There are intruders, hackers, impersonators, and eavesdroppers out there who try to wreck the contents you publish. This may harm your business in a serious way and therefore, it is important that you secure the contents of your Web application from such elements.

In this blog, I am going to explore some of the basic steps that can be taken to secure any Java-based Web application.

Placing the Files in the Right Directory

Java Web applications contain static HTML pages, JSP files, Servlet classes, Framework related classes (such as Action classes in case of Struts), Helper or Utility classes, image files, and any third-party jar files required by the application. Placing these files in the correct directories is the first step towards securing the contents of the application. The typical directory structure of any Java-based Web application deployed on a Tomcat Web server looks like this:

Java-based Web application

Only some of the parts of the application can be accessed directly using the URL. For example, in our case, the name of the application is TestApp which is also called a Webapp root directory. Anything that is placed directly inside the TestApp directory is accessible to the outside world, except the contents of the WEB-INF and META-INF directories. This stands true for any other directories we choose to create directly inside the TestApp directory to arrange our Web applications contents.

In our example, HTML files and JSP pages are placed directly inside the TestApp directory. Assume that a login.jsp file is also placed directly inside the TestApp directory.  This file can be accessed directly from outside the application using the URL http://www.mywebserver.com/TestApp/login.jsp. Further, assume that we choose to create a new directory called ‘auth’ inside the TestApp directory and place the login.jsp file in that directory. Will this new directory still be accessible from outside the application? Yes. In this case, the user just needs to point the browser to http://www.mywebserver.com/TestApp/auth/login.jsp.

This is not true for the resources placed inside WEB-INF and META-INF directories. Anything inside these two directories cannot be accessed from outside the Web server. The Sun Java Specification restricts any Web Server that supports Java based application deployment from directly serving the contents inside the WEB-INF and META-INF directories. If an attempt is made to access the resources inside these two directories, the Web Server in this case must respond with a “404 NOT FOUND” error to the user.

In our example above, if we move login.jsp from TestApp to WEB-INF and try to access it through the URL http://www.mywebserver.com/TestApp/WEB-INF/login.jsp, we will get a “404 NOT FOUND” error from the Web Server. Try this with the META-INF directory as well and you will get the same error.

So, the basic rule of thumb with any Java-based Web application is, place the resources you want to restrict access to in either the WEB-INF directory or META-INF directory. In other words, never put your confidential and valuable resources outside these two directories!

Disabling the Directory Listing Functionality

A Web Server is simply a place to publish the content that you want other people to access. You use the standard directory structure given above to arrange your application resources in the required and desired manner. You have also restricted the access to confidential resources by placing them in the appropriate directories as explained above. What will happen if someone is able to navigate through these directories and hack in? A situation like this is known as a directory traversal attack.

The directory listing feature is enabled by default when you install the Tomcat Web Server for the first time. This feature is useful when you are developing and debugging the Web application to quickly traverse through the application directories and the contents inside. You may not like to use this feature on the production server though. The main reason behind directory listing restriction is to discourage users from navigating through proprietary information.

You can disable the directory listing feature in two ways:

  • Modify the global web.xml file to disable the feature for all Web applications.
  • Modify the web.xml file specific to the application to disable the feature for that single application.

The first way is to open and modify the $CATALINA_HOME/conf/web.xml file. Make sure it contains the following settings for org.apache.catalina.servlets.DefaultServlet.


<servlet>
    <servlet-name>default</servlet-name>
    <servlet-class>org.apache.catalina.servlets.
DefaultServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
    <init-param>
        <param-name>debug</param-name>
        <param-value>0</param-value>
    </init-param>
    <init-param>
        <param-name>listings</param-name>
        <param-value>false</param-value>
    </init-param>
</servlet>

The second way is to redefine the above servlet mappings, with a different servlet name, inside the web.xml file of a particular Web application. For example, if you want to disable the directory listing feature only for TestApp, then you need to edit the TestApp/WEB-INF/web.xml file. Make sure it contains the following servlet mapping for org.apache.catalina.servlets.DefaultServlet.


<servlet>
    <servlet-name>defaultServlet</servlet-name>
    <servlet-class>org.apache.catalina.servlets.
DefaultServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
    <init-param>
        <param-name>debug</param-name>
        <param-value>0</param-value>
    </init-param>
    <init-param>
        <param-name>listings</param-name>
        <param-value>false</param-value>
    </init-param>
</servlet>

<servlet-mapping>
    <servlet-name>defaultServlet</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

Note that we have changed the value of the <servlet-name> element in the second listing above. This is required to avoid a conflict for two different servlet mappings for the same servlet.

The two techniques I have described here are the basic ways to start with security implementations for Web applications. At the advanced level, several additional checks such as authentication, authorization, confidentiality, data integrity, encryption, Secure Socket Layer (SSL) protocol, and data conversion techniques are needed to strengthen the security of the application.

Hitesh Patel
Hitesh Patel– Project Lead

26
Nov
This entry is part 2 of 4 in the series Securing Java Web Applications

In my last blog, Basics of Securing Java Web Applications, I talked about some basic measures that we can take to secure the content of Java-based Web applications. In this blog, I am extending the discussion on how to secure the application one step further by introducing the Authentication feature. Although Authentication and Authorization are features that usually go hand in hand, only the former has been discussed in this blog to keep it small and easier to understand. In my next post, I shall be discussing how to implement Authorization and how Authentication and Authorization work together.

As in the earlier blog, in this one too, I shall consider Apache Tomcat as the Web server on which the application is deployed.

Authentication and Authorization are two different techniques that are used together to restrict access to special features of a Web application. This restriction is applied on various parts of the application based on the organization roles, also called role-based access control. When deployed correctly, these two techniques together form the base of a secure Java-based Web application, which can be extended further by using other advanced techniques such as Confidentiality and Data Integrity.

I will also cover the definition of the terms ‘Authentication’ and ‘Security Realm’ as well as how to implement Authentication in a Web application here.

What is Authentication?

Authentication is an identity confirmation process, usually of the person trying to use the application. It is the way to ensure that the user is who he claims to be. In case of a Web application, it is the process of verifying the user’s credentials in some way.

Relation between the Apache Tomcat Server and the Security Realm

According to the Java Servlet Specification, a place where security information is stored is called realm. The Tomcat Web server provides a $CATALINA_HOME/conf/tomcat-users.xml file that it loads at the server startup time and uses the information provided in that file to build a memory realm. This file can be modified as needed and used to test security implementations at development time, but on a production server, a JDBC-based realm or JNDI based realm are the best approaches to be used.

The tomcat-users.xml file contains user and role mapping information for a memory realm as described below.

<tomcat-users>
  <role rolename=”tomcat”/>
  <role rolename=”role1”/>
  <user username="tomcat" password="tomcat" roles="tomcat"/>
  <user username="both" password="tomcat" roles="tomcat,role1"/>
  <user username="role1" password="tomcat" roles="role1"/>
</tomcat-users>

To start with the Authentication and Authorization implementation for a Web application, first we need to modify the contents of this file as desired. Let us assume that we would like to drop role1 defined above and instead, introduce new roles called Manager and Guest. We shall also define two new users and assign them some roles. This can be done as described in the code fragment below:

<tomcat-users>
  <role rolename=”tomcat”/>
  <role rolename=”Manager”/>
  <role rolename=”Guest”/>
  <user username="tomcat" password="tomcat" roles="tomcat"/>
  <user username="john" password="smith" roles="Manager, Guest"/>
  <user username="maria" password="" roles="Guest"/>
</tomcat-users>

Once we have defined the realm information, we can start with the Authentication and Authorization implementation for our application.

How to implement Authentication?

A common way to authenticate a user is to ask him to provide his username and password to access the restricted resource.  Another way is to provide a Public Key Security Certificate issued by a trusted security certificate provider (such as VeriSign®) to the user and validating that security certificate every time the user is trying to access the restricted resource.

The first approach of asking a user to provide his username and password can be achieved in several ways. All you need to do is specify the authentication method to be used in the <auth-method> element of the <login-config> element as described below:


<web-app …>
  …
  <login-config>
    <auth-method>BASIC</auth-method>
  </login-config>
</web-app>

There are four possible values for the authentication method used: BASIC, DIGEST, CLIENT-CERT, and FORM. Out of these four types, BASIC, DIGEST, and CLIENT-CERT use the browser’s default login dialog box to collect username and password information. Using the FORM method, you can provide a customized login form as desired. BASIC uses the base64 encoding scheme to transmit username and password information and so it is not as secure as DIGEST or CLIENT-CERT. All Web containers are required to support this authentication method. DIGEST uses a more secure way to transmit login information, but Web containers are not required to support it. CLIENT-CERT is the strongest one, because it uses a Public Key Certificate (PKC) to transmit the login information. Although it is strongest, it is not widely used because a certificate must be distributed to all users in order to enable them to log in to the system. The FORM method provides flexibility to define our own login form, but it does not use any encryption scheme, so it is the weakest of all four. Defining FORM based authentication is little different than other <auth-method> definitions, as described below:

<web-app …>
  …
  <login-config>
    <auth-method>FORM</auth-method>
    <form-login-config>
      <form-login-page>/login.html</form-login-page>
      <form-error-page>/loginError.html</form-error-page>
    </form-login-config>
  </login-config>
</web-app>

When the FORM based authentication method is used, the browser will not display the standard login dialog box as in the other three methods. The developer is responsible for creating a custom login form for that, but with several constraints. Note that in the above configuration that we have specified login.html is the login form. So, we need to create a login.html page in our application’s root directory. We also need to create a loginError.html page in the root directory to redirect the user to this page if authentication fails.

In the login.html page, we must use j_security_check as a form action, the name of the username field must be j_username and name of the password field must be j_password as described below:

<form method=”POST” action=”j_security_check”>
  User Name: <input type=”text” name=”j_username”> <br>
  Password: <input type=”password” name=”j_password”>
  <input type=”submit” value=”Submit”>
</form>

So, as I have explained above, the FORM based authentication method does not use any encryption. To secure the login information, we need to define additional security constraints in web.xml deployment descriptor called <transport-guarantee>. This is a separate topic altogether which I shall discuss in a future blog.

Once the authentication configuration is done in web.xml, the next step is to define the resources that we want to keep restricted. In my next blog, I shall cover this configuration along with the Authorization concept. Once the resources are constrained through the configuration provided in the web.xml file, whenever any user tries to access a restricted resource, the Web container will automatically display either the browser’s standard login dialog box or a login form if a FORM based authentication method is used. When a user submits his login credentials, they will be verified by the application server against the memory realm built by the Tomcat Web Server using the tomcat-users.xml file. In case of the FORM based authentication method, we can collect the username and password information on the server by extracting the values provided in the j_username and j_password fields. We can then use these values to authenticate the user against the JDBC-based realm, or the JNDI-based realm.

I have covered only Authentication concept in this post, but in my next post that I shall be posting in a few days, I will cover Authorization concept to conclude Authentication and Authorization.

Hitesh Patel
Hitesh Patel– Project Lead

02
Dec
This entry is part 3 of 4 in the series Securing Java Web Applications

This blog is a continuation of my previous one, Securing Java-based Web Applications: Authentication, in which I have explained the concept of Authentication with an implemented example of a Java-based Web application deployed using the Tomcat Web server.

I will now cover the concept of Authorization in the same way with an implementation example in this blog. I will also cover the definition of ‘Authorization’ with some code samples along with their explanation. The code samples provided here are in line with the code samples covered in my earlier post.

What is Authorization?

Authorization is the process of defining access policies for the resources we wish to protect. It is the way to ensure that the user has the rights to enter into the restricted area or perform a specific restricted function. In case of a Web application, it is the process of verifying the user’s rights based on his predefined role to access any restricted resource on the system.

In my previous post, I have covered the relationship between the Apache Tomcat Web Server and the Security Realm. I have also explained how to modify the $CATALINA_HOME/conf/tomcat-users.xml file to define users, roles and the mapping between the users and their roles. Additionally, I have also explained how to modify the web.xml file of an application to authenticate the user. But what happens after authentication?

Once the user has been authenticated, a Web container checks if the user is allowed to access the resource that he is requesting. It further checks if the user is allowed to perform the requested operation on that resource. This process is called Authorization. Remember however, that to enable authorization, it is necessary to enable authentication for an application by using the <login-config> setting as explained in my earlier post.

How to Implement Authorization?

It is the job of the deployer to decide which resources should be constrained and which users should be allowed to access those constrained resources. The deployer also defines the kind of operations that can be performed on those constrained resources by a user having a particular role.

The first step towards the implementation of authentication is by defining roles, which can be done by modifying the $CATALINA_HOME/conf/tomcat-users.xml file as explained in my earlier post (which also explains how to define the Manager and Guest roles).

The second step is to define the security roles in web.xml so that Tomcat can map the security roles of an application to the roles defined in the memory realm. If we are using the same names for the roles in an application as defined in tomcat-users.xml, then we just need to map the roles as illustrated below:

<web-app …>
  …
  <security-role>
    <description>This is a Manager role</description>
    <role-name>Manager</role-name>
  </security-role>

  <security-role>
    <description>This is a Guest role</description>
    <role-name>Guest</role-name>
  </security-role>
</web-app>

If we are using different names for the roles in the servlets from the roles defined for an application, then we have to map the servlet-specific (also known as user-defined) roles to the roles defined for the application. For example, assume that we have a servlet called DeleteUserServlet in our application and a developer of that servlet has used ‘Admin’ as a role in the request.isUserInRole(“Admin”) method. At the time of development, the developer had originally thought that ‘Admin’ would be the name of the role defined for the application, but a deployer has come up with a different name for the role – ‘Manager’. In this case, a deployer can map the user-defined role with the application specific roles as demonstrated in the following code snippet.

<web-app …>
  …
  <servlet>
    …
    <security-role-ref>
      <role-name>Admin</role-name>
      <role-link>Manager</role-link>
    </security-role-ref>
  </servlet>

  <security-role>
    <description>This is a Manager role which is equivalent to Admin role</description>
    <role-name>Manager</role-name>
  </security-role>

  <security-role>
    <description>This is a Guest role</description>
    <role-name>Guest</role-name>
  </security-role>
</web-app>

The last step is to define the resource and HTTP method constraints for an application in the web.xml file. Assume that we are developing a shopping cart application and we have DiscardBidServlet, DiscardItemServlet, and AddItemServlet. We will be mapping these servlets in the web.xml file as below:

<web-app …>
  …
  <servlet>
    <servlet-name>DiscardBidServlet</servlet-name>
    <servlet-class>app.admin.DiscardBidServlet</servlet-name>
  </servlet>

  <servlet>
    <servlet-name>DiscardItemServlet</servlet-name>
    <servlet-class>app.admin.DiscardItemServlet</servlet-name>
  </servlet>

  <servlet>
    <servlet-name>AddItemServlet</servlet-name>
    <servlet-class>app.common.AddItemServlet</servlet-name>
  </servlet>

  <servlet-mapping>
    <servlet-name>DiscardBidServlet</servlet-name>
    <url-pattern>/ShoppingCartApp/manage/deleteBid</url-pattern>
  </servlet-mapping>

  <servlet-mapping>
    <servlet-name>DiscardItemServlet</servlet-name>
    <url-pattern>/ShoppingCartApp/manage/deleteItem</url-pattern>
  </servlet-mapping>

  <servlet-mapping>
    <servlet-name>AddItemServlet</servlet-name>
    <url-pattern>/ShoppingCartApp/addItem</url-pattern>
  </servlet-mapping>
</web-app>

Now, we would like to apply the constraint that DiscardBidServlet and DiscardItemServlet should only be accessible by a user with the ‘Manager’ role and AddItemServlet should be executed only by a user with a ‘Guest’ role. This can be achieved as described below.

<web-app …>
  …
  <security-constraint>
    <web-resource-collection>
      <web-resource-name>ManagerConstraints</web-resource-name>
      <url-pattern>/ShoppingCartApp/manage/*</url-pattern>
      <http-method>GET</http-method>
      <http-method>POST</http-method>
    </web-resource-collection>

    <auth-constraint>
      <role-name>Manager</role-name>
    </auth-constraint>
  </security-constraint>

  <security-constraint>
    <web-resource-collection>
      <web-resource-name>GuestConstraints</web-resource-name>
      <url-pattern>/ShoppingCartApp/*</url-pattern>
      <http-method>*</http-method>
    </web-resource-collection>

    <auth-constraint>
      <role-name>Guest</role-name>
    </auth-constraint>
  </security-constraint>
</web-app>

In the above code snippet, we have declared the URL with the pattern /ShoppingCartApp/manage/* as a constrained resource. We have further fine-tuned the constraint only for the GET and POST HTTP methods. It means that whenever a Web container receives a request for a URL that contains the above pattern, if the request is for GET or POST HTTP methods, then it will first check if the user is authenticated.

Authentication for an application is explained in my previous post. The container will further check if the user who has requested this URL has the role of a ‘Manager’ by checking the user-role mapping in the memory realm built using the tomcat-users.xml file. The servlet will be allowed to serve the request only when the above details are verified, and not otherwise.

In the above configuration, the URL pattern and HTTP methods together define which resource requests are constrained to be accessed only by the roles that are defined in the <auth-constraint> entry. Since only the ‘Manager’ role is specified in the first <security-constraint> entry, any user who does not have the role of a ‘Manager’ will not be allowed to execute GET and POST requests on the URL pattern /ShoppingCartApp/manage/*.

In the second <security-constraint> entry, we have constrained the URL pattern /ShoppingCartApp/* for all HTTP methods by specifying the ‘*’ wildcard character for the user with a ‘Guest’ role. This means that only users with ‘Guest’ roles will be allowed to access all the HTTP methods on the URLs with /ShoppingCartApp/*. Remember however, that the first <security-constraint> entry still restricts ‘Guest’ users to access ‘Manager’ specific URLs.

The <url-pattern> entry in <web-resource-collection> is mandatory; however, it is possible to specify more than one <url-pattern> in a single <web-resource-collection>. This way, we can constrain multiple URLs for the same set of roles for the same set of HTTP methods.

The <http-method> entry is optional. If omitted, all the HTTP methods will be constrained, which means that only the roles specified in the <auth-constraint> entry can access any of the methods. If used, only the specified HTTP methods will be constrained, and not the rest.

More than one <web-resource-collection> can be specified in the same <security-constraint>. This way, we can constrain multiple URLs for multiple HTTP methods for the same set of roles.

The <role-name> element within the <auth-constraint> element is optional. If it exists with specific role names, only those roles will be allowed to access the constrained resources. If the wildcard character ‘*’ is used for <role-name>, then all the users are allowed to access the constrained resources. If the <role-name> entry is omitted from the <auth-constraint> element, none of the users will be able to access the constrained resources.

The <auth-constraint> element within the <security-constraint> element is optional. If it exists, the container must perform authentication and authorization for the constrained resources. If omitted, the container must allow unauthenticated access to the constrained resources.

This concludes the implementation of Authentication and Authorization for a Java-based Web application. In my upcoming blog, I shall be discussing how to use servlet filters to deal with concerns (also known as Aspects) such as Logging and Security in an application.

Hitesh Patel
Hitesh Patel– Project Lead

17
Dec
This entry is part 4 of 4 in the series Securing Java Web Applications

Introduction

There are often requirements for a Web application to provide the functionalities that are either for an administrative purpose, for a special group of users, or simply to improve the overall response time for a specific type of response for the application. For a Java-based Web application, we have the facility of using filters and wrappers to serve these functionalities. Filters and wrappers are powerful features provided by servlet API to implement cross-cutting features such as logging, auditing, keeping track of user activities, zipping a large file before sending it to a user, or creating a different response altogether.

In this blog article, I am going to discuss the definition of a filter and how we can use the filter API in an application.

What are Filters?

Filters are Java components available in servlet API that are used to intercept the request and response generated by a servlet. The functionality and implementation of a filter are very similar to that of a servlet.

How to implement a Filter?

There is a single interface called Filter available in the servlet API to implement a filter. This interface declares the lifecycle methods for a filter. There are three lifecycle methods called init(), doFilter() and destroy() that we need to implement in a filter class as demonstrated in the following code snippet.


package test;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class TestFilter implements Filter {
  private FilterConfig config;

  public void init(FilterConfig config) throws ServletException {
    this.config = config;
  }

  public void doFilter(ServletRequest request,
                       ServletResponse response,
                       FilterChain chain)
                          throws ServletException, IOException {
    HttpServletRequest req = (HttpServletRequest) request;
    …
    // Call the next filter in the chain
    chain.doFilter(request, response);

    // Process the response if required
    …
  }

  public void destroy() {
  }
}

As we can see, the implementation of a filter is very similar to that of a servlet, with a minor difference in the execution of a filter. The fact is, we can have multiple filters associated for a given URL pattern or a servlet, and the container then chooses which filter to execute and in which order based on the configuration provided in the deployment descriptor. There are certain rules followed by the container that decides which filter will be executed next.

The call to chain.doFilter() in the code snippet above is an instruction to the container that this filter has finished its work and the request is ready to be passed on to the next filter in the chain. If there is no other filter remaining in the chain, then the container will pass on the request to the actual servlet. Similarly, when the servlet finishes with the response, the container will pass on the response to the last filter called and the execution begins from the statement after the chain.doFilter() call.

We need to register and map filters for a URL pattern or for a servlet in a deployment descriptor as illustrated in the following code snippet. We will map TestFilter declared above with two more filters, Filter1 and Filter2, with the ‘*.do’ URL pattern, and TestFilterServlet to understand how multiple filters are mapped and executed.

<filter>
  <filter-name>TestFilter</filter-name>
  <filter-class>test.TestFilter</filter-class>
</filter>

<filter>
  <filter-name>Filter1</filter-name>
  <filter-class>test.Filter1</filter-class>
</filter>

<filter>
  <filter-name>Filter2</filter-name>
  <filter-class>test.Filter2</filter-class>
</filter>

<filter-mapping>
  <filter-name>TestFilter</filter-name>
  <url-pattern>*.do</url-pattern>
</filter-mapping>

<filter-mapping>
  <filter-name>Filter2</filter-name>
  <servlet-name>FilterTestServlet</servlet-name>
</filter-mapping>

<filter-mapping>
  <filter-name>Filter1</filter-name>
  <url-pattern>*.do</url-pattern>
</filter-mapping>

Here, we have configured TestFilter and Filter1 for a URL pattern ‘*.do’ and Filter2 specifically for  FilterTestServlet. When more than one filter is mapped to a single URL pattern or a servlet, the container executes all URL related filters first in the order specified in the deployment descriptor, followed by all the filters mapped to a specific servlet in the order specified.

In the example above, if the request is for a FilterTestServlet and if it ends with a ‘.do’ extension, then the container executes TestFilter first and calls its doFilter() method. When the execution reaches the chain.doFilter()call in TestFilter, the container executes Filter1, because it too matches the ‘.do’ extension. Similarly, when the execution reaches the chain.doFilter() call in Filter1, the container executes Filter2, because it is declared as a filter for FilterTestServlet. When the container encounters the chain.doFilter() call in Filter2 and it identifies that there are no more filters in the chain to be executed, the request is passed on to the actual servlet TestFilterServlet. When the TestFilterServlet finishes, the container will execute the filters in the LIFO order. In our example, the container will execute Filter2, Filter1, and TestFilter in that order. Remember, this time the execution begins at the statement that follows the chain.doFilter() call in the filter.

Since filters are configured for a URL or a resource through a deployment descriptor, it is very easy to change the execution order, or to add new filters and remove the existing ones without modifying the actual servlet code. Using filters, you can easily add common functionalities such as logging, auditing, security, user tracking, etc. across the application without touching the servlet code.

Conclusion

There is more to the filter API to modify the request and response objects before the actual request is passed onto the servlet or the actual response is passed onto the client. We have wrapper classes called ServletRequestWrapper, HttpServletRequestWrapper, ServletResponseWrapper, and HttpServletResponseWrapper in servlet APIs using which we can provide custom request and response objects. For detailed explanation of filters and wrappers, I suggest reading The Essentials of Filters provided by Oracle.

Hitesh Patel
Hitesh Patel– Project Lead