基于ASM的java自动化代码审计工具 ACAF(Auto Code Audit Framework)
字数 1805 2025-08-29 08:30:36

Java自动化代码审计工具ACAF教学文档

1. ACAF框架概述

ACAF (Auto Code Audit Framework) 是一个基于ASM的Java自动化代码审计工具,主要针对Spring Web项目进行安全审计。与传统的静态代码分析工具不同,ACAF通过模拟JVM执行字节码来实现污点的动态流动分析。

1.1 核心特点

  • 基于字节码分析:直接分析.class文件,无需源代码
  • 动态污点分析:模拟JVM执行过程跟踪污点传播
  • 可扩展性:用户只需提供漏洞示例代码即可扩展检测能力
  • 自动化程度高:相比CodeQL等工具使用更简单

1.2 与CodeQL的主要区别

特性 ACAF CodeQL
分析对象 字节码(.class文件) 源代码
使用复杂度 只需提供Java漏洞示例 需要编写QL查询语句
适用范围 专注于Spring Web项目 支持多种语言和框架
自动化程度 更高 需要更多人工参与

2. 核心原理

2.1 技术基础

ACAF基于以下关键技术构建:

  1. ASM库:用于解析和操作Java字节码
  2. JVM模拟执行:借鉴gadget-inspector的思路,用Java代码模拟JVM执行过程
  3. 污点分析:跟踪用户可控数据在程序中的传播路径

2.2 整体架构

+-------------------+    +-------------------+    +-------------------+
|   VulnTemplate    |    |   VulnDiscovery   |    |    Audit Core     |
|   SinkVisitor     |--->|   (特征存储)      |--->|   (审计执行)      |
+-------------------+    +-------------------+    +-------------------+
         ^                                                  |
         |                                                  v
+-------------------+                              +-------------------+
| 用户提供的Sink示例 |                              |   审计结果输出    |
+-------------------+                              +-------------------+

3. 使用方法

3.1 基本使用步骤

  1. 定义Sink示例:编写漏洞代码示例
  2. 配置污点传播:手动链接污点传播路径
  3. 创建配置类:注册Sink检测器
  4. 运行审计:启动ACAF进行扫描

3.2 完整示例

3.2.1 定义SSRF漏洞示例

package com.er1cccc.acaf.example.ssrf;

import com.er1cccc.acaf.config.ControllableParam;
import com.er1cccc.acaf.config.PassthroughRegistry;
import com.er1cccc.acaf.config.Sink;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import java.lang.reflect.Method;

public class SsrfSink4 implements Sink {
    private ControllableParam params = new ControllableParam();
    
    public SsrfSink4(){
        params.put("url", "http://localhost");
    }
    
    @Override
    public Object sinkMethod() throws Exception {
        OkHttpClient httpClient = new OkHttpClient();
        Request request = new Request.Builder()
            .url((String)params.getParameter("url"))
            .build();
        Response response = httpClient.newCall(request).execute();
        return null;
    }
    
    @Override
    public void addPassthrough(PassthroughRegistry passthroughRegistry) {
        try {
            Class<?> builder = new Request.Builder().getClass();
            Method urlMethod = builder.getMethod("url", String.class);
            Method buildMethod = builder.getMethod("build");
            Class<OkHttpClient> okHttpClientClass = OkHttpClient.class;
            Method newCall = okHttpClientClass.getMethod("newCall", Request.class);
            Class<?> call = newCall.getReturnType();
            Method execute = call.getMethod("execute");
            
            passthroughRegistry.addPassthrough(urlMethod, 1);
            passthroughRegistry.addPassthrough(buildMethod, 0);
            passthroughRegistry.addPassthrough(newCall, 1);
            passthroughRegistry.addPassthrough(execute, 0);
        } catch(Exception e){
            e.printStackTrace();
        }
    }
}

3.2.2 创建配置类

package com.er1cccc.acaf.example.ssrf;

import com.er1cccc.acaf.config.*;

public class SSRFConfigurer implements ACAFConfigurer {
    @Override
    public void addSource(SourceRegistry sourceRegistry) {
    }
    
    @Override
    public void addSanitize(SanitizeRegistry sanitizeRegistry) {
    }
    
    @Override
    public void addSink(SinkRegistry sinkRegistry) {
        sinkRegistry.addSink(new SsrfSink4());
    }
}

