网安代审篇-鉴权 - ☕ 经验茶谈极核论坛 - 知识星球 - 极核GetShell

网安代审篇-鉴权

进行鉴权有四大主流技术:原生开发Filter、Spring框架Interceptor、Shiro以及JWT

一、Filter

Java Filter 既可通过原生 Servlet API 开发,也可集成 Spring 框架实现。在代码审计中,需重点关注其实现逻辑的正确性、拦截路径的精确配置以及例外规则的合理排除。

原生 Filter 与 Spring Filter 在拦截路径定义上的主要差异,体现在配置载体,而拦截器本身编写无差异:前者依赖 web.xml 部署描述符,后者则通过注解或 Java 配置类实现。

在开发Filter时需要实现Filter接口,并重写doFilterinit以及destroy方法,作用依次是请求过滤、初始化以及销毁;由于逻辑问题主要出现在doFilter方法,因此doFilter方法是审计的重中之重;以下为Filter示例:

public class AuthFilter implements Filter {
    
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, 
                         FilterChain chain) throws IOException, ServletException {
        
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        
        // 1. 获取Token
        String token = httpRequest.getHeader("Authorization");
        
        // 2. 校验Token
        if (token == null || !isValidToken(token)) {
            // 3. 未认证处理
            httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            httpResponse.getWriter().write("Unauthorized: Invalid token");
            return;
        }
        
        // 4. 认证通过,继续请求
        chain.doFilter(request, response);
    }
    
    private boolean isValidToken(String token) {
        // 实际项目中调用认证服务
        return token != null && token.startsWith("Bearer ");
    }
    
    @Override
    public void init(FilterConfig filterConfig) {}
    
    @Override
    public void destroy() {}
}

1.1 使用XML编写拦截范围

通常纯原生开发会将拦截范围添加至web.xml中,<filter>标签注册拦截器,<filter-mapping>标签配置拦截范围以及例外范围;以下为web.xml范围示例:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 
                             http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <!-- 1. 注册AuthFilter -->
    <filter>
        <filter-name>AuthenticationFilter</filter-name>
        <filter-class>com.example.AuthFilter</filter-class> <!-- 替换为您的完整类路径 -->
    </filter>
    
    <!-- 2. 配置AuthFilter的映射 -->
    <filter-mapping>
        <filter-name>AuthenticationFilter</filter-name>
        
        <!-- 指定要保护的URL模式 -->
        <url-pattern>/api/*</url-pattern>
        <url-pattern>/admin/*</url-pattern>
        <url-pattern>/secure/*</url-pattern>
    </filter-mapping>
    
    <!-- 3. 配置例外路径(如果不需要认证) -->
    <filter-mapping>
        <filter-name>AuthenticationFilter</filter-name>
        <url-pattern>/public/*</url-pattern>
        <dispatcher>REQUEST</dispatcher>
        <!-- 禁用该路径的过滤器 -->
        <dispatcher>NONE</dispatcher>
    </filter-mapping>
</web-app>

1.2 结合Spring编写拦截范围

Spring 结合Filter的主流写法是单独写一个配置类,将已经编辑好的FIlter类添加至FilterRegistrationBean<T>中;需要注意的是该方法只能添加拦截范围,若要添加例外范围需要在FIlter中编写逻辑;以下为Spring配置范围示例:

@Configuration
public class FilterConfig {
    
    @Bean
    public FilterRegistrationBean<AuthFilter> authFilter() {
        FilterRegistrationBean<AuthFilter> reg = new FilterRegistrationBean<>();
        reg.setFilter(new AuthFilter());
        reg.addUrlPatterns("/api/*"); // 保护API路径
        reg.setOrder(1); // 执行顺序
        return reg;
    }
}

二、Interceptor

在功能定位上与 Filter 类似,核心职责均为请求拦截处理。作为 Spring MVC 体系的关键组件,它同样被广泛应用于 Spring Boot 应用中,实现对控制器方法的拦截控制。在 Spring MVC 中,拦截器的路径配置通常通过 XML 文件实现,而 Spring Boot 普遍采用 Java 配置类定义拦截范围。

在开发Interceptor需要实现HandlerInterceptor接口,并重写preHandlepostHandle以及afterCompletion方法,作用依次是请求前拦截、请求后拦截以及请求完成后拦截;由于逻辑问题主要出现在preHandle方法,因此preHandle方法是审计的重中之重;以下为Interceptor示例:

public class LoggingInterceptor implements HandlerInterceptor {
    
    // Controller 执行前调用
    @Override
    public boolean preHandle(HttpServletRequest request, 
                             HttpServletResponse response, 
                             Object handler) {
        System.out.println("请求开始: " + request.getRequestURI());
        long startTime = System.currentTimeMillis();
        request.setAttribute("startTime", startTime);
        return true; // 继续执行流程
    }
    
    // Controller 执行后,视图渲染前调用
    @Override
    public void postHandle(HttpServletRequest request, 
                           HttpServletResponse response, 
                           Object handler,
                           ModelAndView modelAndView) {
        System.out.println("Controller 执行完成");
    }
    
    // 请求完成后调用(视图渲染完成)
    @Override
    public void afterCompletion(HttpServletRequest request, 
                                HttpServletResponse response, 
                                Object handler, 
                                Exception ex) {
        long startTime = (Long) request.getAttribute("startTime");
        long duration = System.currentTimeMillis() - startTime;
        System.out.println("请求完成: " + request.getRequestURI() 
                          + " 耗时: " + duration + "ms");
        if (ex != null) {
            System.err.println("请求异常: " + ex.getMessage());
        }
    }
}

2.1 Spring MVC

<mvc:interceptors>
    <!-- 全局拦截器 -->
    <bean class="com.example.LoggingInterceptor"/>
    
    <!-- 路径匹配拦截器 -->
    <mvc:interceptor>
        <mvc:mapping path="/api/**"/>
        <mvc:exclude-mapping path="/api/public/**"/>
        <bean class="com.example.AuthInterceptor"/>
    </mvc:interceptor>
    
    <!-- 特定Controller拦截 -->
    <mvc:interceptor>
        <mvc:mapping path="/admin/**"/>
        <ref bean="adminSecurityInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>

2.2 Spring boot

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
    
    // 注册拦截器
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 基础日志拦截器
        registry.addInterceptor(new LoggingInterceptor())
                .addPathPatterns("/**") // 所有路径
                .excludePathPatterns("/static/**", "/public/**"); // 排除静态资源
    }
    
    @Bean
    public AuthInterceptor authInterceptor() {
        return new AuthInterceptor();
    }
    
    @Bean
    public PerformanceInterceptor perfInterceptor() {
        return new PerformanceInterceptor();
    }
}

三、Shiro

Apache Shiro 作为轻量级 Java 安全框架,其核心能力包含精准的拦截范围控制;本文仅对路径拦截规则进行讨论。

Shiro拦截范围编写在配置文件中,排除例外的配置属性为shiro.anon_url,编写实例:

tumo.shiro.anon_url=\
  /login,/logout,/register,\
  /,/about,/p/**,/links,/comment/**,/link/list,/article/list,\
  /css/**,/js/**,/img/**

四、JWT

JWT 的四大核心安全问题包括:空加密算法使用、服务端签名缺失验证、默认密钥未更新及弱密钥漏洞。其中前两者属于代码逻辑缺陷,而默认密钥问题则源于部署时未修改配置文件中的初始值;主要审计项目中的默认秘钥值。

请登录后发表评论

    没有回复内容