JFinal如何进行XSS攻击过滤

为啥要做XSS过滤?
比如一个文本框, 正常来说应该是输入普通文本,但是如果有it基础尤其是前端js比较熟悉的童鞋,就可以在这里面写js代码和html代码如下:
这里写图片描述

这还只是普通的代码, 如果可以他能写一个死循环一直弹窗,让你不得不去数据库更改这个数据.
这里写图片描述

我现在用到的是JBoot框架, 于是就需要用JFinal来解决这个问题
JBoot的web.xml文件中,配置过滤器

 <filter>
        <filter-name>jfinal</filter-name>
        <filter-class>com.jfinal.core.JFinalFilter</filter-class>
        <init-param>
            <param-name>configClass</param-name>
            <init-param>
            <param-name>configClass</param-name>
            <!-- <param-value>io.jboot.web.JbootAppConfig</param-value> -->
            <param-value>com.hz.shop.api.gateway.config.XssConfig</param-value>
        </init-param>
        </init-param>
    </filter>

这里我自己定义了一个XssConfig类, 继承了JbootAppConfig, JbootAppConfig又继承了JFinalConfig, 实现了5个方法

  /**
     * Config constant
     */
    public abstract void configConstant(Constants me);

    /**
     * Config route
     */
    public abstract void configRoute(Routes me);

    /**
     * Config plugin
     */
    public abstract void configPlugin(Plugins me);

    /**
     * Config interceptor applied to all actions.
     */
    public abstract void configInterceptor(Interceptors me);

    /**
     * Config handler
     */
    public abstract void configHandler(Handlers me);

JbootAppConfig已经帮我们实现了这5个方法,我们只专注于configHandler(Handlers me)这个方法

package com.hz.shop.api.gateway.config;

import com.hz.shop.api.gateway.handler.XssHandler;
import com.jfinal.config.Handlers;

import io.jboot.web.JbootAppConfig;

public class XssConfig extends JbootAppConfig {


    /* 
     * 配置处理器
     * 添加我们自己的handler
     */
    @Override
    public void configHandler(Handlers handlers) {
        handlers.add(new XssHandler());
        super.configHandler(handlers);
    }

}

这里我们需要再写一个XssHandler, 它继承了Jfinal的Handler

package com.hz.shop.api.gateway.handler;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.jfinal.handler.Handler;

/**
 * 自己定义的处理器
 * @author Admin
 */
public class XssHandler extends Handler{


    @Override
    public void handle(String target, HttpServletRequest request, HttpServletResponse response, boolean[] isHandled) {
        request = new XssRequestWrapper(request);
         next.handle(target, request, response, isHandled);
    }

}

这里我们需要再定义一个自己的RequestWrapper类,它继承了HttpServletRequestWrapper ,在这个类中, 我们对request中的获取参数方法进行重写, 获得我们需要的, 安全的参数

package com.hz.shop.api.gateway.handler;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.logging.Logger;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

public class XssRequestWrapper extends HttpServletRequestWrapper {

    private HttpServletRequest request;

    public XssRequestWrapper(HttpServletRequest request) {
        super(request);
        this.request = request;
    }

    /**
     * 重写getParameter方法
     */
    @Override
    public String getParameter(String name) {
        String value = super.getParameter(name);
        if (value == null) {
            return null;
        }
        value = format(value);
        return value;
    }

    /**
     * 重写getParameterMap
     */
    @Override
    @SuppressWarnings("unchecked")
    public Map<String, String[]> getParameterMap() {
        HashMap<String, String[]> paramMap = (HashMap<String, String[]>) super.getParameterMap();
        paramMap = (HashMap<String, String[]>) paramMap.clone();

        for (Iterator iterator = paramMap.entrySet().iterator(); iterator.hasNext(); ) {
            Map.Entry<String, String[]> entry = (Map.Entry<String, String[]>) iterator.next();
            String [] values = entry.getValue();
            for (int i = 0; i < values.length; i++) {
                if(values[i] instanceof String){
                    values[i] = format(values[i]);
                }
            }
            entry.setValue(values);
        }
        return paramMap;
    }


    /**
     * 重写getParameterValues
     */
    @Override
    public String[] getParameterValues(String name) {
         String[] values = super.getParameterValues(name);  
         int count = values.length;  
            String[] encodedValues = new String[count];  
            for (int i = 0; i < count; i++) {  
                encodedValues[i] = format(values[i]);  
            }  
        return encodedValues;  
    }

