记一次网关项目Actuator未授权访问漏洞的修复方案

前言

公司项目在做等保测评的时候发现网关项目存在Actuator未授权访问漏洞,在 Actuator 启用的情况下,如果没有做好相关权限控制,非法用户可通过访问默认的执行器端点(endpoints)来获取应用系统中的监控信息,从而导致信息泄露甚至服务器被接管的事件发生。默认配置会出现接口未授权访问,部分接口会泄露网站流量信息和内存信息等,使用Jolokia库特性甚至可以远程执行任意代码,获取服务器权限。

漏洞效果

直接通过访问接口 http://服务器ip:程序端口/actuator/env,就返回了服务器的一些重要信息。
在这里插入图片描述

漏洞解决

1. 网上解决方案

网上解决方案大概就两种:
① 直接为了等保测评将Actuator监控直接关掉,等测评通过后再打开。

management:
  endpoints:
    enabled: false

这个就完全是为了应付等保测评了,方案不可取
②引入security

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-security</artifactId>
</dependency>

开启Security,配置访问权限

spring:
  security:
    user:
      username: security账号
      password: security密码

management:
  security:
    enabled: true

再次访问 http://服务器ip:程序端口/actuator/env
在这里插入图片描述
发现需要登录了,这个方案在一般的项目都是可取的,也能起到权限拦截的作用,但是由于我们这个是网关项目,项目内的接口都是对外暴露的,项目内有自己的一套安全认证机制,包括权限认证,接口转发,统一响应等等,如果引入security,项目启动之后,外部访问项目接口都会最先走security的认证机制,就不会走网关项目认证机制,直接返404或其他错误,所以这种方案对于网关项目是不可取的。

2. 我的解决方案

由于security的安全方案不可取,干脆我自己弄一个权限认证机制,对于访问路径是以/actuator开头的,统统需要账号密码进行权限认证:



import cn.hutool.core.collection.CollectionUtil;
import com.sztech.gateway.plugin.api.result.GatewayResultWarp;
import com.sztech.gateway.plugin.api.util.WebFluxResultUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;
import sun.misc.BASE64Decoder;

import java.util.List;

/**
 * 用于处理Actuator未授权访问漏洞的过滤器
 *
 * @author wenchao
 */
@Component
@Slf4j
public class ActuatorFilter implements WebFilter {

    @Value("${com.sztech.prometheus.username}")
    public String userName;

    @Value("${com.sztech.prometheus.password}")
    public String password;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        log.info("into ActuatorFilter ...");
        ServerHttpRequest request = exchange.getRequest();
        String url = request.getPath().toString();
        log.info("url:  {}", url);
        //只拦截actuator相关的接口 如果项目接口有前缀需自行添加进行判断
        if (url.startsWith("/actuator")){
            List<String> authList = request.getHeaders().get("Authorization");
            if (CollectionUtil.isEmpty(authList)){
                Object error = GatewayResultWarp.error("401", "未授权", null);
                return WebFluxResultUtils.result(exchange, error);
            }
            String auth = authList.get(0);
            if (StringUtils.isBlank(auth)){
                Object error = GatewayResultWarp.error("401", "未授权", null);
                return WebFluxResultUtils.result(exchange, error);
            }
            auth = getFromBASE64(auth.substring(6));
            log.info("auth: {}", auth);
            try {
                String[] authArray = auth.split(":");
                if (authArray[0].equals(userName) && authArray[1].equals(password)){
                    return chain.filter(exchange);
                }else {
                    Object error = GatewayResultWarp.error("401", "认证失败", null);
                    return WebFluxResultUtils.result(exchange, error);
                }
            }catch (Exception e){
                e.printStackTrace();
                Object error = GatewayResultWarp.error("401", "认证失败", null);
                return WebFluxResultUtils.result(exchange, error);
            }
        }
        return chain.filter(exchange);
    }


    private String getFromBASE64(String s) {
        if (s == null) {
            return null;
        }
        BASE64Decoder decoder = new BASE64Decoder();
        try {
            byte[] b = decoder.decodeBuffer(s);
            return new String(b);
        } catch (Exception e) {
            return null;
        }
    }


}

配置文件同步配置一下账号密码:

com:
  sztech:
    prometheus:
      username: 账号
      password: 密码

重启项目之后重新访问接口

在这里插入图片描述
由于我们项目是借助于prometheus对actuator监控信息进行收集和展示,所以prometheus的配置文件也需要修改一下,将账号密码配置一下,再重启prometheus即可。

 basic_auth:
   username: 账号
   password: 密码

下面看一下监控效果
在这里插入图片描述

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SpringBoot ActuatorSpring Boot提供的一个监控和管理Spring Boot应用程序的框架,包括健康检查、审计、统计和HTTP接口等功能。而授权访问漏洞则是指攻击者可以通过某种方式授权访问到应用程序中的敏感信息或者功能。 在你提供的URL中,可以看到该漏洞存在于目标主机的Spring Boot应用程序中。攻击者可以通过向该URL发送一个GET请求,获取应用程序的环境配置信息,包括应用程序使用的所有配置属性、系统环境变量、JVM属性等等。这些信息可能包含敏感数据,例如数据库密码、加密密钥等等,从而导致安全风险。 为了解决这个问题,你可以采取以下措施: 1. 更新Spring Boot Actuator版本:Spring Boot官方已经发布了多个版本的Actuator,其中许多版本已经修复了该漏洞。你可以升级到最新版本的Actuator来避免该漏洞。 2. 配置Actuator的安全:Spring Boot Actuator提供了安全配置选项,可以限制对Actuator HTTP端点的访问。你可以使用Spring Security等框架来对Actuator进行安全配置,只允许授权用户访问Actuator端点。 3. 禁用Actuator HTTP端点:如果你不需要使用Actuator提供的HTTP端点,可以禁用它们以避免安全风险。在Spring Boot应用程序的配置文件中,设置management.endpoints.web.exposure.exclude属性,将不需要的端点排除在外。例如:`management.endpoints.web.exposure.exclude=env,health,info`。 综上所述,对于SpringBoot Actuator授权访问漏洞,你应该及时采取相应的措施进行修复和防范。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值