fr.paris.lutece.util.http.SecurityUtil.java Source code

Java tutorial

Introduction

Here is the source code for fr.paris.lutece.util.http.SecurityUtil.java

Source

/*
 * Copyright (c) 2002-2013, Mairie de Paris
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *  1. Redistributions of source code must retain the above copyright notice
 *     and the following disclaimer.
 *
 *  2. Redistributions in binary form must reproduce the above copyright notice
 *     and the following disclaimer in the documentation and/or other materials
 *     provided with the distribution.
 *
 *  3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
 *     contributors may be used to endorse or promote products derived from
 *     this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * License 1.0
 */
package fr.paris.lutece.util.http;

import fr.paris.lutece.util.string.StringUtil;

import org.apache.commons.lang.StringUtils;

import org.apache.log4j.Logger;

import java.util.Enumeration;

import javax.servlet.http.HttpServletRequest;

/**
 * Security utils
 *
 */
public final class SecurityUtil {
    private static final String LOGGER_NAME = "lutece.security.http";
    private static final String CONSTANT_HTTP_HEADER_X_FORWARDED_FOR = "X-Forwarded-For";
    private static final String PATTERN_IP_ADDRESS = "^([0-9]{1,3}\\.){3}[0-9]{1,3}$";
    private static final String CONSTANT_COMMA = ",";

    //private static final String PATTERN_CLEAN_PARAMETER = "^[\\w/]+$+";

    /**
     * Private Constructor
     */
    private SecurityUtil() {
    }

    /**
     * Scan request parameters to see if there no malicious code.
     *
     * @param request The HTTP request
     * @return true if all parameters don't contains any special characters
     */
    public static boolean containsCleanParameters(HttpServletRequest request) {
        return containsCleanParameters(request, null);
    }

    /**
     * Scan request parameters to see if there no malicious code.
     *
     * @param request The HTTP request
     * @param strXssCharacters a String wich contain a list of Xss characters to check in strValue
     * @return true if all parameters don't contains any special characters
     */
    public static boolean containsCleanParameters(HttpServletRequest request, String strXssCharacters) {
        String key;
        String[] values;

        Enumeration<String> e = request.getParameterNames();

        while (e.hasMoreElements()) {
            key = e.nextElement();
            values = request.getParameterValues(key);

            int length = values.length;

            for (int i = 0; i < length; i++) {
                if (SecurityUtil.containsXssCharacters(request, values[i], strXssCharacters)) {
                    Logger logger = Logger.getLogger(LOGGER_NAME);
                    logger.warn("SECURITY WARNING : INVALID REQUEST PARAMETERS" + dumpRequest(request));

                    return false;
                }
            }
        }

        return true;
    }

    /**
     * Checks if a String contains characters that could be used for a
     * cross-site scripting attack.
     *
     * @param request The HTTP request
     * @param strString a character String
     * @return true if the String contains illegal characters
     */
    public static boolean containsXssCharacters(HttpServletRequest request, String strString) {
        return containsXssCharacters(request, strString, null);
    }

    /**
     * Checks if a String contains characters that could be used for a
     * cross-site scripting attack.
     *
     * @param request The HTTP request
     * @param strValue a character String
     * @param strXssCharacters a String wich contain a list of Xss characters to check in strValue
     * @return true if the String contains illegal characters
     */
    public static boolean containsXssCharacters(HttpServletRequest request, String strValue,
            String strXssCharacters) {
        boolean bContains = (strXssCharacters == null) ? StringUtil.containsXssCharacters(strValue)
                : StringUtil.containsXssCharacters(strValue, strXssCharacters);

        if (bContains) {
            Logger logger = Logger.getLogger(LOGGER_NAME);
            logger.warn("SECURITY WARNING : XSS CHARACTERS DETECTED" + dumpRequest(request));
        }

        return bContains;
    }

    /**
     * Dump all request info
     * @param request The HTTP request
     * @return A report containing all request info
     */
    public static String dumpRequest(HttpServletRequest request) {
        StringBuffer sbDump = new StringBuffer("\r\n Request Dump : \r\n");
        dumpTitle(sbDump, "Request variables");
        dumpVariables(sbDump, request);
        dumpTitle(sbDump, "Request parameters");
        dumpParameters(sbDump, request);
        dumpTitle(sbDump, "Request headers");
        dumpHeaders(sbDump, request);

        return sbDump.toString();
    }

