BadInputFilterValvepublic class BadInputFilterValve extends org.apache.catalina.valves.RequestFilterValve Filters out bad user input from HTTP requests to avoid malicious
attacks including Cross Site Scripting (XSS), SQL Injection, and
HTML Injection vulnerabilities, among others. |
Fields Summary |
---|
protected static String | infoDescriptive information about this implementation. | protected boolean | escapeQuotesThe flag that determines whether or not to escape quotes that are
part of the request. | protected boolean | escapeAngleBracketsThe flag that determines whether or not to escape angle brackets
that are part of the request. | protected boolean | escapeJavaScriptThe flag that determines whether or not to escape JavaScript
function and object names that are part of the request. | protected HashMap | quotesHashMapA substitution mapping (regular expression to match, replacement)
that is used to replace single quotes (') and double quotes (")
with escaped equivalents that can't be used for malicious purposes. | protected HashMap | angleBracketsHashMapA substitution mapping (regular expression to match, replacement)
that is used to replace angle brackets (<>) with escaped
equivalents that can't be used for malicious purposes. | protected HashMap | javaScriptHashMapA substitution mapping (regular expression to match, replacement)
that is used to replace potentially dangerous JavaScript function
calls with escaped equivalents that can't be used for malicious
purposes. | protected int | debugThe debug level. |
Constructors Summary |
---|
public BadInputFilterValve()Construct a new instance of this class with default property values.
super();
// Populate the (regex, substitution) maps.
quotesHashMap.put("\"", """);
quotesHashMap.put("\'", "'");
quotesHashMap.put("`", "`");
angleBracketsHashMap.put("<", "<");
angleBracketsHashMap.put(">", ">");
javaScriptHashMap.put(
"document(.*)\\.(.*)cookie", "document.cookie");
javaScriptHashMap.put("eval(\\s*)\\(", "eval(");
javaScriptHashMap.put("setTimeout(\\s*)\\(", "setTimeout$1(");
javaScriptHashMap.put("setInterval(\\s*)\\(", "setInterval$1(");
javaScriptHashMap.put("execScript(\\s*)\\(", "exexScript$1(");
javaScriptHashMap.put("javascript:", "javascript:");
|
Methods Summary |
---|
public boolean | checkAllowsAndDenies(java.lang.String property, org.apache.catalina.Request request, org.apache.catalina.Response response, org.apache.catalina.ValveContext valveContext)Perform the filtering that has been configured for this Valve, matching
against the specified request property. If the request is allowed to
proceed, this method returns true. Otherwise, this method sends
a Forbidden error response page, and returns false.
This method borrows heavily from RequestFilterValve.process(),
only this method has a boolean return type and doesn't call
valveContext.invokeNext().
// Check the deny patterns, if any
for (int i = 0; i < denies.length; i++) {
if (denies[i].match(property)) {
ServletResponse sres = response.getResponse();
if (sres instanceof HttpServletResponse) {
HttpServletResponse hres = (HttpServletResponse) sres;
hres.sendError(HttpServletResponse.SC_FORBIDDEN);
return false;
}
}
}
// Check the allow patterns, if any
for (int i = 0; i < allows.length; i++) {
if (allows[i].match(property)) {
return true;
}
}
// Allow if denies specified but not allows
if ((denies.length > 0) && (allows.length == 0)) {
return true;
}
// Deny this request
ServletResponse sres = response.getResponse();
if (sres instanceof HttpServletResponse) {
HttpServletResponse hres = (HttpServletResponse) sres;
hres.sendError(HttpServletResponse.SC_FORBIDDEN);
}
return false;
| public void | filterParameters(java.util.HashMap subs, org.apache.catalina.Request request)Filters all existing parameters for potentially dangerous content,
and escapes any if they are found.
ParameterMap paramMap =
(ParameterMap) ((HttpServletRequest) request).getParameterMap();
// Unlock the parameters map so we can modify the parameters.
paramMap.setLocked(false);
try {
// Loop through each of the substitution patterns.
Iterator x = subs.keySet().iterator();
while (x.hasNext()) {
String pattern = (String) x.next();
RE r = new RE(pattern);
// Loop through the list of parameters.
Iterator y = paramMap.keySet().iterator();
while (y.hasNext()) {
String name = (String) y.next();
String[] values = ((HttpServletRequest)
request).getParameterValues(name);
// See if the name contains the pattern.
boolean nameMatch;
synchronized (r) {
nameMatch = r.match(name);
}
if (nameMatch) {
// The parameter's name matched a pattern, so we
// fix it by modifying the name, adding the parameter
// back as the new name, and removing the old one.
String newName;
synchronized (r) {
newName = r.subst(name,
(String) subs.get(pattern));
}
((HttpRequest) request).addParameter(newName, values);
paramMap.remove(name);
log("Parameter name " + name +
" matched pattern \"" + pattern +
"\". Remote addr: " +
((HttpServletRequest) request).getRemoteAddr());
}
// Check the parameter's values for the pattern.
if (values != null) {
for (int i = 0; i < values.length; i++) {
String value = values[i];
boolean valueMatch;
synchronized (r) {
valueMatch = r.match(value);
}
if (valueMatch) {
// The value matched, so we modify the value
// and then set it back into the array.
String newValue;
synchronized (r) {
newValue = r.subst(value,
(String) subs.get(pattern));
}
values[i] = newValue;
((HttpRequest) request).addParameter(
name, values);
log("Parameter \"" + name + "\"'s value \"" +
value + "\" matched pattern \"" +
pattern + "\". Remote addr: " +
((HttpServletRequest)
request).getRemoteAddr());
}
}
}
}
}
}
catch (Exception e) {
e.printStackTrace();
}
finally {
// Make sure the parameters map is locked again when we're done.
paramMap.setLocked(true);
}
| public boolean | getEscapeAngleBrackets()Gets the flag which determines whether this Valve will escape
any angle brackets that are part of the request, before the
request is performed.
return escapeAngleBrackets;
| public boolean | getEscapeJavaScript()Gets the flag which determines whether this Valve will escape
any potentially dangerous references to JavaScript functions
and objects that are part of the request, before the request is
performed.
return escapeJavaScript;
| public boolean | getEscapeQuotes()Gets the flag which determines whether this Valve will escape
any quotes (both double and single quotes) that are part of the
request, before the request is performed.
// ------------------------------------------------------------- Properties
return escapeQuotes;
| public java.lang.String | getInfo()Return descriptive information about this Valve implementation.
return info;
| public void | invoke(org.apache.catalina.Request request, org.apache.catalina.Response response, org.apache.catalina.ValveContext valveContext)Sanitizes request parameters before bad user input gets into the
web application.
// Skip logging for non-HTTP requests and responses.
if (!(request instanceof HttpRequest) ||
!(response instanceof HttpResponse)) {
valveContext.invokeNext(request, response);
return;
}
// Only let requests through based on the allows and denies.
if (denies.length > 0 || allows.length > 0) {
if (processAllowsAndDenies(request, response, valveContext)) {
// Filter the input for potentially dangerous JavaScript
// code so that bad user input is cleaned out of the request
// by the time Tomcat begins to perform the request.
HashMap parameterEscapes = new HashMap();
if (escapeQuotes) {
// Escape all quotes.
parameterEscapes.putAll(quotesHashMap);
}
if (escapeAngleBrackets) {
// Escape all angle brackets.
parameterEscapes.putAll(angleBracketsHashMap);
}
if (escapeJavaScript) {
// Escape potentially dangerous JavaScript method calls.
parameterEscapes.putAll(javaScriptHashMap);
}
filterParameters(parameterEscapes, request);
// Perform the request.
valveContext.invokeNext(request, response);
}
}
| protected void | log(java.lang.String message)Log the specified message to our current Logger (if any).
Logger logger = container.getLogger();
if (logger != null)
logger.log(this.toString() + ": " + message);
else
System.out.println(this.toString() + ": " + message);
| public boolean | processAllowsAndDenies(org.apache.catalina.Request request, org.apache.catalina.Response response, org.apache.catalina.ValveContext valveContext)Uses the functionality of the (abstract) RequestFilterValve to
stop requests that contain forbidden string patterns in parameter
names and parameter values.
ParameterMap paramMap =
(ParameterMap) ((HttpServletRequest) request).getParameterMap();
// Loop through the list of parameters.
Iterator y = paramMap.keySet().iterator();
while (y.hasNext()) {
String name = (String) y.next();
String[] values = ((HttpServletRequest)
request).getParameterValues(name);
// See if the name contains a forbidden pattern.
if (!checkAllowsAndDenies(name, request, response,
valveContext)) {
return false;
}
// Check the parameter's values for the pattern.
if (values != null) {
for (int i = 0; i < values.length; i++) {
String value = values[i];
if (!checkAllowsAndDenies(value, request, response,
valveContext)) {
return false;
}
}
}
}
// The request should continue.
return true;
| public void | setDebug(int debug)Set the debugging detail level for this Valve.
this.debug = debug;
| public void | setEscapeAngleBrackets(boolean escapeAngleBrackets)Sets the flag which determines whether this Valve will escape
any angle brackets that are part of the request, before the
request is performed.
this.escapeAngleBrackets = escapeAngleBrackets;
| public void | setEscapeJavaScript(boolean escapeJavaScript)Sets the flag which determines whether this Valve will escape
any potentially dangerous references to JavaScript functions
and objects that are part of the request, before the request is
performed.
this.escapeJavaScript = escapeJavaScript;
| public void | setEscapeQuotes(boolean escapeQuotes)Sets the flag which determines whether this Valve will escape
any quotes (both double and single quotes) that are part of the
request, before the request is performed.
this.escapeQuotes = escapeQuotes;
| public java.lang.String | toString()Return a text representation of this object.
return ("BadInputFilterValve[container=" + container.getName() + ']");
|
|