使用过滤器解决xss攻击、SQL注入问题,自定义注解+aop+反射解决xss攻击问题

一、过滤器和拦截器的区别:

不同点:

    过滤器的执行顺序在拦截前

    过滤器基于servlet,而拦截器是基于框架,springmvc

    过滤器是基于函数回调,而拦截器是基于Java的反射机制

参考博客:https://blog.csdn.net/zxd1435513775/article/details/80556034

二、基于过滤器解决xss问题

(1)、什么是xss问题

  xss问题就是脚本攻击,是指在参数中携带一些script脚本等能在HTML执行的脚本,从而呈现在html页面的脚本被执行导致的结果

(2)解决xss问题 使用过滤器,对每个参数进行参数转化

代码:test1部分

package com.junlaninfo.filter;

import org.apache.commons.lang3.StringEscapeUtils;

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

/**
 * Created by 辉 on 2020/6/5.
 自定义拦截器
 */
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
    public XssHttpServletRequestWrapper(HttpServletRequest request) {
        super(request);
    }

    @Override
    public String getParameter(String name) {
        String oldValue = super.getParameter(name);
        if (oldValue == null) {
            return oldValue;
        }
        String s = StringEscapeUtils.escapeHtml4(oldValue);
        return s ;
    }
}
package com.junlaninfo.filter;


import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

/**
 * Created by 辉 on 2020/6/5.
   注入自定义拦截器
 */
@Component
@WebFilter
public class TestFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
        chain.doFilter(new XssHttpServletRequestWrapper((HttpServletRequest) servletRequest), servletResponse);
    }

    @Override
    public void destroy() {

    }
}

三、自定义注解+aop+反射解决xss问题

代码:test2部分

(1)、自定义注解,定义三个注解,分别作用在方法上、参数上、属性上

package com.junlaninfo.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @Description: 注解在方法上,表示该方法中的参数需要预防XSS
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface PreventXSSMethod {

}

 

package com.junlaninfo.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @Description: 注解在参数上,表示该参数需要预防XSS
 */
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface PreventXSSParameter {
}
package com.junlaninfo.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @Description: 注解在属性上,表示该字段需要预防XSS
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface PreventXSSField {

}

(2)aop

package com.junlaninfo.aop;

import com.junlaninfo.annotation.PreventXSSField;
import com.junlaninfo.annotation.PreventXSSMethod;
import com.junlaninfo.annotation.PreventXSSParameter;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;

/**
 * @Description: AOP防XSS攻击
 */
@Aspect
@Component
public class PreventXSSAspect {

    /**
     * 拦截controller路径下所有类的所有方法
     */
    @Pointcut("execution(* com.junlaninfo.controller.*.*(..))")
    public void pointCut() {}

    @Around("pointCut() && @annotation(preventXSSMethod)")
    public Object around(ProceedingJoinPoint joinPoint, PreventXSSMethod preventXSSMethod) throws Throwable {
        Object[] args = joinPoint.getArgs();
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        // 获取所有参数上的注解(一个参数可能对应多个注解,因此获取到的是一个二维数组。)
        Annotation[][] paramsAnnotations = signature.getMethod().getParameterAnnotations();
        // 遍历一维数组,获取每个参数对应的注解数组
        for (int i = 0; i < paramsAnnotations.length; i++) {
            Annotation[] paramAnnotations = paramsAnnotations[i];
            // 遍历每个参数的注解数组
            for (Annotation annotation: paramAnnotations) {
                // 如果参数需要预防XSS攻击
                if (annotation instanceof PreventXSSParameter){
                    // 如果是String类型,将其进行格式化
                    // 否则获取该类型的所有字段,对String类型的字段进行格式化
                    if (args[i] instanceof String && StringUtils.isNotEmpty((String) args[i])) {
                        args[i] = format((String) args[i]);
                    } else {
                        Class clazz = args[i].getClass();
                        // 获取类的所有字段
                        Field[] fields = clazz.getDeclaredFields();
                        for (Field field: fields) {
                            // 如果字段上有@PreventXSSField注解
                            if (field.getDeclaredAnnotation(PreventXSSField.class) != null) {
                                // 如果是字段不可访问,设置临时可访问
                                if (!field.isAccessible())
                                    field.setAccessible(true);
                                // 如果字段是字符串类型则进行格式化
                                Object fieldValue = field.get(args[i]);
                                if (fieldValue instanceof String && StringUtils.isNotEmpty((String) fieldValue))
                                    field.set(args[i], format((String) fieldValue));
                            }
                        }
                    }
                }
            }
        }
        // 将参数覆盖到到原方法
        Object proceed = joinPoint.proceed(args);
        return proceed;
    }

    /**
     * 对需要防范的字符串进行格式化
     */
    public String format(String xssStr) {
        return StringEscapeUtils.escapeHtml4(xssStr);
    }
}