    /**
     * Get the IP of the user from a request. If the user is behind an apache
     * server, return the ip of the user instead of the ip of the server.
     * @param request The request
     * @return The IP of the user that made the request
     */
    public static String getRealIp(HttpServletRequest request) {
        String strIPAddress = request.getHeader(CONSTANT_HTTP_HEADER_X_FORWARDED_FOR);

        if (strIPAddress != null) {
            String strIpForwarded = null;

            while (!strIPAddress.matches(PATTERN_IP_ADDRESS) && strIPAddress.contains(CONSTANT_COMMA)) {
                strIpForwarded = strIPAddress.substring(0, strIPAddress.indexOf(CONSTANT_COMMA));
                strIPAddress = strIPAddress.substring(strIPAddress.indexOf(CONSTANT_COMMA))
                        .replaceFirst(CONSTANT_COMMA, StringUtils.EMPTY).trim();

                if ((strIpForwarded != null) && strIpForwarded.matches(PATTERN_IP_ADDRESS)) {
                    strIPAddress = strIpForwarded;
                }
            }

            if (!strIPAddress.matches(PATTERN_IP_ADDRESS)) {
                strIPAddress = request.getRemoteAddr();
            }
        } else {
            strIPAddress = request.getRemoteAddr();
        }

        return strIPAddress;
    }

    /**
     * Write a title into the dump stringbuffer
     * @param sbDump The dump stringbuffer
     * @param strTitle The title
     */
    private static void dumpTitle(StringBuffer sbDump, String strTitle) {
        sbDump.append("** ");
        sbDump.append(strTitle);
        sbDump.append("  **\r\n");
    }

    /**
     * Write request variables into the dump stringbuffer
     * @param sb The dump stringbuffer
     * @param request The HTTP request
     */
    private static void dumpVariables(StringBuffer sb, HttpServletRequest request) {
        dumpVariable(sb, "AUTH_TYPE", request.getAuthType());
        dumpVariable(sb, "REQUEST_METHOD", request.getMethod());
        dumpVariable(sb, "PATH_INFO", request.getPathInfo());
        dumpVariable(sb, "PATH_TRANSLATED", request.getPathTranslated());
        dumpVariable(sb, "QUERY_STRING", request.getQueryString());
        dumpVariable(sb, "REQUEST_URI", request.getRequestURI());
        dumpVariable(sb, "SCRIPT_NAME", request.getServletPath());
        dumpVariable(sb, "LOCAL_ADDR", request.getLocalAddr());
        dumpVariable(sb, "SERVER_PROTOCOL", request.getProtocol());
        dumpVariable(sb, "REMOTE_ADDR", request.getRemoteAddr());
        dumpVariable(sb, "REMOTE_HOST", request.getRemoteHost());
        dumpVariable(sb, "HTTPS", request.getScheme());
        dumpVariable(sb, "SERVER_NAME", request.getServerName());
        dumpVariable(sb, "SERVER_PORT", String.valueOf(request.getServerPort()));
    }

    /**
     * Write request headers infos into the dump stringbuffer
     * @param sb The dump stringbuffer
     * @param request The HTTP request
     */
    private static void dumpHeaders(StringBuffer sb, HttpServletRequest request) {
        Enumeration<String> values;
        String key;
        Enumeration<String> headers = request.getHeaderNames();

        while (headers.hasMoreElements()) {
            key = headers.nextElement();
            values = request.getHeaders(key);

            while (values.hasMoreElements()) {
                dumpVariable(sb, key, values.nextElement());
            }
        }
    }

    /**
     * Write request parameters infos into the dump stringbuffer
     * @param sb The dump stringbuffer
     * @param request The HTTP request
     */
    private static void dumpParameters(StringBuffer sb, HttpServletRequest request) {
        String key;
        String[] values;

        Enumeration<String> e = request.getParameterNames();

        while (e.hasMoreElements()) {
            key = e.nextElement();
            values = request.getParameterValues(key);

            int length = values.length;

            for (int i = 0; i < length; i++) {
                dumpVariable(sb, key, values[i]);
            }
        }
    }

    /**
     * Write name / value infos into the dump stringbuffer
     * @param sb The dump string buffer
     * @param strName The info name
     * @param strValue The info value
     */
    private static void dumpVariable(StringBuffer sb, String strName, String strValue) {
        sb.append(strName);
        sb.append(" : \"");
        sb.append(strValue);
        sb.append("\"\r\n");
    }
}