[风一样的创作]防XSS注入攻击

一.首先大概理解下什么是XSS注入攻击

XSS注入攻击本质上就是通过你服务本身的接口把一些HTML,CSS,JS,SQL语句等内容存储进你的服务里面,一般是数据库里面,这时候就可以通过这些存储进去的内容拿取到一些你的数据库隐藏内容或者破坏你的页面排版,比如乱弹窗。

二.解决的方法

首先声明,解决方案不止这一种,这只是最简单的一种

1.使用拦截器拦截所有请求,一定要在最顶层
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Controller;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 自拟定springmvc拦截器,解决不用nginx情况下的cors跨域问题
 */
@Order(-100)    //拦截器级别,越小越在前面
@Controller
@ServletComponentScan
@WebFilter(urlPatterns = "/*", filterName = "shiroLoginFilter")
public class ShiroLoginFilter implements Filter {

    /**
     *  程序启动的时候调用
     *
     * @param filterConfig
     * @throws ServletException
     */
    @Override
    public void init(FilterConfig filterConfig) {
        System.out.println("程序启动");
    }

    /**
     * 每次请求访问时调用
     *
     * @param servletRequest
     * @param servletResponse
     * @param chain
     * @throws IOException
     * @throws ServletException
     */
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        // 允许哪些Origin发起跨域请求
        String orgin = request.getHeader("Origin");
        response.setHeader("Access-Control-Allow-Origin", orgin);
        // 允许请求的请求类型
        response.setHeader("Access-Control-Allow-Methods", "POST,GET,OPTIONS,DELETE,PUT");
        //多少秒内,不需要再发送预检验请求,可以缓存该结果
        response.setHeader("Access-Control-Max-Age", "3600");
        //表明它允许跨域请求头中有哪些参数
        response.setHeader("Access-Control-Allow-Headers", "x-auth-token,Origin,Access-Token,X-Requested-With,Content-Type,Accept,token");
        //是否允许浏览器携带用户身份信息(cookie)
        response.setHeader("Access-Control-Allow-Credentials", "true");
        //cors试探性请求,拦截到OPTIONS类型请求,直接返回结果
        String urlType = request.getMethod();
        if (urlType.equals("OPTIONS")) {
            response.setStatus(200);
            return;
        }

        //不进行XSS攻击处理的接口(一般都是要用到富文本的接口),只是不用过滤HTML字符
        List<String> urlList=new ArrayList<>();
        urlList.add("/assess/addAssessUser");
        urlList.add("/article/addJournalism");
        urlList.add("/article/updateArticle");
        urlList.add("/course/addCourse");
        urlList.add("/course/updateCourse");
        urlList.add("/course_chapters/updateCourseChapters");
        urlList.add("/course_chapters/addCourseChapters");
        urlList.add("/competitionTitbits/updateCompetitionTitbitsOne");
        urlList.add("/competitionTitbits/addCompetitionTitbitsOne");
        urlList.add("/user/addUser");
        urlList.add("/user/updateUser");
        urlList.add("/text/addText");
        urlList.add("/text/updateText");
        urlList.add("/practice_finance/addOrUpdatePracticeFinanceSystem");
        urlList.add("/practice_structure/addOrUpdatePracticeStructureSynopsis");
        //判断当前接口是要进行XSS攻击处理的还是不要的(在不过滤列表里面有就是不过滤,没有则要过滤),只是不用过滤HTML字符
        if(urlList.stream().filter(data -> data.equals(request.getRequestURI())).collect(Collectors.toList()).isEmpty()){
            XssHttpServletRequestWrapper.HTML_TYPE = true;
            XssHttpServletRequestWrapper.SQL_TYPE = true;
        }else {
            XssHttpServletRequestWrapper.HTML_TYPE = false;
            XssHttpServletRequestWrapper.SQL_TYPE = true;
        }
        //处理XSS攻击(其实就是SQL和HTML/CSS/JS注入攻击),方法是重写HttpServletRequest这些请求实体类的参数过滤规则,然后替换掉原生默认的
        XssHttpServletRequestWrapper xssHttpServletRequestWrapper=new XssHttpServletRequestWrapper(request);
        chain.doFilter(xssHttpServletRequestWrapper, response);
    }

    /**
     * 程序关闭的时候调用
     */
    @Override
    public void destroy() {
        System.out.println("程序关闭");
    }
}
2.自拟定XSS过滤工具

其实就是拿取所有的request对象里面的参数,进行过滤,去除一些关键字,转义一些特殊字符

import org.thymeleaf.util.StringUtils;

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

