OWASP Stinger Manual

From OWASP
Revision as of 19:27, 24 September 2006 by Esheridan (Talk | contribs)

Jump to: navigation, search

Contents

Overview

The purpose of the OWASP Stinger manual is to provide users a comprehensive guide to developing upon and deploying the OWASP J2EE Stinger filter. If you have any comments or suggestions concerning the Stinger manual, please to not hesitate to email me at eric.sheridan@owasp.org.

Development

Deployment

Fetch the Latest Files

The latest Stinger release can be downloaded [TBD here]. The deployer should download the jar file into a directory accessible by the Java container. For example, deploying Stinger in Tomcat would require downloading the files in the WEB-INF/lib/ directory.

Configure Deployment Descriptor

There are two major pieces of information necessary to deploy Stinger in your J2EE environment. First, the Java container must be told to implement the Stinger J2EE filter. This is specified in the web.xml file via the following:

<filter>
	<filter-name>StingerFilter</filter-name>
	<filter-class>org.owasp.stinger.StingerFilter</filter-class>
	<init-param>
		<param-name>config</param-name>
		<param-value>C:\stinger.xml</param-value>
	</init-param>
	<init-param>
		<param-name>errmsg</param-name>
		<param-value>A serious error has occurred</param-value>
	</init-param>
	<init-param>
		<param-name>reload</param-name>
		<param-value>true</param-value>
	</init-param>
</filter>

Stinger 2.0 accepts three filter parameters: config, errmsg, and reload. The config parameter tells the Stinger filter the location of the SVDL file. The errmsg parameter is actually the result of a new feature in Stinger 2.0. All exceptions that are thrown from the web application are now caught in Stinger. This prevents sending exceptions to the client and potentially revealing sensitive information (think database exceptions). Instead of leaking sensitive information, Stinger simply writes a message to the client upon catching an exception. The errmsg parameter specifies the message that will be displayed to the user. The third parameter, reload, tells Stinger whether to dynamically load the SVDL file for each incoming HTTP request. As a rule of thumb, set reload to true in testing environments and false for production environments.

The second major piece of information dictates which requests should pass the Stinger J2EE filter. This is specified in the web.xml file via the following:

<filter-mapping>
	<filter-name>StingerFilter</filter-name>
	<url-pattern>/*</url-pattern>
</filter-mapping>

This entry tells the J2EE container that every request handled by the container should pass through the Stinger filter.

Configure Your SVDL File

A template SVDL file for the latest Stinger release can be found [TBD here]. The SVDL file is broken down into three sections.

  • The Regular Expression Section
  • The Cookie Rule Section
  • The Parameter Rule Section

The Regular Expression Section

All regular expressions to be used in Stinger are defined in this section. Essentially, a regular expression entry is comprised of a name, a regular expression, and a description. The description element is for user readability and is not used within Stinger. The regular expressions equiped with Stinger were taken from the [TBD OWASP RegEx Repository]. If you have custom regular expressions and would like to donate them to the Stinger project, please email me at eric.sheridan@owasp.org.

The following is a sample entry in the regular expression section:

<regex>
	<name>JSESSIONID</name>
	<pattern>^[A-F0-9]{32}$</pattern>
	<description>JSESSIONID character and length enforcement</description>
</regex>

The Cookie Rule Section

This section contains definitions for all of the cookies for which we are assigning a rule. A cookie rule is comprised of a name, a regular expression, the URI in which it is created, the URI's which it is enforced, and the actions taken if the cookie is missing or malformed. For most web applications, we wish to create and enforce a cookie for a particular URI. In this case, we have an entry similar to the one found below. In this case the following rule applies: if a cookie is missing from the request sent to the created/enforced URI, then no violation occurs. However, if a cookis is malformed in the request sent to the created/enforced URI, then a violation occurs.

The missing and malformed sections simply specify the severity of the violation as well as the actions to be executed. There exists three possible severities: FATAL, CONTINUE, and IGNORE.

  • If a severity is FATAL, then Stinger stops processing the packet and immediately executes the associated actions.
  • If a severity is CONTINUE, then Stinger appends the violation a list and continues to process the packet.
  • If a severity is IGNORE, no violation is appended to the list of violation and Stinger continues its request validation.

Several actions accept parameters which are designated by the <parameter> tag.

The following is a sample entry in the cookie rule section:

<cookie>
	<name>JSESSIONID</name>
	<regex>JSESSIONID</regex>
	<created>/Stinger-2.0-Lite</created>
	<enforce>/Stinger-2.0-Lite</enforce>
	<enforce>/Stinger-2.0-Lite/</enforce>
	<enforce>/Stinger-2.0-Lite/index.html</enforce>
	<missing>
		<severity>FATAL</severity>
		<action class="org.owasp.stinger.actions.Log">
			<parameter>
				<name>log</name>
				<value>default.log</value>
			</parameter>
			<parameter>
				<name>level</name>
				<value>SEVERE</value>
			</parameter>
			<parameter>
				<name>message</name>
				<value>
					The required JSESSIONID cookie is missing
				</value>
			</parameter>
		</action>
		<action class="org.owasp.stinger.actions.Invalidate" />
		<action class="org.owasp.stinger.actions.ClearCookies" />
		<action class="org.owasp.stinger.actions.Redirect">
			<parameter>
				<name>page</name>
				<value>error.html</value>
			</parameter>
		</action>
	</missing>
	<malformed>
		<severity>FATAL</severity>
		<action class="org.owasp.stinger.actions.Log">
			<parameter>
				<name>log</name>
				<value>default.log</value>
			</parameter>
			<parameter>
				<name>level</name>
				<value>SEVERE</value>
			</parameter>
			<parameter>
				<name>message</name>
				<value>The JSESSIONID cookie is malformed</value>
			</parameter>
		</action>
		<action class="org.owasp.stinger.actions.Invalidate" />
		<action class="org.owasp.stinger.actions.ClearCookies" />
		<action class="org.owasp.stinger.actions.Redirect">
			<parameter>
				<name>page</name>
				<value>error.html</value>
			</parameter>
		</action>
	</malformed>
</cookie>

The Parameter Section

The parameter section describes the parameter rules associated with a particular URI. A uri and it's associated rules constitute a rule set. Every SVDL implementation must contain a default rule set similar to the following:

<ruleset>
	<name>STINGER_DEFAULT</name>
	<path>STINGER_DEFAULT</path>
	<rule>
		<name>STINGER_ALL</name>
		<regex>safetext</regex>

		<missing>
			<severity>ignore</severity>
		</missing>
		<malformed>
			<severity>continue</severity>
			<action class="org.owasp.stinger.actions.Log">
				<parameter>
					<name>log</name>
					<value>default.log</value>
				</parameter>
				<parameter>
					<name>level</name>
					<value>info</value>
				</parameter>
				<parameter>
					<name>message</name>
					<value>
						parameter %name with value %value from %ip
						has been sanitized
					</value>
				</parameter>
			</action>
                       <action class="org.owasp.stinger.actions.Sanitize" />
              </malformed>
	</rule>
</ruleset>

A default Stinger rule set must have the path (the URI) set to STINGER_DEFAULT and the rule name set to STINGER_ALL. When a request to a URI without an associated rule set is submitted, the default rule set is utitlized. When a parameter without an associated rule is sent to the application, then the default rules are utilized.

The following is a sample rule set entry for a ficticious web application:

<ruleset>
	<name>Main</name>
	<path>/Stinger-2.0-Lite</path>
	<path>/Stinger-2.0-Lite/</path>
	<path>/Stinger-2.0-Lite/index.jsp</path>

	<rule>
		<name>username</name>
		<regex>safetext</regex>

		<missing>
			<severity>continue</severity>
			<action
				class="org.owasp.stinger.actions.DisplayMessage">
				<parameter>
					<name>message</name>
					<value>
						The required username parameter is missing
					</value>
				</parameter>
				<parameter>
					<name>bgcolor</name>
					<value>yellow</value>
				</parameter>
			</action>
		</missing>
		<malformed>
			<severity>continue</severity>
			<action class="org.owasp.stinger.actions.Log">
				<parameter>
					<name>log</name>
					<value>default.log</value>
				</parameter>
				<parameter>
					<name>level</name>
					<value>info</value>
				</parameter>
				<parameter>
					<name>message</name>
					<value>
						The username parameter from %ip is malformed
					</value>
				</parameter>
			</action>
			<action class="org.owasp.stinger.actions.Sanitize" />
		</malformed>
	</rule>
	<rule>
		<name>hidden1</name>
		<regex>safetext</regex>

		<missing>
			<severity>fatal</severity>
			<action class="org.owasp.stinger.actions.Log">
				<parameter>
					<name>log</name>
					<value>default.log</value>
				</parameter>
				<parameter>
					<name>level</name>
					<value>info</value>
				</parameter>
				<parameter>
					<name>message</name>
					<value>The hidden1 parameter is missing</value>
				</parameter>
			</action>
			<action class="org.owasp.stinger.actions.Invalidate" />
			<action class="org.owasp.stinger.actions.Redirect">
				<parameter>
					<name>page</name>
					<value>error.html</value>
				</parameter>
			</action>
		</missing>
		<malformed>
			<severity>fatal</severity>
			<action class="org.owasp.stinger.actions.Log">
				<parameter>
					<name>log</name>
					<value>default.log</value>
					</parameter>
				<parameter>
					<name>level</name>
					<value>SEVERE</value>
				</parameter>
                               <parameter>
  				        <name>message</name>
					<value>
						hidden1 parameter from %ip is malformed
					</value>
                               </parameter>
			</action>
			<action class="org.owasp.stinger.actions.Invalidate" />
			<action class="org.owasp.stinger.actions.Redirect">
                               <parameter>
					<name>page</name>
					<value>error.html</value>
				</parameter>
			</action>
		</malformed>
	</rule>
</ruleset>

Although this entry is quite large, there are only a few new entries which must be noted. As we see, this rule set applies to several paths:

  • /Stinger-2.0-Lite
  • /Stinger-2.0-Lite/
  • /Stinger-2.0-Lite/index.jsp.

For this rule set, we have specified two rules, each describing a parameter accepted by the web application. These two parameters, username and hidden1, have very similar entries to that of the cookie rules. Each parameter has an associated regular expression, a missing section, and a malformed section.

SVDL Generator

Obviously, generating a SVDL file for your application can be quite tedious. In an effort to reduce this overhead, Stinger 2.0 is equiped with an SVDL Generator file. Essentially, this filter will allow you to manually browser your web application and specify rules for every parameter. The SVDL Generator filter is designed to modify the HTML of every response coming from your web application. When the filter see's a parameter without an associated rule, then it colors the parameter red and applys an AJAX style javascript menu. This menu contains all of the possible regular expressions specified in the template SVDL file for Stinger. When a user see's the red parameter, then can right click the parameter and specify a regular expression. The parameter color is changed back to normal to signify that a rule now exists and the request is sent to the SVDL Generator filter via an XMLHttpRequest object.

To deploy the SVDL Generator Filter, insert the following in your web.xml file:

<filter>
	<filter-name>SVDLGeneratorFilter</filter-name>
	<filter-class>org.owasp.stinger.SVDLGeneratorFilter</filter-class>
	<init-param>
		<param-name>config</param-name>
		<param-value>stinger.xml</param-value>
	</init-param>
</filter>

<filter-mapping>
	<filter-name>SVDLGeneratorFilter</filter-name>
	<url-pattern>/*</url-pattern>
</filter-mapping>

The SVDL Generator filter accepts a config parameter which points to the location of a template SVDL file. A template SVDL file is considered an SVDL file with a regular expression section and a default rule set entry. A template SVDL file can be downloaded [TBD here].

Deployment Checklist

  • Download the latest Stinger jar files into the appropriate container directory
  • Configure your web.xml file to:
Load Stinger with the appropriate parameters:
config - the location of the SVDL file
errmsg - the error message displayed if any exception is caught
reload - specifies whether the SVDL should be dynamically loaded at runtime
Apply Stinger to a URI Pattern
  • Configure the SVDL for your application

Actions

Stinger is an action based input validation engine. The user can specify actions to be taken place upon violations found in an HTTP request. The following section describes how the actions are implemented as well as the parameters they accept. One major goal of this section is to illustrate the simplicity of creating Stinger actions. If you have created a custom action and are interested in submitting it to the Stinger project, please email me at eric.sheridan@owasp.org.

AbstractAction

Description

Developing your own action is relatively straight forward within Stinger. To implement a custom class, simply extend the AbstractAction class and implement the abstract doAction method. For more information related to building custom actions, please refer to the development section.

Source Code

public abstract class AbstractAction {
	
	private HashMap<String, String> parameters = new HashMap<String, String>();
	
	public String getParameter(String name) {
		return parameters.get(name);
	}
	
	public void setParameter(String name, String value) {
		parameters.remove(name);
		parameters.put(name, value);
	}
	
	public abstract void doAction(Violation violation, MutableHttpRequest request, 
                                     MutableHttpResponse response) throws  BreakChainException;
}

ClearCookies

Description

As the name implies, the ClearCookies action will set the maximum age of every cookie in the request to 0; effectively clearing all cookies for the session.

Parameters

The ClearCookies action currently does not accept any parameters.

Source Code

public class ClearCookies extends AbstractAction {
	
	public void doAction(Violation violation, MutableHttpRequest request, MutableHttpResponse response) {
		Cookie[] cookies = null;
		
		cookies = request.getCookies();
		
		if(cookies != null) {
			for(int i=0; i<cookies.length; i++) {
				cookies[i].setMaxAge(0);
			}
		}
	}
}

DisplayMessage

Description

When a violation occurs, the DisplayMessage action can be configured to display a custom message to the user. This message currently resides at the top of the response in an HTML table format.

Parameters

The DisplayMessage action currently accepts two parameters.

message - the message to be displayed back to the user upon finding a violation
bgcolor - the background color of the HTML table

Source Code

public class DisplayMessage extends AbstractAction {
	
	public String formatMessage(String message, String bgcolor) {
		StringBuffer buffer = new StringBuffer();
		
		buffer.append("<table width=300 border=1 align=center bgcolor=" + bgcolor + " cellpadding=2\n");
		buffer.append("<tr><td>\n");
		buffer.append("<div align=\"center\" >" + message + "</div>\n");
		buffer.append("</td></tr></table>\n");
		
		return buffer.toString();
	}
	
	public void displayMessage(MutableHttpResponse response, String message, String bgcolor) {
		PrintWriter out = null;
		String formatedMessage = formatMessage(message, bgcolor);
		
		out = response.getWriter();
		out.write(formatedMessage);
	}
	
	public void doAction(Violation violation, MutableHttpRequest request, MutableHttpResponse response) {
		String message = getParameter("message");
		String bgcolor = getParameter("bgcolor");
		
		displayMessage(response, message, bgcolor);
	}
}

Drop

Description

The Drop action simply throws the BreakChainException when called. This effectively prevents the HTTP request from ever reaching the web application.

Parameters

The Drop action currently accepts one parameter:

message - the message to be displayed in the exception stack trace. This message is never displayed to the user.

Source Code

public class Drop extends AbstractAction {
	
	public void doAction(Violation violation, MutableHttpRequest request,
                            MutableHttpResponse response) throws  BreakChainException {
		String message = getParameter("message");
		
		/** Let the user define the message to be displayed in the exception **/
		throw new BreakChainException(message);
	}
}