3.2.3 启动审计

package com.er1cccc.acaf.example;

import com.er1cccc.acaf.Launcher;
import com.er1cccc.acaf.example.ssrf.SSRFConfigurer;

public class App {
    public static void main(String[] args) throws Exception {
        Launcher.launch(new SSRFConfigurer(), args);
    }
}

4. 关键技术实现

4.1 漏洞特征抽取

特征抽取过程在VulnTemplateSinkVisitor中实现,主要流程:

  1. 识别可控参数:通过约定的params.getParameter()方法识别用户可控点
  2. 标记污点:将可控参数标记为污点(true)
  3. 跟踪传播:跟踪污点在方法调用间的传播路径
  4. 记录特征:将污点传播路径记录为特征

关键代码片段

// 在VulnTemplateSinkVisitor.VulnTemplateSinkMethodVisitor中
@Override
public void visitMethodInsn(String owner, String name, String descriptor, boolean isInterface) {
    if(isGetParamMethod(owner, name, descriptor)){
        super.visitMethodInsn(owner, name, descriptor, isInterface);
        super.setStackTaint(true); // 标记污点
    } else {
        List<Integer> controllableArgIndex = getControllableArgIndex(owner, name, descriptor);
        super.visitMethodInsn(owner, name, descriptor, isInterface);
        
        if(!controllableArgIndex.isEmpty()){
            // 记录方法调用特征
            compositResolver.addResolver(
                new VisitMethodInsnInfoResolver(owner, name, descriptor, controllableArgIndex)
            );
        } else if(super.getStackTaint(0)){
            // 记录返回值污点特征
            compositResolver.addResolver(
                new VisitMethodInsnInfoResolver(owner, name, descriptor, null)
            );
        }
    }
}

4.2 污点传播处理

ACAF通过PassthroughRegistry处理污点传播中的中断问题:

  1. 问题原因:gadget-inspector的默认污点传播规则不完善
  2. 解决方案:用户通过addPassthrough方法手动指定方法返回值与参数的关联关系

参数下标规则

  • 对于静态方法:0表示第一个参数
  • 对于非静态方法:0表示this,1表示第一个参数

4.3 自动化审计流程

  1. 收集Controller参数:作为污点源(Source)
  2. 深度优先搜索:跟踪污点传播路径
  3. 特征匹配:与从Sink示例中提取的特征进行比对
  4. 结果判定:完全匹配所有特征则判定为漏洞

审计核心代码

// 在VulnMethodAdapter中
@Override
public void visitMethodInsn(String owner, String name, String descriptor, boolean isInterface) {
    List<Integer> controllableArgIndex = getControllableArgIndex(owner, name, descriptor);
    super.visitMethodInsn(owner, name, descriptor, isInterface);
    
    if(vulnResolver.resolve(new VisitMethodInsnInfo(owner, name, descriptor, controllableArgIndex))){
        // 特征匹配成功,输出调用栈
        outputVulnCallStack();
    }
}

5. 实际应用案例

5.1 SSRF漏洞检测

ACAF可以检测多种SSRF实现方式,包括:

  1. OkHttpClient方式
  2. HttpURLConnection方式
  3. HttpClient方式等

5.2 检测效果

在测试项目中:

  • 正确识别4个真实的SSRF漏洞点
  • 对故意添加的fake sink没有误报
  • 能够处理Controller中的复杂参数类型

6. 扩展开发指南

6.1 添加新的漏洞检测

  1. 创建Sink实现类:编写漏洞示例代码
  2. 定义污点传播规则:实现addPassthrough方法
  3. 注册到配置类:在ACAFConfigurer中添加Sink

6.2 处理复杂场景

  1. 复杂参数类型:需要扩展污点源处理逻辑
  2. 误报处理:未来可通过实现SanitizeRegistry添加净化规则
  3. 多步骤漏洞:确保完整提取所有关键特征点

7. 总结与展望

ACAF提供了一种相对简单但有效的Java自动化代码审计方案,特别适合Spring Web项目的安全检测。其核心优势在于:

  1. 使用简单:只需提供Java代码示例即可扩展检测能力
  2. 准确性高:通过动态污点分析减少误报
  3. 适应性强:直接分析字节码,适用于各种构建环境