(2)entity

package com.junlaninfo.entity;

import com.junlaninfo.annotation.PreventXSSField;

/**
 * Created by 辉 on 2020/6/5.
 */
public class user {
    private String username;

    private String password;

    @PreventXSSField
    private String nickname;
    @PreventXSSField
    private String description;

    public user() {
    }

    public user(String username, String password, String nickname, String description) {
        this.username = username;
        this.password = password;
        this.nickname = nickname;
        this.description = description;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getNickname() {
        return nickname;
    }

    public void setNickname(String nickname) {
        this.nickname = nickname;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
}

(3)controller层

package com.junlaninfo.controller;

import com.junlaninfo.*;
import com.junlaninfo.annotation.PreventXSSMethod;
import com.junlaninfo.annotation.PreventXSSParameter;
import com.junlaninfo.entity.user;
import org.springframework.stereotype.Controller;


import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

/**
 * Created by 辉 on 2020/6/5.
 */
@Controller
public class indecController {
    @GetMapping("/")
    public String register() {
        return "register";
    }

    @PreventXSSMethod
    @PostMapping("/info")
    public String info(@PreventXSSParameter  user user, Model model) {
        model.addAttribute("user", user);
        return "user";
    }
}

(4)ftl

register.ftl

<html>
<head>
    <title>注册页面</title>
</head>
<body>
<form action="/info" method="post">
    用户名:<input type="text" name="username">
    密码:<input type="text" name="password">
    昵称:<input type="text" name="nickname">
    描述:<input type="text" name="description">
    <input type="submit" value="提交">
</form>
</body>
</html>

 

user.ftl

<html>
<head>
    <title>用户展示页面</title>
</head>
<body>
<p>用户名:${user.username}</p>
<p>密码:${user.password}</p>
<p>昵称:${user.nickname}</p>
<p>描述:${user.description}</p></body>
</html>

注意:测试过,我的理解是xss攻击只存在不是前后端分离的项目中,真正前后端分离的项目是不存在xss问题,因为返回的数据都是json格式,有不同的见解欢迎指正

四、使用过滤器解决SQL注入的问题

(1)什么是SQL注入

就是用户在输入内容的时候,在SQL拼接的过程中,导致变成了另外一条SQL语句,且新的SQL语句即使输入的内容不正确,但是这条SQL语句是可以正常执行的


例如:  

原SQL语句拼接为: 

	String sql = "select id from user15 where username='"+user.getUserName()+"' and password='"+user.getPassWord()+"'";
	
用户输入的帐号密码分别为:

请输入您的帐号:
suibian
请输入您的密码:
suibian' or '1'='1
组成的SQL语句: 
select id from user15 where username='suibian' and password='suibian' or '1'='1'

(2)SQL注入问题的解决

 使用filter过滤器

 预编译

(3)使用filter解决SQL注入的问题

代码:test3

package com.jualninfo.filter;

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

public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {

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

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

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


        //You'll need to remove the spaces from the html entities below
        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("script", "");
        value = value.replaceAll("[*]","["+"*]");
        value = value.replaceAll("[+]","["+"+]");
        value = value.replaceAll("[?]","["+"?]");
        // replace sql 这里可以自由发挥
        String[] values = value.split(" ");

        String badStr = "'|and|exec|execute|insert|select|delete|update|count|drop|%|chr|mid|master|truncate|" +
                "char|declare|sitename|net user|xp_cmdshell|;|or|-|+|,|like'|and|exec|execute|insert|create|drop|" +
                "table|from|grant|use|group_concat|column_name|" +
                "information_schema.columns|table_schema|union|where|select|delete|update|order|by|count|" +
                "chr|mid|master|truncate|char|declare|or|;|-|--|,|like|//|/|%|#";

        String[] badStrs = badStr.split("\\|");
        for (int i = 0;i<badStrs.length;i++){
            for (int j = 0;j<values.length;j++){
                if (values[j].equalsIgnoreCase(badStrs[i])){
                    values[j] = "forbid";
                }
            }
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0;i<values.length;i++){
            if (i == values.length-1){
                sb.append(values[i]);
            } else {
                sb.append(values[i]+" ");
            }
        }

        value = sb.toString();

        return value;
    }

}

 

package com.jualninfo.filter;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

@WebFilter(urlPatterns = "/*")
@Component
public class XssFilter implements Filter {

    private static final Logger logger = LoggerFactory.getLogger(XssFilter.class);

    FilterConfig filterConfig = null;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        this.filterConfig = filterConfig;
    }

    @Override
    public void destroy() {
        this.filterConfig = null;
    }

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

        logger.info("自定义过滤器->doFilter");

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

(4)预编译

在传入参数的时候,不要使用  $(),使用#(),预编译

代码链接:https://gitee.com/xuexionghui/SecurityTest.git

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
一、什么是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 /*

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值