SpringCloud微服务-实现XSS、SQL注入拦截

SQL注入是常见的系统安全问题之一,用户通过特定方式向系统发送SQL脚本,可直接自定义操作系统数据库,如果系统没有对SQL注入进行拦截,那么用户甚至可以直接对数据库进行增删改查等操作。

XSS全称为Cross Site Script跨站点脚本攻击,和SQL注入类似,都是通过特定方式向系统发送攻击脚本,对系统进行控制和侵害。SQL注入主要以攻击数据库来达到攻击系统的目的,而XSS则是以恶意执行前端脚本来攻击系统。

项目框架中使用mybatis/mybatis-plus数据持久层框架,在使用过程中,已有规避SQL注入的规则和使用方法。但是在实际开发过程中,由于各种原因,开发人员对持久层框架的掌握水平不同,有些特殊业务情况必须从前台传入SQL脚本。这时就需要对系统进行加固,防止特殊情况下引起的系统风险。

在微服务架构下,我们考虑如何实现SQL注入/XSS攻击拦截时,肯定不会在每个微服务都实现一遍SQL注入/XSS攻击拦截。根据我们微服务系统的设计,所有的请求都会经过Gateway网关,所以在实现时就可以参照前面的日志拦截器来实现。在接收到一个请求时,通过拦截器解析请求参数,判断是否有SQL注入/XSS攻击参数,如果有,那么返回异常即可。

我们前面在对微服务Gateway进行自定义扩展时,增加了Gateway插件功能。我们会根据系统需求开发各种Gateway功能扩展插件,并且可以根据系统配置文件来启用/禁用这些插件。下面我们就将防止SQL注入/XSS攻击拦截器作为一个Gateway插件来开发和配置

处理方法 :
新增SqlInjectionFilter 过滤器和XssInjectionFilter过滤器,分别用于解析请求参数并对参数进行判断是否存在SQL注入/XSS攻脚本。此处有公共判断方法,通过配置文件来读取请求的过滤配置,因为不是多有的请求都会引发SQL注入和XSS攻击,如果无差别的全部拦截和请求,那么势必影响到系统的性能。

1.首先新建 CacheBodyGlobalFilter.java

这个过滤器解决body不能重复读的问题(在低版本的spring-cloud不需要这个过滤器),为后续的XssRequestGlobalFilter重写请求body做准备。

package com.zhdj.gateway.filter;

import com.zhdj.gateway.utils.WebFluxUtils;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * 全局缓存获取body请求数据(解决流不能重复读取问题)
 *
 * @author Lion Li
 */
@Component
public class GlobalCacheRequestFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 只缓存json类型请求
        if (!WebFluxUtils.isJsonRequest(exchange)) {
            return chain.filter(exchange);
        }
        return ServerWebExchangeUtils.cacheRequestBody(exchange, (serverHttpRequest) -> {
            if (serverHttpRequest == exchange.getRequest()) {
                return chain.filter(exchange);
            }
            return chain.filter(exchange.mutate().request(serverHttpRequest).build());
        });
    }

    @Override
    public int getOrder() {
        return Ordered.HIGHEST_PRECEDENCE + 1;
    }
}

2.XSS跨站脚本配置

package com.zhdj.gateway.config.properties;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Configuration;

import java.util.ArrayList;
import java.util.List;

/**
 * XSS跨站脚本配置
 *
 * @author ruoyi
 */
@Data
@Configuration
@RefreshScope
@ConfigurationProperties(prefix = "security.xss")
public class XssProperties {
    /**
     * Xss开关
     */
    private Boolean enabled;

    /**
     * 排除路径
     */
    private List<String> excludeUrls = new ArrayList<>();

}

3.Sql注入配置

package com.zhdj.gateway.config.properties;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Configuration;

import java.util.ArrayList;
import java.util.List;

/**
 * Sql注入
 *
 * @author ruoyi
 */
@Data
@Configuration
@RefreshScope
@ConfigurationProperties(prefix = "security.sql")
public class SqlProperties {
    /**
     * Sql开关
     */
    private Boolean enabled;

    /**
     * 排除路径
     */
    private List<String> excludeUrls = new ArrayList<>();

}