public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
    //要过滤数据库SQL的关键字
    private final static String key = "and|exec|insert|select|delete|update|count|chr|mid|master|truncate|char|declare|or";
    private static Set<String> notAllowedKeyWords = new HashSet<String>(0);
    //SQL过滤到要加的标记文字
    private static String replacedString = "INVALID";
    //是否要过滤HTML符号
    public static Boolean HTML_TYPE = true;
    //是否要过滤SQL关键字
    public static Boolean SQL_TYPE = true;

    static {
        String keyStr[] = key.split("\\|");
        for (String str : keyStr) {
            notAllowedKeyWords.add(str);
        }
    }

    private String currentUrl;

    public XssHttpServletRequestWrapper(HttpServletRequest servletRequest) {
        super(servletRequest);
        currentUrl = servletRequest.getRequestURI();
    }


    /**
     * 覆盖getParameter方法,将参数名和参数值都做xss过滤。
     * 如果需要获得原始的值,则通过super.getParameterValues(name)来获取
     * getParameterNames,getParameterValues和getParameterMap也可能需要覆盖
     */
    @Override
    public String getParameter(String parameter) {
        String value = super.getParameter(parameter);
        if (value == null) {
            return null;
        }
        return cleanXSS(value);
    }

    @Override
    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] = cleanXSS(values[i]);
        }
        return encodedValues;
    }

    @Override
    public Map<String, String[]> getParameterMap() {
        Map<String, String[]> values = super.getParameterMap();
        if (values == null) {
            return null;
        }
        Map<String, String[]> result = new HashMap<>();
        for (String key : values.keySet()) {
            String encodedKey = cleanXSS(key);
            int count = values.get(key).length;
            String[] encodedValues = new String[count];
            for (int i = 0; i < count; i++) {
                encodedValues[i] = cleanXSS(values.get(key)[i]);
            }
            result.put(encodedKey, encodedValues);
        }
        return result;
    }

    /**
     * 覆盖getHeader方法,将参数名和参数值都做xss过滤。
     * 如果需要获得原始的值,则通过super.getHeaders(name)来获取
     * getHeaderNames 也可能需要覆盖
     */
    @Override
    public String getHeader(String name) {
        String value = super.getHeader(name);
        if (value == null) {
            return null;
        }
        return cleanXSS(value);
    }

    /**
     * 过滤HTML,CSS,JS中的一些特殊字符,比如 <> () '
     *
     * @param valueP
     * @return
     */
    private String cleanXSS(String valueP) {
        String value = valueP;
        //判断是否过滤HTML字符,是则过滤
        if(HTML_TYPE){
            value = value.replaceAll("<", "&lt;").replaceAll(">", "&gt;");
            value = value.replaceAll("<", "&lt;").replaceAll(">", "&gt;");
            value = value.replaceAll("\\(", "&#40;").replaceAll("\\)", "&#41;");
            value = value.replaceAll("'", "&#39;");
            value = value.replaceAll("eval\\((.*)\\)", "");
            value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\"");
            value = value.replaceAll("alert", "");
        }
        //判断是否过滤SQL关键字,是则过滤
        if(SQL_TYPE){
            value = cleanSqlKeyWords(value);
        }
        return value;
    }

    /**
     * 过滤SQL关键字
     *
     * @param value
     * @return
     */
    private String cleanSqlKeyWords(String value) {
        String paramValue = value;
        if (value.indexOf("q=0.01") == -1) {
            for (String keyword : notAllowedKeyWords) {
                if (paramValue.length() > keyword.length() + 4 && (paramValue.contains(" " + keyword) || paramValue.contains(keyword + " ") || paramValue.contains(" " + keyword + " "))) {
                    paramValue = StringUtils.replace(paramValue, keyword, replacedString);
                }
            }
        }
        return paramValue;
    }

}

三.一些过滤以后会出现的问题

1.比如我碰见的layui富文本就会出现转义以后的字符回显在富文本不会回显样式的问题,暂时没有好的解决方案

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
一、什么是XSS攻击 XSS是一种经常出现在web应用中的计算机安全漏洞,它允许恶意web用户将代码植入到提供给其它用户使用的页面中。比如这些代码包括HTML代码和客户端脚本。攻击者利用XSS漏洞旁路掉访问控制——例如同源策略(same origin policy)。这种类型的漏洞由于被黑客用来编写危害性更大的网络钓鱼(Phishing)攻击而变得广为人知。对于跨站脚本攻击,黑客界共识是:跨站脚本攻击是新型的“缓冲区溢出攻击“,而JavaScript是新型的“ShellCode”。 二、XSS漏洞的危害 (1)网络钓鱼,包括盗取各类用户账号; (2)窃取用户cookies资料,从而获取用户隐私信息,或利用用户身份进一步对网站执行操作; (3)劫持用户(浏览器)会话,从而执行任意操作,例如进行非法转账、强制发表日志、发送电子邮件等; (4)强制弹出广告页面、刷流量等; (5)网页挂马; (6)进行恶意操作,例如任意篡改页面信息、删除文章等; (7)进行大量的客户端攻击,如DDoS攻击; (8)获取客户端信息,例如用户的浏览历史、真实IP、开放端口等; (9)控制受害者机器向其他网站发起攻击; (10)结合其他漏洞,如CSRF漏洞,实施进一步作恶; (11)提升用户权限,包括进一步渗透网站; (12)传播跨站脚本蠕虫等; 三、过滤器配置 web.xml配置 XssFilter com.xxx.Filter.XssFilter XssFilter /*

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

风一样的码农

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值