SpringCloud 跨站点请求伪造

跨站点请求伪造

在项目进行渗透测试的时候,测试出了系统漏洞:

image.png

跨站点请求伪造-CSRF(Cross Site Request Forgery):是一种网络攻击方式。

通常的解决方法有以下几种:

  1. 验证Referer
  2. 在请求参数中添加token验证
  3. 在HTTP头中自定义属性并验证

这里我们只讨论第一种,验证Referer,如需其他,可参考:www.cnblogs.com/xlyslr/p/57…

示例代码

这里我使用的Spring Cloud Gateway,其他网关可参考实现:

@Slf4j
@Component
public class RefererFilter implements GlobalFilter, Ordered {

    @Value("${cmp.referer}")
    private String referer;

    private static final String REFERER = "referer";

    @Override
    public int getOrder() {
        return 0;
    }

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        ServerHttpRequest request = exchange.getRequest();
        HttpHeaders headers = request.getHeaders();
        String headerReferer = headers.getFirst(REFERER);
        ServerHttpResponse response = exchange.getResponse();

        log.info("function=RefererFilter,headerReferer = {}", headerReferer);
        boolean contain = false;
        String[] referers = referer.split(",");
        for (String referer : referers) {
            if (StringUtils.hasText(headerReferer) && headerReferer.startsWith(referer)) {
                contain = true;
                break;
            }
        }
        if (StringUtils.isEmpty(headerReferer) || !contain) {
            log.error("referer请求头为空!,请求路径为: {}", request.getPath().toString());
            response.setStatusCode(HttpStatus.PRECONDITION_FAILED);
            return errorInfo(exchange, "referer请求头为空!");
        }
        return chain.filter(exchange);
    }

    /**
     * 返回response
     *
     * @param exchange exchange
     * @param message  异常信息
     */
    public static Mono<Void> errorInfo(ServerWebExchange exchange, String message) {
        Map<String, Object> resultMap = new HashMap<>(5);
        resultMap.put("message", message);
        resultMap.put("code", -1);
        return Mono.defer(() -> {
            byte[] bytes = new byte[0];
            try {
                bytes = new ObjectMapper().writeValueAsBytes(resultMap);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
            ServerHttpResponse response = exchange.getResponse();
            response.getHeaders().add("Content-Type", MediaType.APPLICATION_JSON_VALUE);
            DataBuffer buffer = response.bufferFactory().wrap(bytes);
            return response.writeWith(Flux.just(buffer));
        });
    }
}
复制代码

配置文件:

cmp:
  referer: http://localhost,http://127.0.0.1,https://...
复制代码

最终效果

如果请求头上没有携带Referer,就返回错误信息。

image.png

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享