图像

SQL Injection,CSS attacks, Script attacks in Java or J2ee web applications

To Prevent SQL Injection,CSS attacks, Script attackes in Java J2ee based web applicataions we had to add filter which
will inspect each and every field that is submitted to the application.
But be careful as some times this filter may change the values of some inputs.
Eg: In our test app when we added this filter all quotes like say for name was replacye by html equivalent.
The reason is there can be some fields like name say Ram’S (with an apostrophe).The apsotrophe here would be replaced
with its html Equivalent.So one way is not allow user to enter (by haveing validation in UI) or
if you still need to allow then exclude that field from filter.
We had to exclude few fields here for some hidden fields which is used by JSF to maintain state on client side.
The reason was when JSF was storing the client state it had some encrypted striung with quotes and
parenthisis. The filter would think that it was sql attack and would replace the quote with html Equivalent ,
As result JSF decoding of the client state would fail with “StreamCorruptedException”.

package com.connove.dev;

import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

/**
 * This class goes through the Request parameters and looks for any suspicious
 * inputs which could be a SQL injected or some java script some user is trying
 * to inject.
 */


public class SqlAndXSSFilter implements Filter {
  private static Map<String, String> excludeFieldsMap = new HashMap<String, String>();

  public void init(FilterConfig config) throws ServletException {
    // Looking for sql-xss-exclusion-filter.properties
    String propertiesFilePath = config.getInitParameter("properties_file");
    if (propertiesFilePath == null || propertiesFilePath.length() == 0) {
      System.out
          .println("XSS filter (c) Connove mailto:dev@connove.com ver. 1.3");
    } else {

      // If you want to inspect every request parameter
      Properties props = new Properties();
      try {
        props.load(getClass().getClassLoader().getResourceAsStream(
            propertiesFilePath));

        Iterator<Object> itr = props.keySet().iterator();

        while (itr.hasNext()) {
          String key = (String) itr.next();
          String value = (String) props.get(key);
          excludeFieldsMap.put(key, value);
        }

        // Send this map to SqlAndXSSRequestWrapper. I made it
        // static intentionally.
        SqlInjectionAndXSSRequestWrapper.excludeFieldsMap = excludeFieldsMap;

      } catch (IOException e) {
        System.out.println("Could not load properties file: "
            + propertiesFilePath);
      }
    }
  }

  public void destroy() {

  }

  public void doFilter(ServletRequest request, ServletResponse response,
      FilterChain chain) throws IOException, ServletException {

    chain.doFilter(new SqlInjectionAndXSSRequestWrapper(
        (HttpServletRequest) request), response);
  }
}

sql-xss-exclusion-filter.properties
===================================
//Property file with Tokens to be excluded from our filter
//Lets Call this file as sql-xss-exclusion-filter.properties, PUT IN YOUR CLASSPATH

# List of all fields that needs to be excluded from SqlInjectionAndXSSFilter
# Any fields thats not listed here will be inspected by the filter and if
# filter finds any thing suspicious (XSS or SQL attacks code) it will replace
# the contents.

# Let the key and value be same so that we can load into map for easy operations.
# (I love maps for the ease of searching)
# survey
addSurvey=addSurvey
modifySurvey=modifySurvey
addSurveyAsk=addSurveyAsk
modifySurveyAsk=modifySurveyAsk

# article
addArticle=addArticle
modifyArticle=modifyArticle
reCacheArticleClassCommand=reCacheArticleClassCommand
addArticleClass=addArticleClass
modifyArticleClass=modifyArticleClass
delArticleToRecycleBin=delArticleToRecycleBin

# res
modifyRes=modifyRes
addRes=addRes
importRes=importRes

# comment
addCommonComment=addCommonComment
delCommonComment=delCommonComment
modifyCommonCommentGrade=modifyCommonCommentGrade
addCommonCommentGrade=addCommonCommentGrade

# spider
addSpiderRule=addSpiderRule
modifySpiderRule=modifySpiderRule
addDBSpiderTask=addDBSpiderTask
modifyDBSpiderTask=modifyDBSpiderTask

# ad
addAdClass=addAdClass
modifyAdClass=modifyAdClass

# flow
addWorkflow=addWorkflow
modifyWorkflow=modifyWorkflow

# job
addjob=addjob
modifyjob=modifyjob

# other
testGatherSQL=testGatherSQL
addMessage=addMessage

class SqlInjectionAndXSSRequestWrapper defined as below:

package com.connove.dev;

import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

/**
 * Used by the filter to remove any potential code sent as input parameter which
 * has XSS (Cross site scripting) and More at : http://ha.ckers.org/xss.html
 * http://www.symantec.com/connect/articles/
 * detection-sql-injection-and-cross-site-scripting-attacks
 *
 */


public class SqlInjectionAndXSSRequestWrapper extends HttpServletRequestWrapper {

  // The filter will set this map

  public static Map<String, String> excludeFieldsMap = new HashMap<String, String>();

  public SqlInjectionAndXSSRequestWrapper(HttpServletRequest servletRequest) {

    super(servletRequest);

  }

  public String[] getParameterValues(String parameter) {

    String[] values = super.getParameterValues(parameter);

    if (values == null) {

      return null;

    }

    int count = values.length;

    String[] encodedValues = new String[count];

    for (int i = 0; i < count; i++) {

      encodedValues[i] = replaceXSSAndSqlInjection(values[i], parameter);

    }
    return encodedValues;
  }