未来可能的改进方向:

  1. 内置更多常见漏洞的检测模板
  2. 增强对复杂代码逻辑的分析能力
  3. 支持更多类型的项目结构(如War包等)
  4. 添加误报消除机制(Sanitize)
Java自动化代码审计工具ACAF教学文档 1. ACAF框架概述 ACAF (Auto Code Audit Framework) 是一个基于ASM的Java自动化代码审计工具,主要针对Spring Web项目进行安全审计。与传统的静态代码分析工具不同,ACAF通过模拟JVM执行字节码来实现污点的动态流动分析。 1.1 核心特点 基于字节码分析 :直接分析.class文件,无需源代码 动态污点分析 :模拟JVM执行过程跟踪污点传播 可扩展性 :用户只需提供漏洞示例代码即可扩展检测能力 自动化程度高 :相比CodeQL等工具使用更简单 1.2 与CodeQL的主要区别 | 特性 | ACAF | CodeQL | |------|------|--------| | 分析对象 | 字节码(.class文件) | 源代码 | | 使用复杂度 | 只需提供Java漏洞示例 | 需要编写QL查询语句 | | 适用范围 | 专注于Spring Web项目 | 支持多种语言和框架 | | 自动化程度 | 更高 | 需要更多人工参与 | 2. 核心原理 2.1 技术基础 ACAF基于以下关键技术构建: ASM库 :用于解析和操作Java字节码 JVM模拟执行 :借鉴gadget-inspector的思路,用Java代码模拟JVM执行过程 污点分析 :跟踪用户可控数据在程序中的传播路径 2.2 整体架构 3. 使用方法 3.1 基本使用步骤 定义Sink示例 :编写漏洞代码示例 配置污点传播 :手动链接污点传播路径 创建配置类 :注册Sink检测器 运行审计 :启动ACAF进行扫描 3.2 完整示例 3.2.1 定义SSRF漏洞示例 3.2.2 创建配置类 3.2.3 启动审计 4. 关键技术实现 4.1 漏洞特征抽取 特征抽取过程在 VulnTemplateSinkVisitor 中实现,主要流程: 识别可控参数 :通过约定的 params.getParameter() 方法识别用户可控点 标记污点 :将可控参数标记为污点(true) 跟踪传播 :跟踪污点在方法调用间的传播路径 记录特征 :将污点传播路径记录为特征 关键代码片段 4.2 污点传播处理 ACAF通过 PassthroughRegistry 处理污点传播中的中断问题: 问题原因 :gadget-inspector的默认污点传播规则不完善 解决方案 :用户通过 addPassthrough 方法手动指定方法返回值与参数的关联关系 参数下标规则 对于静态方法:0表示第一个参数 对于非静态方法:0表示this,1表示第一个参数 4.3 自动化审计流程 收集Controller参数 :作为污点源(Source) 深度优先搜索 :跟踪污点传播路径 特征匹配 :与从Sink示例中提取的特征进行比对 结果判定 :完全匹配所有特征则判定为漏洞 审计核心代码 5. 实际应用案例 5.1 SSRF漏洞检测 ACAF可以检测多种SSRF实现方式,包括: OkHttpClient方式 HttpURLConnection方式 HttpClient方式等 5.2 检测效果 在测试项目中: 正确识别4个真实的SSRF漏洞点 对故意添加的fake sink没有误报 能够处理Controller中的复杂参数类型 6. 扩展开发指南 6.1 添加新的漏洞检测 创建Sink实现类 :编写漏洞示例代码 定义污点传播规则 :实现 addPassthrough 方法 注册到配置类 :在 ACAFConfigurer 中添加Sink 6.2 处理复杂场景 复杂参数类型 :需要扩展污点源处理逻辑 误报处理 :未来可通过实现SanitizeRegistry添加净化规则 多步骤漏洞 :确保完整提取所有关键特征点 7. 总结与展望 ACAF提供了一种相对简单但有效的Java自动化代码审计方案,特别适合Spring Web项目的安全检测。其核心优势在于: 使用简单 :只需提供Java代码示例即可扩展检测能力 准确性高 :通过动态污点分析减少误报 适应性强 :直接分析字节码,适用于各种构建环境 未来可能的改进方向: 内置更多常见漏洞的检测模板 增强对复杂代码逻辑的分析能力 支持更多类型的项目结构(如War包等) 添加误报消除机制(Sanitize)