This article is taken from the website http://jdj.sys-con.com/

Imagine building a house starting with only a pile of timber and a lump of iron, or making a bowl of spaghetti from a sack of wheat and a bag of tomatoes. The importance of having the right materials makes the idea of building products from scratch seem absurd. Similarly, any software project that doesn’t take advantage of the numerous frameworks available for any manner of development activity could be wasting valuable resources and ignoring established best practices.

The advantages of using frameworks are obvious to any developer who has implemented a complex, bug-ridden solution to a design problem that’s already been elegantly addressed by a framework. And perhaps the most difficult design problems to get right are those concerning security. With the popularity of Web applications and services on the rise, there has been an increasing move to standardize security-critical tasks, such as authentication and session management, in the container or framework. This way, developers can focus on implementing business processes, rather than specialized tasks like cryptographic algorithms or pseudo-random number generation.

This article will focus on developing secure Web applications with the popular Java framework Struts. It will detail a set of best practices using the included security mechanisms. The first section will provide an overview of both Struts and Web application security as a context for discussion. Each subsequent section will focus on a specific security principle and discuss how Struts can be leveraged to address it.

Struts
Struts is a very popular framework for Java Web applications large and small because of the numerous advantages it offers developers. The main goal of the Struts framework is to enforce a MVC-style (Model-View-Controller) architecture, which means that there is a separation of concerns among different architectural components: the model is the representation of the logic, the view is in charge of displaying data to the user, and the controller is responsible for providing the user with a way to interact with the application and affect the model. A simple analogy for this is a video game, where you have a game console (the model), the television or monitor (the view), and a controller (quite appropriately, the controller). This architectural pattern promotes reuse and stability by reducing the effects of code changes (since the implementation of each component is agnostic to the implementation of the others and the model is isolated from the user).

Although it is approximately an implementation of the MVC pattern, Struts is more accurately based on the “Model 2” architecture specific to the Java servlet technology. Rather than having users access the JSPs directly, Struts applications have a “front controller” servlet that’s the initial target of all requests and decides how to process requests and route users. Struts also has two different frameworks, the original (Struts Action Framework) and one based on JSF (Struts Shale). For the purposes of this article, we’ll only consider the original framework.

Web Application Security
Web applications (such as those built on Struts) rely on users being able to access potentially sensitive information from all over the world over disparate untrusted networks. It’s not exactly a surprise or a secret that many non-secure Web applications have been exploited, making front-page news and causing an enormous amount of problems for the organizations responsible. Application security attacks like SQL injection, cross-site scripting, session hijacking, and cookie poisoning are now mainstays in the toolkit of any hacker worth his salt, and it’s becoming increasingly obvious that developers have to put more of an emphasis on security.

Organizations like OWASP (Open Web Application Security Project) and WASC (Web Application Security Consortium) have assembled a great deal of information on how to avoid common pitfalls and create more secure Web applications. These and other resources are invaluable for learning about Web application security, and this article complements them as a guide for best practices in Struts applications with respect to security. Here we’ll focus on four specific types of security concerns and how they relate to Struts.

Struts & Input Validation
Input validation refers to the practice of verifying that input from an untrusted source is acceptable and safe to use. This has a significant security impact because malformed data submitted by a malicious user is the direct cause of numerous exploits (including SQL injection and cross-site scripting) and generally causes an application to behave unexpectedly and outside of its security design.

The Struts Validator plug-in lets you cleanly encapsulate all of your validation logic in XML configuration files instead of Java code. The Validator plug-in assists developers by standardizing common types of validations, preventing validation logic duplication, and being easier to verify and change (no recompilation is required). Two things to consider when using the Validator plug-in:

  1. There’s a mechanism to validate the code of the ActionForm (org.apache.struts.action.ActionForm, the Java class in the controller responsible for handling user data). However, this doesn’t offer the advantages described above and won’t be discussed here.
  2. Any business-level validation should be performed in the model, and the controller should be limited to semantic validation (correct length, type, acceptable character set). For instance, in the Validator plug-in you might ensure a credit card number is the right format, but you’d ensure it’s a valid card in the business logic.

Here’s how the Validator plug-in works: 1. User input is encapsulated in one of the ValidatorForm classes (which extend ActionForm classes):

public class UserValidatorForm extends org.apache.struts.validator.ValidatorForm {
public String firstName;
public String lastName;
public String phoneNumber;
public String userId;

}

