Spring-Cloud-Gateway-实现XSS、SQL注入拦截

XSS和SQL注入是Web应用中常见计算机安全漏洞,文章主要分享通过Spring Cloud Gateway 全局过滤器对XSS和SQL注入进行安全防范。
写这篇文章也是因为项目在经过安全组进行安全巡检时发现项目存储该漏洞后进行系统整改,本文的运行结果是经过安全组验证通过。

使用版本

  • spring-cloud-dependencies Hoxton.SR7
  • spring-boot-dependencies 2.2.9.RELEASE
  • spring-cloud-gateway 2.2.4.RELEASE

核心技术点

1. AddRequestParameterGatewayFilterFactory 获取get请求参数并添加参数然后重构get请求

public GatewayFilter apply(NameValueConfig config) {
    return new GatewayFilter() {
      public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        URI uri = exchange.getRequest().getURI();
        StringBuilder query = new StringBuilder();
        //获取请求url携带的参数,?号后面参数体,类似cl=3&tn=baidutop10&fr=top1000&wd=31 
        String originalQuery = uri.getRawQuery();
        if (StringUtils.hasText(originalQuery)) {
          query.append(originalQuery);
          if (originalQuery.charAt(originalQuery.length() - 1) != '&') {
            query.append('&');
          }
        }

        String value = ServerWebExchangeUtils.expand(exchange, config.getValue());
        query.append(config.getName());
        query.append('=');
        query.append(value);

        try {
          //重构请求uri
          URI newUri = UriComponentsBuilder.fromUri(uri).replaceQuery(query.toString()).build(true).toUri();
          ServerHttpRequest request = exchange.getRequest().mutate().uri(newUri).build();
          return chain.filter(exchange.mutate().request(request).build());
        } catch (RuntimeException var9) {
          throw new IllegalStateException("Invalid URI query: \"" + query.toString() + "\"");
        }
      }

      public String toString() {
        return GatewayToStringStyler.filterToStringCreator(AddRequestParameterGatewayFilterFactory.this).append(config.getName(), config.getValue()).toString();
      }
    };
  }