Invalidate

Description

If the session object exists, then it will be invalidated by this action. This action is considered more severe and should be deployed only when an obvious attack occurs. For example, cookie values are rarely tampered with by the client side code (i.e. javascript). Therefore, we can (safely?) assume that any cookie modification is considered a deliberate attack.

Parameters

The Invalidate action currently accepts no parameters.

Source Code

public class Invalidate extends AbstractAction {
	
	public void doAction(Violation violation, MutableHttpRequest request, MutableHttpResponse response) {
		HttpSession session = null;
		
		session = request.getSession(false);
		
		if(session != null) {
			session.invalidate();
		}
	}
}

Log

Description

As the name implies, we can log any and every request sent to the web application. The Log action is an essential action and should be heavily implemented in Stinger deployment.

Parameters

The Log action currently accepts 3 parameters:

log - the log file where the message should be recorded
level - the level of the log message (i.e. INFO, SEVERE, etc.)
message - the message which shall be logged. The message parameter itself accepts 3 format parameters.
          These include the offender's ip address, the offender's remote port, the parameter/cookie name,
          the parameter/cookie value, and the JSESSIONID. The format strings are %ip, %port, %name, %value, %js respectively.

Source Code

public class Log extends AbstractAction {
	
	private static Logger logger = Logger.getLogger("org.owasp.stinger.actions.Log");
	