2. Validation functions (several standard ones come pre-baked) are defined in validator-rules.xml. This rule calls a validation method from a custom class:

<validator name=”userId”
classname=”com.jdjexample.validator.UserIdValidator”
method=”validateUserId”
methodParams=”java.lang.Object,
org.apache.commons.validator.ValidatorAction,
org.apache.commons.validator.Field,
org.apache.struts.action.ActionErrors,
javax.servlet.http.HttpServletRequest”
msg=”errors.userid”>

</validator>

3. Validation.xml maps which fields have to be validated by which rules:

<form-validation>
<formset>
<form name=”userForm”>
<field property=”firstName” depends=”required”>
<arg0 key=”firstName.displayName”/>
</field>
<field property=”lastName” depends=”required “>
<arg0 key=”lastName.displayName”/>
</field>
<field property=”phoneNumber” depends=”required, mask”>
<arg0 key=”phoneNumber.mask”/>
<var>
<var-name>mask</var-name>
<var-value>
^D?(d{3})D?D?(d{3})D?(d{4})$
</var-value>
</var>
</field>
</field>
<field property=”userId” depends=”required, userId”>
<arg0 key=”phoneNumber.mask”/>
</field>
</form>
</formset>
</form-validation>

So how can we use the Validator plug-in to improve security?

1. Think “White List” – Most common attacks based on input validation flaws leverage special “meta-characters” to inject user-modifiable data into places it shouldn’t be. A typical security mistake developers make is to try to recognize, clean, or escape known “bad” values rather than accept only “good” values. This becomes a problem when a new “bad” value is discovered. With the enormous number of different locales, encodings, syntaxes, and variations thereof, it’s likely this strategy will fail, or at least be difficult to maintain. Struts Validator plug-in lets users verify that input data conforms to strict requirements and is well formed. The validation routines Struts uses can leverage regular expressions (with the mask field) to ensure that only safe strings are accepted. Sometimes, it may be necessary to accept some malicious characters, but it’s important to handle them very carefully. Furthermore, data can be verified to ensure that it’s within reasonable length bounds to avoid denial-of-service-style attacks.

2. Be Consistent – Using the Validator plug-in, it’s significantly easier to verify that there are no holes in the input validation mechanism. This means that all the data from the user should be in a ValidatorForm class and all fields should be specified in the validation framework. This can be checked simply by matching XML elements and it’s much easier to discern than having widespread, inconsistent input validation schemes.

3. Be Strict – Furthermore, there are some cases where it’s preferable to let the user select a few values from a finite list than to let him enter arbitrary data (for example, in cases of a yes/no, multiple choice, or filename). When designing input forms, it’s good practice to constrain the possible values as narrowly as possible and reinforce these constraints through validation.

Struts and Access Control
One of the main principles of security is access control (also called authorization) – making decisions on who can and can’t do what. Operating systems, file systems, databases, and other systems that must enforce security requirements all contain some sort of access control system to prevent malicious and/or inappropriate usage or resources. In Java Web applications using JAAS (Java Authentication and Authorization Service) and similar mechanisms, there are two different approaches for enforcing access control: declarative and programmatic. Declarative access control means specifying users, roles, and security constraints in configuration files, while programmatic access control declares and implements this logic in the code. The decision to use either approach depends on requirements, but generally declarative access control is easier to implement but inflexible, while programmatic access control requires custom coding but is largely customizable.

The Struts framework, as a whole, is built to be extensible, and this is one of its major strengths. Whether an application uses declarative or programmatic access control, Struts has built-in support and extension points for fulfilling access control requirements.

Declarative Access Control
The Struts framework has a role-based access control mechanism for securing actions declaratively. In struts-config.xml, each action has a roles attribute, which accepts a comma-separated list of available roles:

<action path=”/AdminLogin”
forward=”/admin_login.jsp”
roles=”administrator”/>

This allows for a more natural approach to access control based on the named Action classes rather than URL patterns. One important thing to note is that this doesn’t secure JSPs, HTML, or other non-Action resources. If all JSPs are only accessible through the controller (which is a Struts/MVC best practice), a recommended countermeasure is to put all JSPs in the WEB-INF folder so they aren’t directly available to users. However, this requires that the container stipulates that files in the WEB-INF folder aren’t accessible to Web users. Otherwise, JSPs can be protected by standard security constraints in the configuration file.