2. [Spring Cloud Gateway中RequestBody只能获取一次的问题解决方案](https://blog.csdn.net/dear_little_bear/article/details/105319657)
3. Spring Gateway GlobalFilter

技术实现

  1. 创建Filter 实现GlobalFilter, Ordered
@Slf4j
@Component
public class SqLinjectionFilter implements GlobalFilter, Ordered {

  @SneakyThrows
  @Override
  public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain){
    // grab configuration from Config object
    log.debug("----自定义防XSS攻击网关全局过滤器生效----");
    ServerHttpRequest serverHttpRequest = exchange.getRequest();
    HttpMethod method = serverHttpRequest.getMethod();
    String contentType = serverHttpRequest.getHeaders().getFirst(HttpHeaders.CONTENT_TYPE);
    URI uri = exchange.getRequest().getURI();

    Boolean postFlag = (method == HttpMethod.POST || method == HttpMethod.PUT) &&
        (MediaType.APPLICATION_FORM_URLENCODED_VALUE.equalsIgnoreCase(contentType) || MediaType.APPLICATION_JSON_VALUE.equals(contentType));

    //过滤get请求
    if (method == HttpMethod.GET) {

      String rawQuery = uri.getRawQuery();
      if (StringUtils.isBlank(rawQuery)){
        return chain.filter(exchange);
      }

      log.debug("原请求参数为:{}", rawQuery);
      // 执行XSS清理
      rawQuery = XssCleanRuleUtils.xssGetClean(rawQuery);
      log.debug("修改后参数为:{}", rawQuery);

      //	如果存在sql注入,直接拦截请求
      if (rawQuery.contains("forbid")) {
        log.error("请求【" + uri.getRawPath() + uri.getRawQuery() + "】参数中包含不允许sql的关键词, 请求拒绝");
        return setUnauthorizedResponse(exchange);
      }

      try {
        //重新构造get request
        URI newUri = UriComponentsBuilder.fromUri(uri)
            .replaceQuery(rawQuery)
            .build(true)
            .toUri();

        ServerHttpRequest request = exchange.getRequest().mutate()
            .uri(newUri).build();
        return chain.filter(exchange.mutate().request(request).build());
      } catch (Exception e) {
        log.error("get请求清理xss攻击异常", e);
        throw new IllegalStateException("Invalid URI query: \"" + rawQuery + "\"");
      }
    }
    //post请求时,如果是文件上传之类的请求,不修改请求消息体
    else if (postFlag){

      return DataBufferUtils.join(serverHttpRequest.getBody()).flatMap(d -> Mono.just(Optional.of(d))).defaultIfEmpty(
          Optional.empty())
          .flatMap(optional -> {
            // 取出body中的参数
            String bodyString = "";
            if (optional.isPresent()) {
              byte[] oldBytes = new byte[optional.get().readableByteCount()];
              optional.get().read(oldBytes);
              bodyString = new String(oldBytes, StandardCharsets.UTF_8);
            }
            HttpHeaders httpHeaders = serverHttpRequest.getHeaders();
            // 执行XSS清理
            log.debug("{} - [{}:{}] XSS处理前参数:{}", method, uri.getPath(), bodyString);
            bodyString = XssCleanRuleUtils.xssPostClean(bodyString);
            log.info("{} - [{}:{}] XSS处理后参数:{}", method, uri.getPath(), bodyString);

            //	如果存在sql注入,直接拦截请求
            if (bodyString.contains("forbid")) {
              log.error("{} - [{}:{}] 参数:{}, 包含不允许sql的关键词,请求拒绝", method, uri.getPath(), bodyString);
              return setUnauthorizedResponse(exchange);
            }

            ServerHttpRequest newRequest = serverHttpRequest.mutate().uri(uri).build();

            // 重新构造body
            byte[] newBytes = bodyString.getBytes(StandardCharsets.UTF_8);
            DataBuffer bodyDataBuffer = toDataBuffer(newBytes);
            Flux<DataBuffer> bodyFlux = Flux.just(bodyDataBuffer);

            // 重新构造header
            HttpHeaders headers = new HttpHeaders();
            headers.putAll(httpHeaders);
            // 由于修改了传递参数,需要重新设置CONTENT_LENGTH,长度是字节长度,不是字符串长度
            int length = newBytes.length;
            headers.remove(HttpHeaders.CONTENT_LENGTH);
            headers.setContentLength(length);
            headers.set(HttpHeaders.CONTENT_TYPE, "application/json;charset=utf8");
            // 重写ServerHttpRequestDecorator,修改了body和header,重写getBody和getHeaders方法
            newRequest = new ServerHttpRequestDecorator(newRequest) {
              @Override
              public Flux<DataBuffer> getBody() {
                return bodyFlux;
              }

              @Override
              public HttpHeaders getHeaders() {
                return headers;
              }
            };

            return chain.filter(exchange.mutate().request(newRequest).build());
          });
    } else {
      return chain.filter(exchange);
    }

  }


  // 自定义过滤器执行的顺序,数值越大越靠后执行,越小就越先执行
  @Override
  public int getOrder() {
    return Ordered.HIGHEST_PRECEDENCE;
  }

  /**
   * 设置403拦截状态
   */
  private Mono<Void> setUnauthorizedResponse(ServerWebExchange exchange) {
    return WebfluxResponseUtil.responseFailed(exchange, HttpStatus.FORBIDDEN.value(),
        "request is forbidden, SQL keywords are not allowed in the parameters.");
  }

  /**
   * 字节数组转DataBuffer
   *
   * @param bytes 字节数组
   * @return DataBuffer
   */
  private DataBuffer toDataBuffer(byte[] bytes) {
    NettyDataBufferFactory nettyDataBufferFactory = new NettyDataBufferFactory(ByteBufAllocator.DEFAULT);
    DataBuffer buffer = nettyDataBufferFactory.allocateBuffer(bytes.length);
    buffer.write(bytes);
    return buffer;
  }

}
  1. 定义xss注入、sql注入工具类
@Slf4j
public class XssCleanRuleUtils {

