目录

Java代码审计-第一篇Spring应用程序架构审计要点

【Java代码审计 | 第一篇】Spring应用程序架构审计要点

未经许可,不得转载。

https://i-blog.csdnimg.cn/direct/892c1dc4ebd94ce8a3a9fedf5670cf1f.png

在开展Java代码审计之前,需先夯实相关基础知识,以确保审计过程更加高效和精准。

请同时参考:

Spring应用程序分层架构

Spring 是一个功能强大的 Java 开源框架,主要用于简化 Java 企业级应用开发。它提供了依赖注入(DI)、面向切面编程(AOP)、事务管理等核心特性,并支持集成各种 Java 技术(如 JDBC、JPA、Spring MVC)。Spring 通过 IoC(控制反转)容器管理对象生命周期,减少了代码耦合,提高了开发效率。

Spring 与 Java 的关系密切,它基于 Java 语言构建,广泛应用于 Java Web 开发、微服务架构(如 Spring Boot 和 Spring Cloud),成为 Java 生态中最主流的开发框架之一。

Spring 适用于大规模、细粒度控制的企业级开发,Spring Boot 更适合快速开发、微服务架构。

https://i-blog.csdnimg.cn/direct/9091574fde4f4be69be13edf4fec0bf8.png

1. 表现层(View 层)

定义 :处理用户界面展示,常使用JSP、Thymeleaf、Freemarker等模板引擎

核心组件

  • 模板文件(.jsp/.html)
  • 视图解析器(ViewResolver)
  • 前端控制器(DispatcherServlet)

审计要点

<!-- 漏洞示例:未转义的XSS漏洞 -->
<p>${userInput}</p>  <!-- 危险写法 -->
<p th:text="${userInput}"></p>  <!-- 安全写法 -->
  • 模板引擎是否开启自动HTML转义
  • 动态内容输出时是否强制使用安全输出语法
  • 客户端渲染(如Vue/React)与服务器端渲染的混合使用场景

2. 接口层(API 层)

定义 :提供RESTful/SOAP等API接口,使用 @RestController 标注

典型特征

  • 接口响应格式(JSON/XML)
  • 统一状态码管理(如200/401/500)

审计要点