Programmatic Access Control
The Struts framework offers several different extension points where programmatic access control can be implemented. Specifically, the request processor has a processRoles() method that can be extended to do custom programmatic access control for all requests to the application:

protected boolean processRoles( HttpServletRequest request,
HttpServletResponse response,
ActionMapping mapping )
throws IOException, ServletException {

if (request.isUserInRole(roleName)) {

}

There are other places that access control could occur, including Servlet Filters and ActionServlets, which will be discussed in the struts and Cross-Cutting Security Concerns section.

Additionally, Struts has tag libraries to support programmatic “content-level” access control in JSP pages. Using the following tag, content in JSP pages can be secured according to roles:

<logicRazzresent role=”administrator”/>
<a href=”admin_page.jsp”>Administrator Home</a>
</logicRazzresent>

In almost all cases, it’s recommended that you use the security mechanisms built into the containers and frameworks rather than write them from scratch. Struts provides a granular, integrated set of role-based access control functionalities that help teams design and implement secure applications.

Struts and Error Handling
Application hackers are very resourceful; any piece of information uncovered during an attack will be noted, analyzed, and leveraged for future attacks. One of the most useful (read compromising) pieces of data that a hacker can access is an error messages that says too much about the internal workings of the application. This lets the attacker make informed decisions about the effectiveness of the attack, how to proceed in further attacks, and what resources are accessible by the application.

Struts has a very powerful and extensible exception-handling mechanism built-in. It’s very important, for security’s sake, to use this carefully to improve the user experience without letting information leak to malicious attackers. Specifically, it’s important to have robust error handling, so that expected errors (e.g., bad logins) are handled as appropriately as unexpected errors (NullPointerExceptions) and that there are good logging facilities to verify security-relevant events.

For Java Web applications in general, there are several ways to catch exceptions.

 

  • Programmatically:
    1. Use try/catch blocks. try {
    login(username, password);
    } catch (BadLoginException) {

    }
    2. Use the JSP page directive “errorPage”.

    <%@ page errorPage=”bad_login.jsp” %>

  • Declaratively:
    3. In Web.xml, declare error-page and exception type forwards. <error-page>
    <exception-type>
    com.jdjexample.BadLoginException
    </exception-type>
    <location>/bad_login.jsp</location>
    </error-page>
    The Struts framework builds on these methods.

     

  • Programmatically:
    1. Use Action Errors to wrap exceptions. try {
    login(username, password);
    } catch (BadLoginException) {
    ActionErrors errors = new ActionErrors();
    errors.add(“login”, new ActionError(“bad. login”));
    return errors;
    }
    2. Implement processExceptions in RequestProcessor.

    protected ActionForward processException(HttpServ-letRequest request,
    HttpServletResponse response,
    Exception exception,
    ActionForm form,
    ActionMapping mapping)
    throws IOException, ServletException {
    if (exception instanceof BadLoginException) {

    }

  • Declaratively:
    1. Specify action and global exception forwards. <global-exceptions>
    <exception
    key=”bad.login”
    type=”com.jdjexample.BadLoginException”
    handler=”com.jdjexample.BadLoginExceptionHandler”/>
    </global-exceptions>
    Error handling is a vital part of any application robustness and security, and each application must discern requirements about how to deal with errors. Often, these requirements will include logging security relevant errors to provide forensics information after attacks and comply with traceability stipulations in compliance guidelines. Struts lets errors be handled cleanly both in and outside of the code, with multiple points to implement custom code for unique requirements.

    Struts and Cross-Cutting Security Concerns
    Often, applications have security requirements that affect all resources, such as guarantees about privacy, or auditing requirements. Rather than try to apply the correct logic in each individual component, it’s often helpful to have an “intercepting” class that funnels all the invocations and performs a common set of routines. This way, changes to overall functionality can be isolated to a small area. Struts has several different places where cross-cutting security concerns can be implemented, each with its own particular benefits.

    ActionServlet
    ActionServlet is the primary servlet in the Struts framework, and handles all requests to Struts Actions. In Struts 1.0, ActionServlet was the class to extend to change the handling of all requests to actions; however, much of the functionality of ActionServlet was refactored to the RequestProcessor class. This lets sub-application modules handle requests differently and promotes abstraction between the processing of raw HTTP requests and Struts-specific request processing, which should happen in RequestProcessor. Typically ActionServlet should only be extended if other extension points can’t provide the functionality needed.

    RequestProcessor
    The RequestProcessor class is where most of the per-request processing takes place. There are many different methods that can be overridden here, but some have very direct security relevance:

    1. processRoles(): This method should be overridden for any action-level access control that must be programmatic (for instance, if the application doesn’t use JAAS).
    2. processNoCache(): This method should be overridden to tag the response as “no-cache” to avoid security vulnerabilities associated with locally caching content.
    3. processException(): This method should do any special exception handling that can’t be done declaratively.
    4. processValidate(): This method should do any special validation that can’t be done declaratively.

    Obviously, more security concerns can be addressed by extending the RequestProcessor. This is where we see the Struts framework shine, since it lets us easily implement maintainable cross-cutting security mechanisms in our Web applications. However, it’s important to note that any request that doesn’t go through the action/controller servlet (e.g., for a static HTML page, JSP, image/multimedia file, etc.) isn’t intercepted by the RequestProcessor and won’t be subject to these controls (see Servlet Filter if this is a concern). Base Action
    By defining a base Action class that all other actions extend, security concerns can be addressed in the perform method and all other action classes would call the super. The disadvantage here is that all actions must extend this action, but this is a viable alternative to using a request processor.

    Servlet Filter
    The Filter class (javax.servlet.Filter) isn’t Struts-related, but can be used to intercept and handle requests. Servlet Filters have the advantage of intercepting all (or some subset of) requests, not just those based on actions; if this functionality is necessary, then filters may be appropriate. An interesting use of Servlet Filters with respect to security is the security filter project (securityfilter.sourceforge.net) that emulates container-managed security, but alleviates problems with flexibility and portability. However, extending RequestProcessor is typically a cleaner solution because it centralizes the application logic in the Struts framework and requires less maintenance than using two separate libraries.

    Conclusion
    Application security is a problem that affects projects from the business goals down to the code implementation. Despite the increasing amount of knowledge and expertise available to the development community, many homegrown security solutions are used in place of established best practices. The Struts framework offers developers easy and effective security mechanisms that, when applied correctly, can significantly improve an application’s overall security. While this article discusses some common issues, it’s always important to consider unique security requirements and leverage best practices to suit the needs of the project as well as any included frameworks.

  • One thought on “How to Create Secure Web Applications with Struts

    Leave a Reply to Quality post Cancel reply

    Your email address will not be published.

    Click to Insert Smiley

    SmileBig SmileGrinLaughFrownBig FrownCryNeutralWinkKissRazzChicCoolAngryReally AngryConfusedQuestionThinkingPainShockYesNoLOLSillyBeautyLashesCuteShyBlushKissedIn LoveDroolGiggleSnickerHeh!SmirkWiltWeepIDKStruggleSide FrownDazedHypnotizedSweatEek!Roll EyesSarcasmDisdainSmugMoney MouthFoot in MouthShut MouthQuietShameBeat UpMeanEvil GrinGrit TeethShoutPissed OffReally PissedMad RazzDrunken RazzSickYawnSleepyDanceClapJumpHandshakeHigh FiveHug LeftHug RightKiss BlowKissingByeGo AwayCall MeOn the PhoneSecretMeetingWavingStopTime OutTalk to the HandLoserLyingDOH!Fingers CrossedWaitingSuspenseTremblePrayWorshipStarvingEatVictoryCurseAlienAngelClownCowboyCyclopsDevilDoctorFemale FighterMale FighterMohawkMusicNerdPartyPirateSkywalkerSnowmanSoldierVampireZombie KillerGhostSkeletonBunnyCatCat 2ChickChickenChicken 2CowCow 2DogDog 2DuckGoatHippoKoalaLionMonkeyMonkey 2MousePandaPigPig 2SheepSheep 2ReindeerSnailTigerTurtleBeerDrinkLiquorCoffeeCakePizzaWatermelonBowlPlateCanFemaleMaleHeartBroken HeartRoseDead RosePeaceYin YangUS FlagMoonStarSunCloudyRainThunderUmbrellaRainbowMusic NoteAirplaneCarIslandAnnouncebrbMailCellPhoneCameraFilmTVClockLampSearchCoinsComputerConsolePresentSoccerCloverPumpkinBombHammerKnifeHandcuffsPillPoopCigarette