    /**
     * 重写getHeader
     */
    @Override
    public String getHeader(String name) {
        // TODO Auto-generated method stub
        return format(super.getHeader(name));
    }


    public String filter(String message) {
        if (message == null)
            return (null);
        message = format(message);
        return message;
    }


     /**
     *  @desc 统一处理特殊字符的方法,替换掉sql和js的特殊字符
     *  @param name 要替换的字符
     */
    private String format(String name) {
        return xssEncode(name);
    }

    /** 
     * 将容易引起xss & sql漏洞的半角字符直接替换成全角字符 
     *  
     * @param s 
     * @return 
     */  
    private static String xssEncode(String s) {  
        if (s == null || s.isEmpty()) {  
            return s;  
        }else{  
            s = stripXSSAndSql(s);  
        }  
        StringBuilder sb = new StringBuilder(s.length() + 16);  
        for (int i = 0; i < s.length(); i++) {  
            char c = s.charAt(i);  
            switch (c) {  
            case '>':  
                sb.append(">");// 转义大于号  
                break;  
            case '<':  
                sb.append("<");// 转义小于号  
                break;  
            case '\'':  
                sb.append("'");// 转义单引号  
                break;  
            case '\"':  
                sb.append(""");// 转义双引号  
                break;  
            case '&':  
                sb.append("&");// 转义&  
                break;  
            case '#':  
                sb.append("#");// 转义#  
                break;  
            default:  
                sb.append(c);  
                break;  
            }  
        }  
        return sb.toString();  
    }  



    /** 
     *  
     * 防止xss跨脚本攻击(替换,根据实际情况调整) 
     */  
    public static String stripXSSAndSql(String value) {  
        if (value != null) {  
            // NOTE: It's highly recommended to use the ESAPI library and  
            // uncomment the following line to  
            // avoid encoded attacks.  
//             value = ESAPI.encoder().canonicalize(value);  
            // Avoid null characters  
/**         value = value.replaceAll("", "");***/  
            // Avoid anything between script tags  
            Pattern scriptPattern = Pattern.compile("<[\r\n| | ]*script[\r\n| | ]*>(.*?)</[\r\n| | ]*script[\r\n| | ]*>", Pattern.CASE_INSENSITIVE);  
            value = scriptPattern.matcher(value).replaceAll("");  
            // Avoid anything in a src="http://www.yihaomen.com/article/java/..." type of e-xpression  
            scriptPattern = Pattern.compile("src[\r\n| | ]*=[\r\n| | ]*[\\\"|\\\'](.*?)[\\\"|\\\']", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);  
            value = scriptPattern.matcher(value).replaceAll("");  
            // Remove any lonesome </script> tag  
            scriptPattern = Pattern.compile("</[\r\n| | ]*script[\r\n| | ]*>", Pattern.CASE_INSENSITIVE);  
            value = scriptPattern.matcher(value).replaceAll("");  
            // Remove any lonesome <script ...> tag  
            scriptPattern = Pattern.compile("<[\r\n| | ]*script(.*?)>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);  
            value = scriptPattern.matcher(value).replaceAll("");  
            // Avoid eval(...) expressions  
            scriptPattern = Pattern.compile("eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);  
            value = scriptPattern.matcher(value).replaceAll("");  
            // Avoid e-xpression(...) expressions  
            scriptPattern = Pattern.compile("e-xpression\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);  
            value = scriptPattern.matcher(value).replaceAll("");  
            // Avoid javascript:... expressions  
            scriptPattern = Pattern.compile("javascript[\r\n| | ]*:[\r\n| | ]*", Pattern.CASE_INSENSITIVE);  
            value = scriptPattern.matcher(value).replaceAll("");  
            // Avoid vbscript:... expressions  
            scriptPattern = Pattern.compile("vbscript[\r\n| | ]*:[\r\n| | ]*", Pattern.CASE_INSENSITIVE);  
            value = scriptPattern.matcher(value).replaceAll("");  
            // Avoid onload= expressions  
            scriptPattern = Pattern.compile("onload(.*?)=", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);  
            value = scriptPattern.matcher(value).replaceAll("");  
        }  
        return value;  
    }  


}

上面的正则匹配过滤规则,可以根据自己的需求而定
这里写图片描述
现在script标签直接被替换为"",英文的引号,小括号,都被替换成中文的,所以不会被识别成代码

猜你喜欢

转载自blog.csdn.net/zzzgd_666/article/details/80356266