@GetMapping("/user")
public User getUser(@RequestParam String id) { // 未经验证的参数
    return userService.findById(id);
}
  • 接口鉴权缺失(如未使用 @PreAuthorize
  • 敏感数据未脱敏(如密码字段返回给前端)
  • 未限制HTTP方法(如PUT/DELETE权限控制)

3. 控制器层(Controller 层)

核心组件@Controller@RequestMapping

处理流程

  1. 接收HTTP请求参数
  2. 调用Service层处理业务
  3. 返回视图或数据模型

审计要点

@RequestMapping("/download")
public void downloadFile(String filename, HttpServletResponse response) {
    File file = new File("/uploads/" + filename); // 路径遍历漏洞风险
    // ...
}
  • 参数绑定漏洞(如 @RequestParam 未校验格式)
  • 未处理文件上传大小限制(导致DoS攻击)
  • 重定向未校验目标地址(开放重定向漏洞)

4. 业务逻辑层(Service 层)

核心组件@Service 注解类

职责

  • 实现核心业务规则
  • 事务管理( @Transactional

审计示例

@Service
public class PaymentService {
    public void transfer(Account from, Account to, BigDecimal amount) {
        from.withdraw(amount);  // 未加事务锁可能导致并发问题
        to.deposit(amount);
    }
}

审计要点

  • 业务规则绕过(如支付金额负数校验缺失)
  • 事务未处理回滚(如数据库异常后数据不一致)
  • 循环依赖导致的空指针异常

5. 数据访问层(DAO 层 / Repository 层)

技术栈 :JDBC、JPA、MyBatis

核心组件

  • @Repository 注解类
  • JpaRepository接口实现

漏洞示例

@Query("SELECT u FROM User u WHERE u.username = '" + username + "'") // SQL注入风险
User findByUsername(String username);

审计要点

  • 动态SQL拼接(MyBatis中 ${} 误用)
  • JPA方法名注入(如 findByUsername 参数未过滤)
  • 连接池配置泄露(如未加密数据库密码)

6. 模型层(Model 层)

组成 :POJO类(如 User.java )、DTO、VO

审计关注点

public class User {
    @Size(min=6, max=20) 
    private String password; // 长度校验但未限制复杂度
}
  • 数据验证注解(如 @NotNull@Pattern )的完整性
  • 敏感字段(如密码)是否标记为 @Transient 避免持久化
  • DTO与实体类转换时的属性拷贝漏洞

7. 配置层(Configuration 层)

配置文件application.properties@Configuration

关键配置项

# 安全风险示例:关闭CSRF保护
spring.security.csrf.enabled=false 

审计要点

  • CORS配置过于宽松(如 allowedOrigins=*
  • 敏感信息硬编码(数据库密码、API密钥)
  • 日志级别泄露调试信息(如开启DEBUG模式)

8. 工具层(Utility 层)

常见类StringUtilsDateUtils 、加密工具类

漏洞案例

public static String encrypt(String input) {
    // 使用不安全的MD5哈希
    return DigestUtils.md5Hex(input);
}

审计重点

  • 弱加密算法(如DES、MD5)
  • 随机数生成器( java.util.Random 替代SecureRandom)
  • 反射调用未做安全限制

9. 缓存层(Cache 层)

技术实现 :Redis、Ehcache、 @Cacheable 注解

风险场景

@Cacheable(value = "users", key = "#username")
public User getUser(String username) { 
    // 缓存未设置过期时间导致敏感数据长期驻留
}

审计要点

  • 缓存穿透/击穿/雪崩防护机制
  • 本地缓存未隔离不同用户数据
  • Redis未启用SSL通信加密

10. 消息处理层(Messaging 层)

技术组件 :Kafka、RabbitMQ、JMS

漏洞示例

@JmsListener(destination = "orderQueue")
public void processOrder(String message) {
    // 未验证消息来源,导致恶意消息注入
}

审计重点

  • 消息消费者未做身份验证
  • 消息内容未加密(敏感信息泄露)
  • 死信队列未监控导致消息堆积

11. 异步层(Async 层)

实现方式@Async 注解、线程池

风险代码

@Async
public void logAccess(String username) {
    // 异步方法内未捕获异常,导致线程崩溃
    accessLogService.log(username);
}

审计关注点

  • 线程池资源耗尽(未设置合理队列大小)
  • 异步任务未记录日志(难以追踪问题)
  • CompletableFuture回调链中的空指针异常

12. 安全层(Security 层)

框架 :Spring Security、Shiro

配置要点

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
        .antMatchers("/admin/**").hasRole("ADMIN") // 权限配置
        .anyRequest().permitAll();
}

审计重点

  • URL权限配置遗漏(如 /actuator/** 未保护)
  • 密码存储策略(是否使用BCrypt加密)
  • CSRF Token未绑定到用户会话

13. 审计层(Audit 层)

实现方式@Audit 注解、AOP切面

审计要求

@Aspect
public class AuditAspect {
    @AfterReturning("execution(* com.example.service.*.*(..))")
    public void logAction(JoinPoint joinPoint) {
        // 未记录操作人ID和IP地址
    }
}
  • 关键操作日志缺失(如账户删除、权限变更)
  • 日志未脱敏(记录完整信用卡号)
  • 日志文件权限过宽(所有用户可读)

14. 过滤器层(Filter 层)

常见过滤器

  • 认证过滤器(AuthenticationFilter)
  • XSS防护过滤器
  • 请求日志过滤器

漏洞案例

public class XssFilter implements Filter {
    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {
        // 仅过滤POST参数,遗漏GET参数
    }
}

审计要点

  • 过滤顺序错误(如先执行业务逻辑后过滤)
  • 全局异常处理未覆盖过滤器中的异常
  • 敏感请求头(如Authorization)未清除

15. Servlet 层

核心对象 :HttpServletRequest、HttpServletResponse

风险代码

protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
    String param = req.getParameter("input");
    resp.getWriter().write(param); // 直接输出未过滤
}

审计重点

  • 自定义Servlet的URL映射冲突
  • 未禁用TRACE/TRACK方法
  • 响应头未设置安全策略(如Content-Security-Policy)

底层支撑

16. JDBC

定义

JDBC(Java Database Connectivity)是 Java 语言用于访问关系型数据库的 API,提供了一套标准接口,使 Java 应用程序能够与不同类型的数据库(如 MySQL、PostgreSQL、Oracle)进行交互。

风险代码

Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM users WHERE id=" + input); // SQL注入

防护措施

  • 使用PreparedStatement绑定参数
  • 验证数据库连接池配置(如maxActive限制)

17. Tomcat

定义

Tomcat 是一个开源的 Java Servlet 容器,用于运行 Java Web 应用程序(如 JSP 和 Servlet)。它实现了 Java EE 规范(如 Servlet、JSP),并提供 HTTP 服务器功能,广泛用于 Web 应用的部署和运行。

关键配置

<!-- server.xml 中禁用不必要协议 -->
<Connector port="8080" protocol="HTTP/1.1" 
           maxThreads="200" relaxedQueryChars="[]"/> <!-- 允许特殊字符可能引发解析问题 -->

审计重点

  • 禁用AJP协议(如不需要)
  • 错误页面未泄露版本信息
  • 会话固定防护配置

18. Maven

定义

Maven 是一个 项目管理和构建工具,用于管理 Java 项目的依赖、构建、测试和部署。它基于 pom.xml 文件定义项目结构,并通过 中央仓库(Maven Central)下载和管理第三方依赖组件,确保项目的可复现性和一致性。

依赖风险

<dependency>
    <groupId>commons-collections</groupId>
    <artifactId>commons-collections</artifactId>
    <version>3.2.1</version> <!-- 已知存在反序列化漏洞 -->
</dependency>

检查项

  • 使用 mvn dependency:tree 排查漏洞组件
  • 确保SNAPSHOT版本未上线生产环境
  • 仓库地址使用HTTPS协议