  private final static Pattern[] scriptPatterns = {
      Pattern.compile("<script>(.*?)</script>", Pattern.CASE_INSENSITIVE),
      Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL),
      Pattern.compile("</script>", Pattern.CASE_INSENSITIVE),
      Pattern.compile("<script(.*?)>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL),
      Pattern.compile("eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL),
      Pattern.compile("expression\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL),
      Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE),
      Pattern.compile("vbscript:", Pattern.CASE_INSENSITIVE),
      Pattern.compile("onload(.*?)=", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL)
  };

  private static 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 Pattern sqlPattern = Pattern.compile(badStrReg, Pattern.CASE_INSENSITIVE);//整体都忽略大小写

  /**
   * GET请求参数过滤
   * @param value
   * @return
   */
  public static String xssGetClean(String value) throws UnsupportedEncodingException {

    //过滤xss字符集
    if (value != null) {
      value = value.replaceAll("\0|\n|\r", "");
      for (Pattern pattern : scriptPatterns) {
        value = pattern.matcher(value).replaceAll("");
      }
      value = value.replaceAll("<", "&lt;").replaceAll(">", "&gt;");
    }

    //sql关键字检查
    return cleanGetSqlKeyWords(value);

  }


  public static String xssPostClean(String value) {

    //过滤xss字符集
    if (value != null) {
      value = value.replaceAll("\0|\n|\r", "");
      for (Pattern pattern : scriptPatterns) {
        value = pattern.matcher(value).replaceAll("");
      }
      value = value.replaceAll("<", "&lt;").replaceAll(">", "&gt;");
    }
    //sql关键字检查
    return cleanPostSqlKeyWords(value);

  }

  /**
   * 解析参数SQL关键字
   * @param value
   * @return
   */
  private static String cleanGetSqlKeyWords(String value) throws UnsupportedEncodingException {

    //参数需要url编码
    //这里需要将参数转换为小写来处理
    //不改变原值
    //value示例 order=asc&pageNum=1&pageSize=100&parentId=0
    String lowerValue = URLDecoder.decode(value, "UTF-8").toLowerCase();

    //获取到请求中所有参数值-取每个key=value组合第一个等号后面的值
    boolean isContains = Stream.of(lowerValue.split("\\&"))
        .map(kp -> kp.substring(kp.indexOf("=") + 1))
        .parallel()
        .anyMatch(param -> {
          if (sqlPattern.matcher(param).find())
          {
            log.error("参数中包含不允许sql的关键词");
            return true;
          }
          return false;
        });

    return isContains ? "forbid" : value;
  }


  /**
   * 解析参数SQL关键字
   * @param value
   * @return
   */
  private static String cleanPostSqlKeyWords(String value){

    JSONObject json = JSONObject.parseObject(value);
    Map<String, Object> map = json;
    Map<String, Object> mapjson = new HashMap<>();

    for (Map.Entry<String, Object> entry : map.entrySet()) {
      String value1 =  entry.getValue().toString();

      //这里需要将参数转换为小写来处理-不改变原值
      String lowerValue = value1.toLowerCase();

      if (sqlPattern.matcher(lowerValue).find())
      {
        log.error("参数中包含不允许sql的关键词");
        value1 = "forbid";
        mapjson.put(entry.getKey(),value1);
        break;
      } else {
        mapjson.put(entry.getKey(),entry.getValue());
      }

    }

    return JSONObject.toJSONString(mapjson);
  }

踩坑过程

  1. sql注入过滤规则
    网上大多数sql注入拦截规则都是使用一个sql关键字匹配,
//定义sql注入关键字
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|//|/|%|#";
//过滤规则
for (String bad : badStrs) {
				if (value1.equalsIgnoreCase(bad)) {
					value1 = "forbid";
					mapjson.put(entry.getKey(),value1);
					break;
				} else {
					mapjson.put(entry.getKey(),entry.getValue());
				}
			}
		}

最初我们也是使用改方式,但是关键字匹配方式实在太容易误杀正常业务,且容易漏,比如

select/*/1from/*/tt 

这样形式的参数就无法过滤。
最后我们还是采取sql正则匹配的方式(见代码),已和安全工程师完成联调,能够挡住安全工程师的注入测试案例,对业务也完成回归测试,基本不影响现有业务正常运行。
2. get请求拦截过程不要对源参数进行url编码,否则应用可能出现不必要的错误

get请求参数中的中文字符以及一些特色字符请求到服务器会自动编码,在对xss注入过滤过程需要进行url编码才能进行过滤规则的验证,在起初我们是在源参数上进行编码,但是一些正常请求中携带+号这样的特色符号的请求在处理过程会被过滤掉,该问题排查了许久才发现的,因此建议不要改变源请求参数的编码格式

 //参数需要url编码
    //这里需要将参数转换为小写来处理
    //不改变原值
    //value示例 order=asc&pageNum=1&pageSize=100&parentId=0
    String lowerValue = URLDecoder.decode(value, "UTF-8").toLowerCase();
  1. RequestBody只能获取一次的问题
    代码参考了网上对于RequestBody只能获取一次的问题解决的方案,在spring-cloud-gateway 2.2.4.RELEASE验证有效

优化

拦截器在实际生产运行过程存在一些列问题:

  1. 对xss字符集的转换会导致会第三方平台接入的接口出现一些列问题,尤其是需要参数签名验签的接口,因为参数的变化导致验签不成功
  2. 对于第三方平台(尤其时强势的第三方),我们往往无法要求第三方按照我们的参数规则传递参数,这类的接口会包含sql注入的关键字
  3. 在请求重构过程,可能会改变参数的结构,会导致验签失败
  4. 对post请求,虽然目前前后端大多交互都是通过Json,但如有特殊请求参数可能是非Json格式参数,需要多改类型参数进行兼容

因此,在实现XSS、SQL注入拦截基础上进行优化,移除xss字符集转换且不改变请求参数,增加白名单机制,具体实现如下:

@Slf4j
@Component
@ConfigurationProperties(prefix = "gateway.security.ignore")
@RefreshScope
public class SqLinjectionFilter implements GlobalFilter, Ordered {

  private String[] sqlinjectionHttpUrls = new String[0];

  @SneakyThrows
  @Override
  public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain){
    // grab configuration from Config object
    log.debug("----自定义防sql注入网关全局过滤器生效----");
    ServerHttpRequest serverHttpRequest = exchange.getRequest();
    HttpMethod method = serverHttpRequest.getMethod();
    String contentType = serverHttpRequest.getHeaders().getFirst(HttpHeaders.CONTENT_TYPE);
    URI uri = exchange.getRequest().getURI();

    //1.动态刷新 sql注入的过滤的路径
    String path = serverHttpRequest.getURI().getRawPath();
    String matchUrls[] = this.getSqlinjectionHttpUrls();

    if( AuthUtils.isMatchPath(path, matchUrls)){
      log.error("请求【{}】在sql注入过滤白名单中,直接放行", path);
      return chain.filter(exchange);
    }

    Boolean postFlag = (method == HttpMethod.POST || method == HttpMethod.PUT) &&
        (MediaType.APPLICATION_FORM_URLENCODED_VALUE.equalsIgnoreCase(contentType) || MediaType.APPLICATION_JSON_VALUE.equals(contentType));

    //过滤get请求
    if (method == HttpMethod.GET) {

      String rawQuery = uri.getRawQuery();
      if (StringUtils.isBlank(rawQuery)){
        return chain.filter(exchange);
      }

      log.debug("请求参数为:{}", rawQuery);
      // 执行sql注入校验清理
      boolean chkRet = SqLinjectionRuleUtils.getRequestSqlKeyWordsCheck(rawQuery);

      //	如果存在sql注入,直接拦截请求
      if (chkRet) {
        log.error("请求【" + uri.getRawPath() + uri.getRawQuery() + "】参数中包含不允许sql的关键词, 请求拒绝");
        return setUnauthorizedResponse(exchange);
      }
      //透传参数,不对参数做任何处理
      return chain.filter(exchange);
    }
    //post请求时,如果是文件上传之类的请求,不修改请求消息体
    else if (postFlag){

      return DataBufferUtils.join(serverHttpRequest.getBody()).flatMap(d -> Mono.just(Optional.of(d))).defaultIfEmpty(
          Optional.empty())
          .flatMap(optional -> {
            // 取出body中的参数
            String bodyString = "";
            if (optional.isPresent()) {
              byte[] oldBytes = new byte[optional.get().readableByteCount()];
              optional.get().read(oldBytes);
              bodyString = new String(oldBytes, StandardCharsets.UTF_8);
            }
            HttpHeaders httpHeaders = serverHttpRequest.getHeaders();
            // 执行XSS清理
            log.debug("{} - [{}] 请求参数:{}", method, uri.getPath(), bodyString);
           if (MediaType.APPLICATION_JSON_VALUE.equals(contentType)) {
              //如果MediaType是json才执行json方式验证
              chkRet = SqLinjectionRuleUtils.postRequestSqlKeyWordsCheck(bodyString);
            } else {
              //form表单方式,需要走get请求
              chkRet = SqLinjectionRuleUtils.getRequestSqlKeyWordsCheck(bodyString);
            }

            //	如果存在sql注入,直接拦截请求
            if (chkRet) {
              log.error("{} - [{}] 参数:{}, 包含不允许sql的关键词,请求拒绝", method, uri.getPath(), bodyString);
              return setUnauthorizedResponse(exchange);
            }

            ServerHttpRequest newRequest = serverHttpRequest.mutate().uri(uri).build();

            // 重新构造body
            byte[] newBytes = bodyString.getBytes(StandardCharsets.UTF_8);
            DataBuffer bodyDataBuffer = toDataBuffer(newBytes);
            Flux<DataBuffer> bodyFlux = Flux.just(bodyDataBuffer);

            // 重新构造header
            HttpHeaders headers = new HttpHeaders();
            headers.putAll(httpHeaders);
            // 由于修改了传递参数,需要重新设置CONTENT_LENGTH,长度是字节长度,不是字符串长度
            int length = newBytes.length;
            headers.remove(HttpHeaders.CONTENT_LENGTH);
            headers.setContentLength(length);
            headers.set(HttpHeaders.CONTENT_TYPE, "application/json;charset=utf8");
            // 重写ServerHttpRequestDecorator,修改了body和header,重写getBody和getHeaders方法
            newRequest = new ServerHttpRequestDecorator(newRequest) {
              @Override
              public Flux<DataBuffer> getBody() {
                return bodyFlux;
              }

              @Override
              public HttpHeaders getHeaders() {
                return headers;
              }
            };

            return chain.filter(exchange.mutate().request(newRequest).build());
          });
    } else {
      return chain.filter(exchange);
    }

  }