4.跨站脚本过滤器

package com.zhdj.gateway.filter;

import cn.hutool.http.HtmlUtil;
import com.zhdj.common.core.utils.StringUtils;
import com.zhdj.gateway.config.properties.XssProperties;
import com.zhdj.gateway.utils.WebFluxUtils;
import io.netty.buffer.ByteBufAllocator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.*;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;

/**
 * 跨站脚本过滤器
 *
 * @author ruoyi
 */
@Component
@ConditionalOnProperty(value = "security.xss.enabled", havingValue = "true")
public class XssFilter implements GlobalFilter, Ordered {
    // 跨站脚本的 xss 配置,nacos自行添加
    @Autowired
    private XssProperties xss;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        // GET DELETE 不过滤
        HttpMethod method = request.getMethod();
        if (method == null || method == HttpMethod.GET || method == HttpMethod.DELETE) {
            return chain.filter(exchange);
        }
        // 非json类型,不过滤
        if (!WebFluxUtils.isJsonRequest(exchange)) {
            return chain.filter(exchange);
        }
        // excludeUrls 不过滤
        String url = request.getURI().getPath();
        if (StringUtils.matches(url, xss.getExcludeUrls())) {
            return chain.filter(exchange);
        }
        ServerHttpRequestDecorator httpRequestDecorator = requestDecorator(exchange);
        return chain.filter(exchange.mutate().request(httpRequestDecorator).build());

    }

    private ServerHttpRequestDecorator requestDecorator(ServerWebExchange exchange) {
        ServerHttpRequestDecorator serverHttpRequestDecorator = new ServerHttpRequestDecorator(exchange.getRequest()) {
            @Override
            public Flux<DataBuffer> getBody() {
                Flux<DataBuffer> body = super.getBody();
                return body.buffer().map(dataBuffers -> {
                    DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory();
                    DataBuffer join = dataBufferFactory.join(dataBuffers);
                    byte[] content = new byte[join.readableByteCount()];
                    join.read(content);
                    DataBufferUtils.release(join);
                    String bodyStr = new String(content, StandardCharsets.UTF_8);
                    // 防xss攻击过滤
                    bodyStr = HtmlUtil.cleanHtmlTag(bodyStr);
                    // 转成字节
                    byte[] bytes = bodyStr.getBytes();
                    NettyDataBufferFactory nettyDataBufferFactory = new NettyDataBufferFactory(ByteBufAllocator.DEFAULT);
                    DataBuffer buffer = nettyDataBufferFactory.allocateBuffer(bytes.length);
                    buffer.write(bytes);
                    return buffer;
                });
            }

            @Override
            public HttpHeaders getHeaders() {
                HttpHeaders httpHeaders = new HttpHeaders();
                httpHeaders.putAll(super.getHeaders());
                // 由于修改了请求体的body,导致content-length长度不确定,因此需要删除原先的content-length
                httpHeaders.remove(HttpHeaders.CONTENT_LENGTH);
                httpHeaders.set(HttpHeaders.TRANSFER_ENCODING, "chunked");
                return httpHeaders;
            }

        };
        return serverHttpRequestDecorator;
    }

    @Override
    public int getOrder() {
        return Ordered.HIGHEST_PRECEDENCE;
    }
}

5.防sql注入

package com.zhdj.gateway.filter;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zhdj.gateway.config.properties.SqlProperties;
import com.zhdj.gateway.config.properties.XssProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.reactive.function.server.HandlerStrategies;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @Author {Yangb}
 * @Date: 2023/10/30/ 10:40
 * @description 防sql注入
 */
@Slf4j
@Component
@ConditionalOnProperty(value = "security.sql.enabled", havingValue = "true")
public class SqlInjectionFilter implements GlobalFilter, Ordered {

    @Autowired
    private SqlProperties sqlProperties;