	private static HashMap<String, FileHandler> handlers = new HashMap<String, FileHandler>();
	
	public Log() {
		
	}
	
	public void doAction(Violation violation, MutableHttpRequest request, MutableHttpResponse response) {
		FileHandler handler = null;
		String log = getParameter("log");
		String level = getParameter("level");
		String message = getParameter("message");
		
		/** Offender's IP **/
		message = message.replace("%ip", request.getRemoteAddr());
		/** Offender's Port **/
		message = message.replace("%port", String.valueOf(request.getRemotePort()));
		/** Offending parameter name **/
		if(violation.getName() != null) {
			message = message.replace("%name", violation.getName());
		} else {
			message = message.replace("%name", "NULL");
		}
		/** Offending parameter value **/
		if(violation.getValue() != null) {
			message = message.replace("%value", violation.getValue());
		} else {
			message = message.replace("%value", "NULL");
		}
		/** Offender's JSESSIONID **/
		if(request.getCookie("JSESSIONID") != null) {
 			message = message.replace("%js", request.getCookie("JSESSIONID").getValue());
		} else {
			message = message.replace("%js", "NULL");
		}
		
		handler = getHandler(log);
		logger.addHandler(handler);
		
		logger.log(Level.parse(level.toUpperCase()), message);
		handler.flush();
		
		logger.removeHandler(handler);
	}
	
	private synchronized FileHandler getHandler(String log) {
		FileHandler handler = null;
		
 		handler = handlers.get(log);
		
		if(handler == null) {
			try {
				handler = new FileHandler(log);
			} catch (IOException ioe) {
				ioe.printStackTrace();
			}
			
			handlers.put(log, handler);
		}
		
		return handler;
	}
}

Redirect

Description

The Redirect action redirects a user to a specific page. This action is often used to send a user to an error message upon finding a violation.

Parameters

The Redirect action currently accepts 1 parameter:

page - the page to redirect the user to

Source Code

public class Redirect extends AbstractAction {
	
	public void doAction(Violation violation, MutableHttpRequest request,
                            MutableHttpResponse response) throws  BreakChainException {
		String page = getParameter("page");
		
		try {
			response.sendRedirect(page);
		} catch (IOException ioe) {
			ioe.printStackTrace();
		}
	}
}

Feedback and Participation

We hope you find Stinger useful. Please contribute back to the project by sending your comments, questions, and suggestions to the Stinger mailing list. Thanks!

To join the OWASP Stinger mailing list or view the archives, please visit the subscription page.

Project Sponsors

The Stinger project is sponsored by aspect_logo.gif.