  public String getParameter(String parameter) {

    String value = super.getParameter(parameter);

    if (value == null) {

      return null;

    }

    return replaceXSSAndSqlInjection(value, parameter);
  }

  public String getHeader(String name) {

    String value = super.getHeader(name);

    if (value == null) {

      return null;

    }

    return replaceXSSAndSqlInjection(value, name);

  }

  /**
   *
   * If its finds any XSS injection it will replace the values with html
   * equivalent and and for SQL injection it will replace few sql key words
   * (insert, delete...etc)
   *
   * @param value
   * @return
   */


  public static String replaceXSSAndSqlInjection(String value,
      String fieldName) {

    // The key and value will be same

    // Eg:jsf_tree_64=jsf_tree_64 - See sql-xss-exclusion-filter.properties

    // SO here we ignore any fields that we feel should not be inspeacted by
    // this filter..

    String fieldToExclude = excludeFieldsMap.get(fieldName);

    if ((fieldToExclude != null)
        && (fieldToExclude.equalsIgnoreCase(fieldName))) {

      return value;

    }

    String orgValue = new String(value);

    // No < and > as it could be for some sql.

    value = value.replaceAll("<", "&lt;").replaceAll(">", "&gt;");

    // No () brackets as part of data....

    value = value.replaceAll("\\(", "&#40;").replaceAll("\\)", "&#41;");

    // Handle any apostrophe. Can a name have this ??

    value = value.replaceAll("'", "&#39;");

    // Any java script stuff.

    value = value.replaceAll("eval\\((.*)\\)", "");

    value = value.replaceAll("[\\\"\\'][\\s]*javascript:(.*)[\\\"\\']",
        "\"\"");

    value = value.replaceAll("script", "");

    /*
     *
     * This signature first looks out for the = sign or its hex equivalent
     * (%3D). It then allows for zero or more non-newline characters, and
     * then it checks for the single-quote, the double-dash or the
     * semi-colon. Detect either the hex equivalent of the single-quote, the
     * single-quote itself or the presence of the double-dash. These are SQL
     * characters for MS SQL Server and Oracle, which denote the beginning
     * of a comment, and everything that follows is ignored. See more info
     * at
     * http://www.symantec.com/connect/articles/detection-sql-injection-and
     * -cross-site-scripting-attacks Regex for detecting SQL Injection
     * meta-characters
     */


    value = value.replaceAll(
        "/((\\%3D)|(=))[^\\n]*((\\%27)|(\')|(\\-\\-)|(\\%3B)|(;))/i",
        "");

    /*
     *
     * Regex for detecting SQL Injection with the UNION keyword
     *
     * (\%27)|(\') - the single-quote and its hex equivalent union - the
     * keyword union
     */


    value = value.replaceAll("/((\\%27)|(\'))union/ix", "");

    /*
     *
     *
     *
     * A typical SQL injection attempt of course revolves around the use of
     * the single quote to manipulate the original query so that it always
     * results in a true value. Most of the examples that discuss this
     * attack use the string 1'or'1'='1. However, detection of this string
     * can be easily evaded by supplying a value such as 1'or2>1--. Thus the
     * only part that is constant in this is the initial alphanumeric value,
     * followed by a single-quote, and then followed by the word 'or'. The
     * Boolean logic that comes after this may be varied to an extent where
     * a generic pattern is either very complex or does not cover all the
     * variants. Thus these attacks can be detected to a fair degree of
     * accuracy by using the next regular expression
     *
     * Regex for typical SQL Injection attack
     *
     * /\w*((\%27)|(\'))((\%6F)|o|(\%4F))((\%72)|r|(\%52))/ix
     */


    value = value
        .replaceAll(
            "/\\w*((\\%27)|(\'))((\\%6F)|o|(\\%4F))((\\%72)|r|(\\%52))/ix",
            "");

    // checking for the keywords and a combination of quotes with
    // conjunctions and quotes with double pipe (||)

    value = value
        .replaceAll(
            "insert|update|delete|having|drop|(\'|%27).(and|or).(\'|%27)|(\'|%27).%7C{0,2}|%7C{2}",
            "");

    // Regex for "<img src" CSS attack
    value = value
        .replaceAll(
            "/((\\%3C)|<)((\\%69)|i|(\\%49))((\\%6D)|m|(\\%4D))((\\%67)|g|(\\%47))[^\n]+((\\%3E)|>)/I",
            "");
    return value;

  }
}

In your web.xml now configure the filter

<filter>
    <filter-name>SqlAndXSSFilter</filter-name>
    <filter-class>com.connove.dev.SqlAndXSSFilter</filter-class>
    <init-param>
      <param-name>properties_file</param-name>
      <param-value>sql-xss-exclusion-filter.properties</param-value>
    </init-param>
  </filter>

  <filter-mapping>
    <filter-name>SqlAndXSSFilter</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
  </filter-mapping>

You now try to enter some value in text fields on the UI in your application. The filter will intercept and
replace the html equivalent.So if you don’t want a field to be intercepted you can add those fields
in sql-xss-exclusion-filter.properties

Hope this helps.

发表评论