    /**
     * SQL注入正则判断
     */
    private static final String badStrReg = "\\b(and|or)\\b.{1,6}?(=|>|<|\\bin\\b|\\blike\\b)|\\/\\*.+?\\*\\/|<\\s*script\\b|\\bEXEC\\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\\s+(TABLE|DATABASE)";
    /**
     * 整体都忽略大小写
     */
    private static final Pattern sqlPattern = Pattern.compile(badStrReg, Pattern.CASE_INSENSITIVE);

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 获取请求路径、请求方法、请求参数
        ServerHttpRequest request = exchange.getRequest();
        String requestPath = request.getPath().toString();
        HttpMethod method = request.getMethod();
        MediaType contentType = request.getHeaders().getContentType();
        log.info("SqlInjectionFilter start requestPath:{}, method:{}, contentType:{}", requestPath, method, contentType);
        // 白名单放行
        String[] whiteListArray = sqlProperties.getExcludeUrls().toArray(new String[0]);
        for (String path : whiteListArray) {
            if (requestPath.startsWith(path)) {
                log.info("SqlInjectionFilter white list:" + requestPath);
                return chain.filter(exchange);
            }
        }
        // 判断Param是否存在SQL注入
        AtomicBoolean isSqlInjection = new AtomicBoolean(false);
        request.getQueryParams().forEach((key, values) -> {
            for (String value : values) {
                if (StringUtils.hasText(value) && checkSqlInjection(value)) {
                    isSqlInjection.set(true);
                    return;
                }
            }
        });
        if (isSqlInjection.get()) {
            return errorResponse(exchange.getResponse());
        }
        // contentType不为空,一般说明body中有参数,判断body中是否存在SQL注入,如果存在则直接返回错误信息
        if (contentType != null) {
            return DataBufferUtils.join(exchange.getRequest().getBody()).flatMap(dataBuffer -> {
                // 取出body中的参数
                byte[] bytes = new byte[dataBuffer.readableByteCount()];
                dataBuffer.read(bytes);
                DataBufferUtils.release(dataBuffer);
                Flux<DataBuffer> cachedFlux = Flux.defer(() -> {
                    DataBuffer buffer = exchange.getResponse().bufferFactory().wrap(bytes);
                    DataBufferUtils.retain(buffer);
                    return Mono.just(buffer);
                });
                String bodyString = new String(bytes, StandardCharsets.UTF_8);
                if (MediaType.APPLICATION_JSON.isCompatibleWith(contentType)) {
                    if (StringUtils.hasText(bodyString) && checkJsonBody(bodyString)) {
                        isSqlInjection.set(true);
                    }
                } else if (MediaType.APPLICATION_FORM_URLENCODED.isCompatibleWith(contentType)) {
                    if (StringUtils.hasText(bodyString) && checkFormUrlencoded(bodyString)) {
                        isSqlInjection.set(true);
                    }
                } else if (MediaType.MULTIPART_FORM_DATA.isCompatibleWith(contentType)) {
                    if (StringUtils.hasText(bodyString) && checkFormData(bodyString)) {
                        isSqlInjection.set(true);
                    }
                }
                //  如果存在sql注入,直接拦截请求
                if (isSqlInjection.get()) {
                    log.error("SqlInjectionFilter {} - [{}] 参数:{}, 包含不允许sql的关键词,请求拒绝", method, requestPath, bodyString);
                    return errorResponse(exchange.getResponse());
                }
                // 重新包装ServerHttpRequest
                ServerHttpRequest mutatedRequest = new ServerHttpRequestDecorator(exchange.getRequest()) {
                    @Override
                    public Flux<DataBuffer> getBody() {
                        return cachedFlux;
                    }
                };
                // 用新的ServerHttpRequest改变交换对象
                ServerWebExchange mutatedExchange = exchange.mutate().request(mutatedRequest).build();
                // 使用默认的messageReaders读取正文字符串
                return ServerRequest.create(mutatedExchange, HandlerStrategies.withDefaults().messageReaders()).bodyToMono(String.class).doOnNext(objectValue -> {
                    log.info("SqlInjectionFilter end requestPath:{}, method:{}, contentType:{}", requestPath, method, contentType);
                }).then(chain.filter(mutatedExchange));
            });
        }
        log.info("SqlInjectionFilter end requestPath:{}, method:{}, contentType:{}", requestPath, method, null);
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return Ordered.HIGHEST_PRECEDENCE + 2;
    }
    /**
     * 返回错误响应
     *
     * @param response 响应
     * @return Mono<Void>
     */
    private Mono<Void> errorResponse(ServerHttpResponse response) {
        response.setStatusCode(HttpStatus.BAD_REQUEST);
        response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("code", HttpStatus.BAD_REQUEST.value());
        jsonObject.put("msg", "invalid request params");
        String body = jsonObject.toJSONString();
        DataBuffer buffer = response.bufferFactory().wrap(body.getBytes(StandardCharsets.UTF_8));
        return response.writeWith(Flux.just(buffer));
    }

    /**
     * 判断输入的字符串是否包含SQL注入
     *
     * @param str 输入的字符串
     * @return 如果输入的字符串包含SQL注入,返回 true,否则返回 false。
     */
    private boolean checkSqlInjection(String str) {
        str = str.toLowerCase();
        Matcher matcher = sqlPattern.matcher(str);
        if (matcher.find()) {
            log.error("SqlInjectionFilter 参数[{}]中包含不允许sql的关键词", str);
            return true;
        }
        return false;
    }

    /**
     * 检测application/x-www-form-urlencoded是否包含SQL注入关键字
     *
     * @param bodyString 请求体
     * @return 是否包含SQL注入关键字
     */
    private boolean checkFormUrlencoded(String bodyString) {
        String[] params = bodyString.split("&");
        for (String param : params) {
            String[] keyValue = param.split("=");
            if (keyValue.length == 2) {
                // 判断是否为空
                if (StrUtil.isBlank(keyValue[1])) {
                    continue;
                }
                if (checkSqlInjection(keyValue[1])) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 检测application/json是否包含SQL注入关键字
     *
     * @param body 请求体
     * @return 是否包含SQL注入关键字
     */
    private boolean checkJsonBody(String body) {
        try {
            ObjectMapper objectMapper = new ObjectMapper();
            JsonNode rootNode = objectMapper.readTree(body);
            return checkJsonNode(rootNode);
        } catch (IOException e) {
            log.error("SqlInjectionFilter Error while parsing JSON body", e);
            return false;
        }
    }


    private boolean checkJsonNode(JsonNode node) {
        if (node.isValueNode()) {
            return checkSqlInjection(node.asText());
        } else if (node.isObject()) {
            Iterator<Map.Entry<String, JsonNode>> fieldsIterator = node.fields();
            while (fieldsIterator.hasNext()) {
                Map.Entry<String, JsonNode> field = fieldsIterator.next();
                // 判断是否为空
                if (field.getValue().isNull()) {
                    continue;
                }
                if (checkJsonNode(field.getValue())) {
                    return true;
                }
            }
        } else if (node.isArray()) {
            for (JsonNode childNode : node) {
                if (checkJsonNode(childNode)) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 检测multipart/form-data是否包含SQL注入关键字
     *
     * @param bodyString 请求体
     * @return 是否包含SQL注入关键字
     */
    public boolean checkFormData(String bodyString) {
        bodyString = bodyString.replaceAll("\r", "");
        String[] parts = bodyString.split("\n");
        for (int i = 0; i < parts.length; i++) {
            String part = parts[i];

            if (part.contains("Content-Disposition: form-data;")) {
                // 文件类型不检测
                if (part.contains("file")) {
                    log.info("SqlInjectionFilter file skip");
                    return false;
                }
                String value = parts[i + 2];
                if (StrUtil.isBlank(value)) {
                    continue;
                }
                if (checkSqlInjection(value)) {
                    return true;
                }
            }
        }
        return false;
    }


}

6.yml 配置

在这里插入图片描述

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
lamp-cloud的前身是zuihou-admin-cloud,从3.0.0版本开始,改名为lamp-cloud,它是lamp项目的其中一员。   lamp-cloud是一个基于SpringCloud(Hoxton.SR10) + SpringBoot(2.3.10.RELEASE)的SaaS微服务脚手架,具有统一授权、认证后台管理系统,其中包含具备用户管理、资源权限管理、网关API、分布式事务、大文件断点分片续传等多个模块,支持多业务系统并行开发,可以作为后端服务的开发脚手架。代码简洁,架构清晰,适合学习和直接项目中使用。核心技术采用Nacos、Fegin、Ribbon、Zuul、Hystrix、JWT Token、Mybatis、SpringBoot、Redis、RibbitMQ等主要框架和中间件。 lamp-cloud功能: 1、服务注册&发现与调用: 基于Nacos来实现的服务注册与发现,使用使用Feign来实现服务互调, 可以做到使用HTTP请求远程调用时能与调用本地方法一样的编码体验,开发者完全感知不到这是远程方法,更感知不到这是个HTTP请求。 2、服务鉴权: 通过JWT的方式来加强服务之间调度的权限验证,保证内部服务的安全性。 3、负载均衡: 将服务保留的rest进行代理和网关控制,除了平常经常使用的node.js、nginx外,Spring Cloud系列的zuul和ribbon,可以帮我们进行正常的网关管控和负载均衡。其中扩展和借鉴国外项目的扩展基于JWT的Zuul限流插件,方面进行限流。 4、熔断机制: 因为采取了服务的分布,为了避免服务之间的调用“雪崩”,采用了Hystrix的作为熔断器,避免了服务之间的“雪崩”。 5、监控: 利用Spring Boot Admin 来监控各个独立Service的运行状态;利用turbine来实时查看接口的运行状态和调用频率;通过Zipkin来查看各个服务之间的调用链等。 6、链路调用监控: 利用Zipkin实现微服务的全链路性能监控, 从整体维度到局部维度展示各项指标,将跨应用的所有调用链性能信息集中展现,可方便度量整体和局部性能,并且方便找到故障产生的源头,生产上可极大缩短故障排除时间。有了它,我们能做到: 请求链路追踪,故障快速定位:可以通过调用链结合业务日志快速定位错误信息。 可视化:各个阶段耗时,进行性能分析。 依赖优化:各个调用环节的可用性、梳理服务依赖关系以及优化。 数据分析,优化链路:可以得到用户的行为路径,汇总分析应用在很多业务场景。 7、数据权限 利用基于Mybatis的DataScopeInterceptor拦截实现了简单的数据权限 8、SaaS(多租户)的无感解决方案 使用Mybatis拦截实现对所有SQL拦截,修改默认的Schema,从而实现多租户数据隔离的目的。 并且支持可插拔。 9、二级缓存 采用J2Cache操作缓存,第一级缓存使用内存(Caffeine),第二级缓存使用 Redis。 由于大量的缓存读取会导致 L2 的网络成为整个系统的瓶颈,因此 L1 的目标是降低对 L2 的读取次数。 该缓存框架主要用于集群环境中。单机也可使用,用于避免应用重启导致的缓存冷启动后对后端业务的冲击。 10、优雅的Bean转换 采用Dozer组件来对 DTO、DO、PO等对象的优化转换 11、前后端统一表单验证 严谨的表单验证通常需要 前端+后端同时验证, 但传统的项目,均只能前后端各做一次检验, 后期规则变更,又得前后端同时修改。 故在hibernate-validator的基础上封装了zuihou-validator-starter起步依赖,提供一个通用接口,可以获取需要校验表单的规则,然后前端使用后端返回的规则, 以后若规则改变,只需要后端修改即可。 12、防跨站脚本攻击(XSS) 通过过滤器对所有请求中的 表单参数 进行过滤 通过Json反序列化器实现对所有 application/json 类型的参数 进行过滤 13、当前登录用户信息注入器 通过注解实现用户身份注入 14、在线API 由于原生swagger-ui某些功能支持不够友好,故采用了国内开源的swagger-bootstrap-ui,并制作了stater,方便springboot用户使用。 15、代码生成器 基于Mybatis-plus-generator自定义了一套代码生成器, 通过配置数据库字段的注释,自动生成枚举类、数据字典注解、SaveDTO、UpdateDTO、表单验证规则注解、Swagger注解等。 16、定时任务调度器: 基于xxl-jobs进行了功能增强。(如:指定时间发送任务、执行器和调度器合并项目、多数据源) 17、大文件/断点/分片续传 前端采用w
一、什么是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、付费专栏及课程。

余额充值