  // 自定义过滤器执行的顺序,数值越大越靠后执行,越小就越先执行
  @Override
  public int getOrder() {
    return Ordered.HIGHEST_PRECEDENCE;
  }

  /**
   * 设置403拦截状态
   */
  private Mono<Void> setUnauthorizedResponse(ServerWebExchange exchange) {
    return WebfluxResponseUtil.responseFailed(exchange, HttpStatus.FORBIDDEN.value(),
        "request is forbidden, SQL keywords are not allowed in the parameters.");
  }

  /**
   * 字节数组转DataBuffer
   *
   * @param bytes 字节数组
   * @return DataBuffer
   */
  private DataBuffer toDataBuffer(byte[] bytes) {
    NettyDataBufferFactory nettyDataBufferFactory = new NettyDataBufferFactory(ByteBufAllocator.DEFAULT);
    DataBuffer buffer = nettyDataBufferFactory.allocateBuffer(bytes.length);
    buffer.write(bytes);
    return buffer;
  }

  public String[] getSqlinjectionHttpUrls() {
    return sqlinjectionHttpUrls;
  }

  public void setSqlinjectionHttpUrls(String[] sqlinjectionHttpUrls) {
    this.sqlinjectionHttpUrls = sqlinjectionHttpUrls;
  }
}

@Slf4j
public class SqLinjectionRuleUtils {

  private static 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 Pattern sqlPattern = Pattern.compile(badStrReg, Pattern.CASE_INSENSITIVE);//整体都忽略大小写


  /**
   * get请求sql注入校验
   * @param value
   * @return
   */
  public static boolean getRequestSqlKeyWordsCheck(String value) throws UnsupportedEncodingException {

    //参数需要url编码
    //这里需要将参数转换为小写来处理
    //不改变原值
    //value示例 order=asc&pageNum=1&pageSize=100&parentId=0
    String lowerValue = URLDecoder.decode(value, "UTF-8").toLowerCase();

    //获取到请求中所有参数值-取每个key=value组合第一个等号后面的值
    return Stream.of(lowerValue.split("\\&"))
        .map(kp -> kp.substring(kp.indexOf("=") + 1))
        .parallel()
        .anyMatch(param -> {
          if (sqlPattern.matcher(param).find())
          {
            log.error("参数中包含不允许sql的关键词");
            return true;
          }
          return false;
        });
  }


  /**
   * post请求sql注入校验
   * @param value
   * @return
   */
  public static boolean postRequestSqlKeyWordsCheck(String value){

    Object jsonObj = JSON.parse(value);
    if (jsonObj instanceof JSONObject) {
      JSONObject json = (JSONObject) jsonObj;
      Map<String, Object> map = json;

      //对post请求参数值进行sql注入检验
      return map.entrySet().stream().parallel().anyMatch(entry -> {

        //这里需要将参数转换为小写来处理
        String lowerValue = Optional.ofNullable(entry.getValue())
            .map(Object::toString)
            .map(String::toLowerCase)
            .orElse("");


        if (sqlPattern.matcher(lowerValue).find())
        {
          log.error("参数[{}]中包含不允许sql的关键词", lowerValue);
          return true;
        }
        return false;
      });
    } else {
      JSONArray json = (JSONArray) jsonObj;
      List<Object> list = json;
      //对post请求参数值进行sql注入检验
      return list.stream().parallel().anyMatch(obj -> {

        //这里需要将参数转换为小写来处理
        String lowerValue = Optional.ofNullable(obj)
            .map(Object::toString)
            .map(String::toLowerCase)
            .orElse("");


        if (sqlPattern.matcher(lowerValue).find())
        {
          log.error("参数[{}]中包含不允许sql的关键词", lowerValue);
          return true;
        }
        return false;
      });
    }


}

ps:网关全局拦截影响应用所有请求,拦截规则和对请求类型的兼容还需要根据项目线上实际情况进行调整。

  • 15
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 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
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值