论文状态:已完成

GPTScan: Detecting Logic Vulnerabilities in Smart Contracts by Combining GPT with Program Analysis

发表:2023/08/07
原文链接PDF 下载
价格:0.100000
价格:0.100000
已有 2 人读过
本分析由 AI 生成,可能不完全准确,请以原文为准。

TL;DR 精炼摘要

该论文提出了GPTScan,这是首个将GPT与静态分析结合用于智能合约逻辑漏洞检测的工具。通过将逻辑漏洞分解为场景和属性,GPTScan与GPT匹配候选漏洞,进一步指示GPT识别关键变量。评估结果显示,GPTScan在代币合约中精度超过90%,且有效检测到人类审计员遗漏的漏洞,表现出快速和成本效益高的优势。

摘要

Smart contracts are prone to various vulnerabilities, leading to substantial financial losses over time. Current analysis tools mainly target vulnerabilities with fixed control or data-flow patterns, such as re-entrancy and integer overflow. However, a recent study on Web3 security bugs revealed that about 80% of these bugs cannot be audited by existing tools due to the lack of domain-specific property description and checking. Given recent advances in Large Language Models (LLMs), it is worth exploring how Generative Pre-training Transformer (GPT) could aid in detecting logicc vulnerabilities. In this paper, we propose GPTScan, the first tool combining GPT with static analysis for smart contract logic vulnerability detection. Instead of relying solely on GPT to identify vulnerabilities, which can lead to high false positives and is limited by GPT's pre-trained knowledge, we utilize GPT as a versatile code understanding tool. By breaking down each logic vulnerability type into scenarios and properties, GPTScan matches candidate vulnerabilities with GPT. To enhance accuracy, GPTScan further instructs GPT to intelligently recognize key variables and statements, which are then validated by static confirmation. Evaluation on diverse datasets with around 400 contract projects and 3K Solidity files shows that GPTScan achieves high precision (over 90%) for token contracts and acceptable precision (57.14%) for large projects like Web3Bugs. It effectively detects ground-truth logic vulnerabilities with a recall of over 70%, including 9 new vulnerabilities missed by human auditors. GPTScan is fast and cost-effective, taking an average of 14.39 seconds and 0.01 USD to scan per thousand lines of Solidity code. Moreover, static confirmation helps GPTScan reduce two-thirds of false positives.

思维导图

论文精读

中文精读

1. 论文基本信息

1.1. 标题

GPTScan: 检测智能合约逻辑漏洞通过结合 GPT 与程序分析 (GPTScan: Detecting Logic Vulnerabilities in Smart Contracts by Combining GPT with Program Analysis)

1.2. 作者

  • Yuqiang Sun (南洋理工大学,新加坡)
  • Daoyuan Wu (南洋理工大学,新加坡)
  • Yue Xue (MetaTrust Labs,新加坡)
  • Han Liu (华东师范大学,上海,中国)
  • Haijun Wang (西安交通大学,西安,中国)
  • Zhengzi Xu (南洋理工大学,新加坡)
  • Xiaofei Xie (新加坡管理大学,新加坡)
  • Yang Liu (南洋理工大学,新加坡)

1.3. 发表期刊/会议

该论文发布在预印本服务器 arXiv 上,发布时间为 2023-08-07T05:48:53.000Z。arXiv 是一个广受认可的预印本平台,在计算机科学(特别是人工智能、软件工程、安全等领域)具有重要影响力,许多顶级会议和期刊的论文初稿都会先在此发布。

1.4. 发表年份

2023

1.5. 摘要

智能合约 (Smart Contracts) 容易受到各种漏洞的攻击,长期以来已导致巨大的经济损失。当前的分析工具主要针对具有固定控制流 (Control-Flow) 或数据流 (Data-Flow) 模式的漏洞,例如重入 (re-entrancy) 和整数溢出 (integer overflow)。然而,一项关于 Web3 安全漏洞的最新研究表明,约 80% 的此类漏洞无法通过现有工具进行审计,原因是缺乏特定领域属性描述和检查。鉴于大型语言模型 (LLMs) 的最新进展,探索生成式预训练 Transformer (Generative Pre-training Transformer, GPT) 如何辅助检测逻辑漏洞 (Logic Vulnerabilities) 变得具有研究价值。

本文提出了 GPTScan,这是首个结合 GPT 与静态分析 (Static Analysis) 用于智能合约逻辑漏洞检测的工具。GPTScan 并非完全依赖 GPT 来识别漏洞(这可能导致高假阳性率,并受限于 GPT 的预训练知识),而是将 GPT 用作一种通用的代码理解工具。通过将每种逻辑漏洞类型分解为场景 (scenarios) 和属性 (properties),GPTScan 将候选漏洞与 GPT 进行匹配。为了提高准确性,GPTScan 进一步指示 GPT 智能识别关键变量和语句,这些变量和语句随后通过静态确认 (Static Confirmation) 进行验证。在包含约 400 个合约项目和 3000 个 Solidity 文件的多样化数据集上进行的评估表明,GPTScan 在代币合约 (token contracts) 方面实现了高精度(超过 90%),对于 Web3Bugs 等大型项目也达到了可接受的精度(57.14%)。它能有效检测真实标注 (Ground-Truth) 的逻辑漏洞,召回率 (recall) 超过 70%,其中包括 9 个人类审计员遗漏的新漏洞。GPTScan 速度快、成本效益高,平均每扫描一千行 Solidity 代码仅需 14.39 秒和 0.01 美元。此外,静态确认帮助 GPTScan 减少了三分之二的假阳性 (False Positives)。

1.6. 原文链接

https://arxiv.org/abs/2308.03314v3 PDF 链接: https://arxiv.org/pdf/2308.03314v3.pdf 发布状态:预印本 (Preprint)

2. 整体概括

2.1. 研究背景与动机

智能合约作为去中心化金融 (DeFi) 的基石,虽然提供了可编程和自动化的金融交易解决方案,但其安全性一直是一个重大问题。历史上的安全漏洞已造成数十亿美元的经济损失,严重威胁到 DeFi 生态系统和用户资产安全。

现有的智能合约分析工具(如 Slither、Mythril 等)主要侧重于检测具有固定控制流或数据流模式的漏洞,例如重入、整数溢出和访问控制漏洞。然而,一项由 Zhang 等人 [65] 进行的 Web3 安全漏洞研究发现,高达 80% 的漏洞无法通过现有工具检测。这些未被检测的漏洞主要与智能合约的业务逻辑 (Business Logic) 相关。传统静态和动态分析方案无法有效解决这些问题,因为它们不旨在理解智能合约的底层业务逻辑,也无法对功能进行建模或考虑变量和函数的作用。

近年来,大型语言模型 (LLMs),特别是生成式预训练 Transformer (GPT) 模型,在代码理解方面取得了显著进展。这促使研究人员探索 GPT 如何辅助检测智能合约中的逻辑漏洞。然而,纯粹依赖 GPT 的方法存在局限性:

  1. 高假阳性率 (High False Positive Rate): David 等人 [34] 尝试使用 GPT 通过提供高级漏洞描述进行项目级的“是或否”查询,但这种方法产生了约 96% 的高假阳性率。

  2. 高级推理能力需求 (Demand for Advanced Reasoning): 纯 GPT 方法通常需要 GPT 具备高级的逻辑推理能力,这通常意味着需要更强大的模型(如 GPT-4 而非 GPT-3.5),从而增加了成本。

  3. 上下文长度限制 (Context Length Limitation): GPT 模型存在上下文长度限制(例如 GPT-3.5 的 4k 词元,GPT-4 的 32k 词元),使得直接将整个智能合约项目或长文档喂给 GPT 进行分析变得不可行或成本过高。

    鉴于这些挑战,本文的动机是探索如何将 GPT 的强大代码理解能力与传统静态分析技术相结合,以克服现有工具的局限性,并更准确、高效地检测智能合约中的逻辑漏洞。

2.2. 核心贡献/主要发现

本文提出了 GPTScan,这是首个结合 GPT 与静态分析来检测智能合约逻辑漏洞的工具。其核心贡献和主要发现包括:

  • 提出 GPTScan 框架: 设计并实现了 GPTScan,一个将 GPT 作为通用代码理解工具与静态分析相结合的框架。它通过将逻辑漏洞分解为代码级的场景 (scenarios) 和属性 (properties),利用 GPT 进行初步匹配,并通过静态分析进行精确确认。
  • 多维函数过滤机制: 开发了一种多维过滤过程,包括项目级文件过滤、OpenZeppelin 函数过滤和漏洞特定函数过滤,以有效缩小 GPT 匹配的候选函数范围,解决了 GPT 上下文长度限制和成本问题。
  • GPT-based 场景与属性匹配: 创新性地将漏洞类型分解为代码级场景和属性,使 GPT 能够直接从代码语义层面识别潜在漏洞,而非依赖高层描述。引入了“mimic-in-the-background”提示技巧,以减少 GPT 输出的随机性。
  • 结合静态确认的混合检测: 利用 GPT 智能识别关键变量和语句,然后通过专门的静态确认模块(数据流追踪、值比较检查、顺序检查、函数调用参数检查)验证漏洞是否存在,显著降低了假阳性率。
  • 高性能与成本效益:
    • 在非漏洞代币合约数据集 Top200 上实现了 4.39% 的低假阳性率。
    • 在包含真实漏洞的 DefiHacks 数据集上达到 90.91% 的高精度,在 Web3Bugs 等大型项目上达到 57.14% 的可接受精度。
    • 对于真实逻辑漏洞的检测,在 Web3Bugs 数据集上召回率为 83.33%,F1 分数为 67.8%;在 DefiHacks 数据集上召回率为 71.43%,F1 分数为 80%。
    • 平均每扫描一千行 Solidity 代码仅需 14.39 秒和 0.01 美元,证明了其高效和成本效益。
  • 新漏洞发现: GPTScan 成功发现了 9 个之前被人类审计员遗漏的新漏洞(其中 5 个为 Risky First Deposit,3 个为 Price Manipulation by AMM,1 个为 Front Running),凸显了其作为人类审计员有用补充的价值。
  • 静态确认的有效性: 实验证明,静态确认步骤将 Web3Bugs 数据集中三分之二的假阳性案例过滤掉,极大提高了检测准确性。
  • 可用性: GPTScan 已集成到行业领先的智能合约安全扫描平台 MetaScan 中。

3. 预备知识与相关工作

3.1. 基础概念

3.1.1. 智能合约 (Smart Contracts)

智能合约是部署在区块链 (Blockchain) 上,能够自动执行、控制或记录法律相关事件和行为的计算机协议。它们由高级语言 (High-Level Language) 编写,如 Solidity,一旦部署就不可篡改。它们是去中心化金融 (DeFi) 应用的基石,但在提供自动化和透明性的同时,其安全性也面临挑战。

3.1.2. 逻辑漏洞 (Logic Vulnerabilities)

逻辑漏洞是指智能合约在业务逻辑层面的缺陷,这些缺陷可能导致非预期的行为或资产损失。与重入、整数溢出等常见漏洞不同,逻辑漏洞通常不涉及固定的控制流或数据流模式,而是与合约特定的功能、变量角色和操作顺序紧密相关。由于其定制化和业务相关性,现有工具难以检测。本文关注的六大类逻辑漏洞包括:价格操纵 (Price Manipulation)、ID 相关违规 (ID-related Violations)、错误状态更新 (Erroneous State Updates)、原子性违规 (Atomicity Violation)、权限提升 (Privilege Escalation) 和错误会计 (Erroneous Accounting)。

3.1.3. 大型语言模型 (Large Language Models, LLMs)

LLMs 是一类基于 Transformer 架构的深度学习模型,通过在海量文本数据上进行预训练,学习语言的模式、语法、语义和世界知识。例如 GPT-3.5 和 GPT-4。它们能够理解、生成和处理人类语言,并在各种自然语言处理任务中表现出色。在代码领域,LLMs 也能理解和解释源代码,支持零样本学习 (Zero-Shot Learning) 和少样本学习 (Few-Shot Learning)。

3.1.4. 生成式预训练 Transformer (Generative Pre-training Transformer, GPT)

GPT 是 OpenAI 开发的一系列基于 Transformer 架构的 LLMs。它们通过预测下一个词元 (token) 进行预训练,从而学习语言的统计规律。在本文中,GPT 被用作一个强大的代码理解工具,能够识别代码语义,但其在逻辑推理和减少随机性方面存在挑战。

3.1.5. 静态分析 (Static Analysis)

静态分析是一种在不实际执行程序的情况下,通过检查程序源代码或编译后的二进制代码来查找错误和缺陷的方法。它可以分析程序的控制流、数据流、符号执行 (Symbolic Execution) 等。在智能合约安全领域,静态分析工具如 Slither、Mythril 被广泛用于检测已知模式的漏洞。本文将静态分析与 GPT 结合,用于精确确认 GPT 识别出的潜在漏洞。

3.1.6. 抽象语法树 (Abstract Syntax Tree, AST)

抽象语法树是源代码的抽象表示,以树状结构表示编程语言的语法结构。它消除了源代码中的不必要细节,同时保留了程序的结构信息。ANTLR 等工具可以用来解析源代码并生成 AST,进而进行程序分析,如构建调用图 (Call Graph) 和数据依赖图 (Data Dependence Graph)。

3.1.7. 假阳性 (False Positive, FP) 与假阴性 (False Negative, FN)

  • 假阳性 (FP): 指模型或工具错误地将非漏洞代码报告为漏洞。高假阳性率会增加人工审计的负担。
  • 假阴性 (FN): 指模型或工具未能检测到真实存在的漏洞。高假阴性率意味着潜在的安全风险。

3.1.8. 精度 (Precision)、召回率 (Recall) 和 F1 分数 (F1 Score)

这些是评估分类模型性能的常用指标。

  • 精度 (Precision): 衡量所有被报告为正例的样本中,有多少是真正的正例。在漏洞检测中,高精度意味着工具报告的漏洞大部分是真实的,减少了人工审查的负担。 Precision=True PositivesTrue Positives+False Positives \text{Precision} = \frac{\text{True Positives}}{\text{True Positives} + \text{False Positives}}
  • 召回率 (Recall): 衡量所有真正的正例中,有多少被模型成功识别。在漏洞检测中,高召回率意味着工具能够发现大部分真实存在的漏洞。 Recall=True PositivesTrue Positives+False Negatives \text{Recall} = \frac{\text{True Positives}}{\text{True Positives} + \text{False Negatives}}
  • F1 分数 (F1 Score): 精度和召回率的调和平均值,用于综合评估模型的性能,特别是在数据不平衡时。 F1 Score=2×Precision×RecallPrecision+Recall \text{F1 Score} = 2 \times \frac{\text{Precision} \times \text{Recall}}{\text{Precision} + \text{Recall}} 其中:
    • True Positives (TP):正确检测到的真实漏洞数量。
    • False Positives (FP):错误地报告为漏洞的非漏洞数量。
    • False Negatives (FN):未能检测到的真实漏洞数量。

3.2. 前人工作

3.2.1. 传统智能合约漏洞分析工具

  • Slither [37]: 一个针对 Solidity 智能合约的静态分析框架,专注于检测常见的漏洞模式,如重入、整数溢出和访问控制问题。然而,它不擅长理解业务逻辑相关的漏洞。

  • Mythril [13] / Manticore [47]: 符号执行 (Symbolic Execution) 工具,用于分析智能合约字节码和源代码,检测边界检查和漏洞。这些工具擅长检测具有固定模式的漏洞。

  • Ethainter [29], Zues [43], Securify [56]: 其他静态分析工具,也主要针对特定的漏洞模式或属性进行检测。

  • 动态分析 (Dynamic Analysis) 和模糊测试 (Fuzz Testing) [40, 41, 59, 63]: 通过自动生成测试用例或输入来在运行时发现异常行为。

  • 形式化验证 (Formal Verification) [51, 53]: 通过数学方法验证合约是否满足用户定义的规范。

    前人工作局限性: Zhang 等人 [65] 的研究指出,超过 80% 的可利用漏洞是机器无法检测的,这些漏洞通常与高层语义或业务逻辑紧密相关,而上述传统工具难以处理这类问题。

3.2.2. 基于 NLP/LLM 的漏洞检测

  • 早期 NLP 方法 [32, 33, 48, 55, 58]: 在 ChatGPT 出现之前,大多数基于自然语言处理 (NLP) 的漏洞检测方法涉及将代码输入到二分类或多分类模型中。
  • 基于 GPT 的漏洞检测 [34]: David 等人 [34] 尝试使用 GPT 通过向其提供高层漏洞描述来检测智能合约漏洞。他们使用 GPT-4-32k 模型分析整个项目,以检测 38 种漏洞。
    • 关键发现: 纯粹基于 GPT 的方法精度非常低(GPT-4 仅 4.14%,Claude 仅 4.30%),召回率也相对有限(GPT-4 43.84%)。这主要归因于 GPT 的固有问题,如幻觉 (Hallucination)、训练数据中的偏差以及问题描述的模糊性。
    • 挑战: 这种方法需要 GPT 具备高级推理能力,且受限于 GPT 的上下文长度,不适用于大型项目。

3.3. 技术演进

智能合约漏洞检测领域从早期的基于签名 (Signature-Based)、控制流/数据流分析的静态工具,逐渐发展到符号执行、形式化验证和动态模糊测试。然而,这些方法在理解和检测业务逻辑漏洞方面存在固有局限。随着 LLMs 的兴起,研究人员开始探索将其强大的代码理解能力应用于漏洞检测。本文的工作正是在这一背景下,试图弥合 LLMs 在语义理解上的优势与传统静态分析在精确验证上的优势之间的鸿沟,提出一种混合方法来解决传统工具无法有效处理的逻辑漏洞问题。

3.4. 差异化分析

GPTScan 与上述前人工作的核心区别和创新点在于:

  1. 混合方法 (Hybrid Approach): GPTScan 是第一个将 GPT 与静态分析相结合以检测智能合约逻辑漏洞的工具。它避免了纯粹依赖 GPT 导致的高假阳性问题,也弥补了纯静态分析无法理解高层语义的不足。
  2. GPT 的角色转变 (Shift in GPT's Role): 不同于 David 等人 [34] 将 GPT 视为一个高级推理引擎来直接判断漏洞,GPTScanGPT 定位为一个通用的代码理解工具。它利用 GPT 的语义理解能力来匹配抽象的场景和属性,并识别关键代码元素,而不是直接进行“是或否”的判断。
  3. 细粒度漏洞分解 (Fine-grained Vulnerability Decomposition): GPTScan 将逻辑漏洞类型分解为代码级的场景和属性,这使得 GPT 可以直接从代码语义层面进行匹配,降低了对 GPT 高级推理能力的需求,同时提高了匹配的精确度。
  4. 多维过滤与静态确认 (Multi-dimensional Filtering & Static Confirmation): 引入多维函数过滤机制,有效应对 GPT 的上下文长度和成本限制。更重要的是,通过静态确认模块对 GPT 识别出的关键变量和语句进行验证,显著降低了假阳性率,这是纯 GPT 方法所不具备的优势。
  5. 成本效益 (Cost-Effectiveness): 借助过滤机制,GPTScan 能够使用成本更低的 GPT-3.5-turbo 模型和默认的 4k 词元上下文,而不是更昂贵、上下文更大的 GPT-4 模型,使其更适合大规模应用。

4. 方法论

本节将详细阐述 GPTScan 的设计与实现,包括其整体工作流程、核心组件以及如何克服智能合约逻辑漏洞检测中的挑战。

4.1. 概述与挑战

GPTScan 的高层工作流程如以下图像(原文 Figure 3)所示:

该图像是一个示意图,展示了GPTScan工具在智能合约逻辑漏洞检测中的工作流程,包含多维过滤、候选函数匹配、识别关键变量和静态确认等步骤。

GPTScan 的工作流程概览:

  1. 合约解析 (Contract Parsing) & 过滤 (Filtering): 给定一个智能合约项目(可能包含多个 Solidity 文件),GPTScan 首先进行合约解析,然后执行调用图 (Call Graph) 分析以确定函数可达性 (Function Reachability),并进行多维过滤以提取候选函数 (Candidate Functions) 及其上下文函数。

  2. GPT 匹配 (GPT Matching): GPTScan 随后利用 GPT 将这些候选函数与预先抽象的漏洞类型的场景 (scenarios) 和属性 (properties) 进行匹配。

  3. 关键变量/语句识别 (Key Variable/Statement Recognition): 对于通过匹配的函数,GPTScan 进一步指示 GPT 智能识别其中的关键变量和语句。

  4. 静态确认 (Static Confirmation): 识别出的关键变量和语句被传递给专门的静态分析模块,进行漏洞确认。

    在上述三步过程中,GPTScan 需要解决三个主要挑战:

  • C1: 规模与成本问题: 智能合约项目可能包含数十个 Solidity 文件,直接将所有文件喂给 GPT 是不可行或成本高昂的。此外,非漏洞函数的存在可能会干扰 GPT 对漏洞函数的识别。因此,如何有效地缩小 GPT 匹配的候选函数范围至关重要。

  • C2: GPT 的语义理解与漏洞分解: 现有的 GPT 基于的漏洞检测方法通常向 GPT 提供高层漏洞描述进行匹配,这要么对 GPT 的高级推理能力要求过高,要么依赖于 GPT 预训练的漏洞知识。因此,如何以一种允许 GPT 作为通用代码理解工具直接从代码级语义识别漏洞的方式来分解漏洞类型?

  • C3: 结果可靠性与验证: 考虑到 GPT 可能会产生不可靠的答案或无法识别相似函数之间的细微差别,进一步确认匹配到的潜在漏洞变得至关重要。

    挑战 C1C3 都与 C2 相关。因此,GPTScan 首先解决 C2,然后分别解决 C1C3

4.2. GPT-based 场景与属性匹配

4.2.1. 将漏洞分解为场景与属性

现有的 GPT 基于的漏洞检测工作通常简单地向 GPT 提供高层漏洞描述,这使得 GPT 难以直接解释代码级语义。

GPTScan 采取了不同的方法,将漏洞类型分解为代码级场景和属性。

  • 场景 (Scenarios): 描述了可能发生逻辑漏洞的代码功能。

  • 属性 (Properties): 解释了脆弱代码的属性或操作。

    以下表格(原文 Table 1)展示了 GPTScan 如何将十种常见的逻辑漏洞类型分解为场景和属性:

    Vulnerability Type Scenario and Property Filtering Type Static Check
    Approval NotCleared Scenario: add or check approval via require/if statements before the token transferProperty: and there is no clear/reset of the approval when the transferfinishes its main branch or encounters exceptions FNI, FCCE VC
    Risky FirstDeposit Scenario: deposit/mint/add the liquidity pool/amount/shareProperty: and set the total share to the number of first deposit whenthe supply/liquidity is 0 FCCE DF, VC
    Price Manipulationby AMM Scenario: have code statements that get or calculate LP token's value/priceProperty: based on the market reserves/AMMprice/exchangeRate OR thecustom token balanceOf/totalSupply/amount/liquidity calculation FNK, FCCE DF
    Price Manipulationby Buying Tokens Scenario: buy some tokensProperty: using Uniswap/PancakeSwap APIs FNK, FCE FA
    Vote Manipulationby Flashloan Scenario: calculate vote amount/numberProperty: and this vote amount/number is from a vote weight that mightbe manipulated by flashloan FCCE DF
    Front Running Scenario: mint or vest or collect token/liquidity/earning and assign them tothe address recipient or to variableProperty: and this operation could be front run to benefit the account/addressthat can be controlled by the parameter and has no sender check in the function code FNK, FPNC, FPT, FCNE, FNM FA
    Wrong InterestRate Order Scenario: have inside code statements that update/accrue interest/exchange rateProperty: and have inside code statements that calculate/assign/distribute thebalance/share/stake/fee/loan/reward FCE, CEN OC
    WrongCheckpoint Order Scenario: have inside code statements that invoke user checkpointProperty: and have inside code statements that calculate/assign/distribute thebalance/share/stake/fee/loan/reward FCE, CEN OC
    Slippage Scenario: involve calculating swap/liquidity or adding liquidity, and there isasset exchanges or price queriesProperty: but this operation could be attacked by Slippage/Sandwich Attack due to noslip limit/minimum value check FCCE, FCNCE VC
    UnauthorizedTransfer Scenario: involve transfering token from an address different from message senderProperty: and there is no check of allowance/approval from the address owner FNK, FCNE, FCE, FCNCE, FPNC VC

分解过程的思考:

  1. 初步筛选: 场景的第一部分描述了函数的功能性,帮助 GPTScan 进行初步筛选,减少不必要的扫描。例如,Front Running 漏洞要求函数涉及铸造 (minting)、归属 (vesting) 或转移其他用户代币等操作。
  2. 根源描述: 场景的第二部分描述了与漏洞根源相关的函数行为,如缺少安全检查或错误的会计顺序。如果函数满足场景(第一部分),GPTScan 会再次将函数发送给 GPT,检查是否同时满足场景和属性。
  3. 自动化生成 (未来工作): 本文手动分解了十种漏洞类型。未来计划采用基于 GPT-4 的方法自动从历史漏洞报告中提取初步的场景和属性语句,并通过原始漏洞代码进行验证和迭代生成。

4.2.2. 是或否的场景与属性匹配 (Yes-or-No Scenario and Property Matching)

GPTScan 使用抽象的场景和属性通过 GPT 匹配候选函数。以下图像(原文 Figure 4)展示了 GPTScan 用于场景和属性匹配的提示模板:

Figure 4: Prompt for scenario and property matching.

提示模板设计考虑:

  1. 分离匹配: 属性匹配只针对通过场景匹配的函数进行。这种分离使得 GPTScan 可以在一个提示中查询所有场景,从而节省 GPT 成本。
  2. 双重确认: 在属性匹配阶段,GPTScan 通过查询场景和属性的组合(而不是单独查询属性)来再次确认场景,以确保完整性。
  3. 限制回答格式: 场景和属性匹配被设计为“是或否”问题,旨在最小化非结构化 GPT 响应的影响。
  4. JSON 输出: GPTScan 指示 GPT 学习输出 JSON 格式,以利用 GPT 的指令学习能力。

4.2.3. 最小化 GPT 输出随机性 (Minimizing the Impact of GPT Output Randomness)

尽管使用“是或否”问题限制了 GPT 响应的格式,但 GPT 模型固有的随机性可能导致对相同问题给出不同答案。

  • 温度参数: GPTScanGPT 模型的 temperature 参数设置为 0,使模型倾向于确定性输出。
  • “幕后模仿”提示 (Mimic-in-the-Background Prompting): 借鉴了零样本思维链 (Zero-Shot Chain-of-Thought) 提示中“让我们一步一步思考”的成功经验 [44],GPTScan 提出了一种“幕后模仿”提示技巧。如 Figure 4 所示,GPTScan 使用 GPT 系统提示来指示模型在后台模拟回答问题五次,并提供出现频率最高的答案,以确保更高的一致性。

4.3. 多维函数过滤 (Multi-dimensional Function Filtering)

为了解决挑战 C1(大规模与成本问题),GPTScanGPT 匹配之前,采用多维过滤来系统地选择候选函数,并进行可达性分析以保留可能被攻击者访问的函数。

4.3.1. 项目级文件过滤 (Project-wide File Filtering)

多维过滤从项目级文件过滤开始,排除:

  • 非 Solidity 文件(例如,node_modules 目录下的文件)。
  • 测试文件(例如,各种 test 目录中的文件)。
  • 第三方库文件(例如,来自知名库如 openzeppelinuniswappancakeswap 的文件)。 通过此过滤,GPTScan 能够专注于项目自身的 Solidity 文件。

4.3.2. 过滤 OpenZeppelin 函数 (Filtering out OpenZeppelin Functions)

OpenZeppelin [26] 提供了一套用于构建安全智能合约的库,被广泛使用。尽管已过滤作为库导入的 OpenZeppelin 合约,但发现 OpenZeppelin 函数常被直接复制到开发者的合约代码中。

  • 离线分析: GPTScan 首先对 OpenZeppelin 源代码进行离线分析,提取所有 API 函数签名作为白名单。每个签名包含访问控制修饰符 (Access Control Modifier)、类名 (Sub-Contract Name)、函数名、返回值类型和参数类型。例如,ERC20 合约中 transfer 函数的签名是 public ERC20.transfer(address,uint256)
  • 签名比较: GPTScan 生成所有候选函数的签名,并与白名单中的签名进行比较。候选函数的签名会包含类名和继承类名,因为开发者可能实现了继承类。通过这种比较,GPTScan 排除与白名单中函数签名相同的函数,将其视为安全函数。未来计划增加覆盖函数体的基于克隆的过滤。

4.3.3. 漏洞特定函数过滤 (Vulnerability-specific Function Filtering)

在项目级文件和 OpenZeppelin 过滤之后,GPTScan 对不同漏洞类型进行函数级过滤,这是多维过滤的主要部分。GPTScan 设计了 YAML 格式的过滤规则规范,支持以下过滤规则:

  • FNK (Function Name Keyword):函数名应包含至少一个关键词。

  • FCE (Function Content Expression):函数内容应包含至少一个表达式。

  • FCNE (Function Content Not Expression):函数内容不应包含任何表达式。

  • FCCE (Function Content Combination of Expressions):函数内容应包含给定表达式的至少一个组合。

  • FCNCE (Function Content Not Combination of Expressions):函数内容不应包含给定表达式的任何组合。

  • FPT (Function Parameters Type):函数参数应匹配给定类型。

  • FPNC (Function Public, Not Caller):函数为公共 (Public) 类型,不分析其调用者 (Caller)。

  • FNM (Function No Modifier):函数不应包含带有访问控制的修饰符 (Modifiers) (例如 onlyOwner)。

  • CFN (Caller Function Not Analyzed):此函数的调用者将不被分析。

    这些过滤规则涵盖了基本函数名 (FNK)、详细函数内容 (FCEFCNEFCCEFCNCE)、函数参数 (FPT) 和函数的调用者关系 (FPNCFNMCFN)。不同漏洞将使用其特定的过滤规则。过滤器的选择主要基于对漏洞类型的领域知识 (Domain Knowledge)。例如,Figure 1 中展示的 Risky First Deposit 漏洞仅使用 FCCE 规则类型来选择“total”、“supply”和“liquidity”的任何组合(无论是单独出现还是共同出现),以确保存款与代币的总供应量或流动性计算相关。

4.3.4. 可达性分析 (Reachability Analysis)

过滤后,GPTScan 进行调用图分析以确定候选函数的可达性。

  • AST 生成: GPTScan 利用 ANTLR [21](一个词法分析器和解析器生成器)解析智能合约项目的源代码并生成抽象语法树 (AST)。
  • 调用图构建: 使用 AST,为整个项目构建调用图。
  • 访问控制: Solidity 中有四种访问控制注解:publicexternalinternalprivate
    • publicexternal 函数可被任何人调用,直接对攻击者可达。
    • internalprivate 函数可能被其他可达函数调用,因此分析其可达性,如果可达则包含。
    • 带有自定义修饰符(如 onlyOwner)的函数被视为不可达。
  • 排除不可达函数: 被判定为不可达的函数将从后续的 GPT 匹配中排除。

4.4. 从 GPT 识别到静态确认 (From GPT Recognition to Static Confirmation)

尽管候选函数通过了初步过滤和基于 GPT 的函数属性匹配,但 GPT 并不总是关注语法细节,如条件语句 (conditional statements)、require 语句、assert 语句、revert 语句等。因此,需要更细粒度的静态分析来识别潜在的漏洞函数。静态分析工具通常关注特定的变量或语句,而当前的输入仍然是函数。这就是需要 GPT 辅助提取与提示中描述的特定业务逻辑相关的变量和语句的地方。有了这些变量和语句,就可以使用静态分析来确认漏洞是否存在。

以下图像(原文 Figure 5)展示了发送给 GPT 以请求 Risky First Deposit 相关变量或表达式的提示示例:

Figure 5: A prompt for finding related variables/statements.

GPT 识别过程:

  1. 变量/语句提取: GPTScan 指示 GPT 识别与特定业务逻辑(通过提示描述)相关的变量和语句。

  2. 短描述与验证: 对于每个提取的变量或语句,GPTScan 指示 GPT 提供一个简短描述。此描述有助于确定给定变量是否与问题相关,并避免不正确的答案。如果 GPT 提供的变量或语句在函数上下文中不存在,或者描述与所问问题不相关,GPTScan 将终止判断过程,并认为不存在该漏洞。

  3. 静态分析确认: 如果提供的变量和语句通过验证,GPTScan 将它们输入到静态分析工具中,使用静态数据流追踪和静态符号执行等方法确认漏洞的存在。

    GPTScan 设计了以下四种主要的静态分析类型来验证 Table 1 中列出的常见逻辑漏洞:

4.4.1. 静态数据流追踪 (Static Data Flow Tracing, DF)

此方法追踪程序中变量的数据流。静态分析确定 GPT 提供的两个变量或表达式之间是否存在数据依赖关系。

  • 示例:Risky First Deposit 漏洞中,Figure 1 显示需要数据流分析来确定份额 (_shares) 是否直接通过存款金额 (_amount) 计算。

4.4.2. 值比较检查 (Value Comparison Check, VC)

此方法检查两个变量或表达式是否在条件语句(如 requireassertif)中进行比较。它用于确保变量或表达式在使用前经过适当检查。

  • 示例:Risky First Deposit 中,VC 用于检查份额是否与存款金额进行比较。同样,在 Unauthorized Transfer (未经授权的转账) 中,VC 用于验证转账前是否已检查发送者。

4.4.3. 顺序检查 (Order Check, OC)

此方法检查两个语句的执行顺序。静态分析确定 GPT 提供的两个语句的顺序。

  • 示例:Wrong Checkpoint Order (错误检查点顺序) 中,Figure 2 显示 OC 用于验证执行转账和更新检查点的执行顺序。

4.4.4. 函数调用参数检查 (Function Call Argument Check, FA)

此方法检查函数调用的参数是否可由用户控制或满足特定要求。具体来说,GPT 提供一个函数调用和参数索引,静态分析确定该参数是否可由用户控制或满足规则中描述的要求。

  • 示例:Price Manipulation by Buying Tokens (通过购买代币进行价格操纵) 中,函数调用需要通过 FA 进行检查,因为一些敏感变量可能被用作参数并导致价格操纵。

4.5. 实现细节

GPTScan 主要用 Python (3,640 行代码) 和 Java/Kotlin (154 行代码) 实现。

4.5.1. GPT 模型及其参数

  • 模型选择: 开发和测试过程中使用了 OpenAI 的 GPT-3.5-turbo 模型 [27]。
  • 上下文大小: 借助 S4.3 中引入的多维过滤,GPTScan 可以使用默认的 4k 词元上下文大小,而不是 16k,从而实现了更具成本效益的解决方案。
  • 参数设置:
    • TopP 设为 1。
    • Frequency Penalty 设为 0。
    • Presence Penalty 设为 0。
    • Temperature 参数从默认值 1 调整为 0,以最小化 GPT 输出的随机性。
  • 会话管理: 每次 GPT 查询时,问题都会以空会话发送,以确保之前的问答不会影响当前问题。

4.5.2. 静态分析工具支持

  • AST 生成: 使用 ANTLR [21] 解析 Solidity 源代码并生成抽象语法树 (AST)。ANTLR 能够在不需要编译的情况下进行源代码分析,对于依赖有限且没有构建脚本的源代码,比依赖编译的工具(如 Slither [37])更有效。
  • 数据依赖分析: 为了确定两个变量或表达式之间的数据依赖关系,GPTScan 采用了基于 crytic-compiler [7] 输出的静态分析工具 [23]。crytic-compiler 是一个能够为静态分析生成标准 AST 的 Solidity 编译器。通过这种方法,GPTScan 可以构建控制流图 (Control Flow Graph) 和数据依赖图 (Data Dependence Graph)。

5. 实验设置

本节将详细介绍 GPTScan 的实验设置,包括使用的数据集、评估指标以及对比基线。

5.1. 数据集

实验使用了三个从真实世界智能合约中收集的多样化数据集,如下表格(原文 Table 2)所示:

Dataset Name Projects P Files F F/P LoC Vuls
Top200 303 555 1.83 134,322 0
Web3Bugs 72 2,573 35.74 319,878 48
DefiHacks 13 29 2.23 17,824 14
Sum 388 3,157 8.14 472,024 62
  • Top200:

    • 来源: 包含市值前 200 的智能合约,共 303 个开源合约项目,来自六个主流以太坊兼容链 [62]。
    • 特点: 这些项目经过良好审计并被广泛使用,因此被认为是无显著漏洞的。
    • 用途: 主要用于测试 GPTScan 在已审计合约中的假阳性率 (False Positive Rate)
    • 代码示例: 由于 Top200 包含的是成熟项目,通常不会提供具有明显漏洞的特定代码示例,而是作为通用代码库进行测试。
  • Web3Bugs:

    • 来源: 从最新的 Web3Bugs 数据集 [8, 65] 中收集,该数据集包含 100 个在 Code4rena 平台 [10] 审计的项目。其中 72 个可直接编译的项目被纳入。
    • 特点: 包含大型合约项目,平均每个项目有 36 个 Solidity 文件,共包含 48 个真实标注 (Ground-Truth) 的逻辑漏洞。
    • 用途: 用于评估 GPTScan 在复杂大型项目上检测真实漏洞的有效性。
    • 代码示例: 论文中 Figure 1 和 Figure 2 提供的例子均来自 Web3Bugs 数据集。
      • 示例 1 (Risky FirstDeposit):

        function deposit(uint256 _amount) external returns (uint256) {
          uint256 _pool = balance();
          uint256 _before = token.balanceOf(address(this));
          token.safeTransferFrom(msg.sender, address(this), _amount);
          uint256 _after = token.balanceOf(address(this));
          _amount = _after.sub(_before); // Additional check for deflationary tokens
          uint256 _shares = 0;
          if (totalSupply() == 0) { // <- 漏洞点
            _shares = _amount; // <- 漏洞点:当totalSupply为0时,第一个存款者可以任意铸造份额
          } else {
            _shares = (_amount.mul(totalSupply())).div(_pool);
          }
          _mint(msg.sender, _shares);
        }
        

        此示例来自 Code4rena 项目 2021-11-yaxis [2],展示了当 totalSupply() 为 0 时,第一个存款者可以铸造与其存款量 (_amount) 相等的份额,但这个份额可能与实际价值不符,导致后续存款者的份额被稀释。

      • 示例 2 (Wrong Checkpoint Order):

        function transfer(address account, uint256 amount) external override notPaused returns (bool) {
          require(msg.sender != account, Error.SELF_TRANSFER_NOT_ALLOWED);
          require(balances[msg.sender] >= amount, Error.INSUFFICIENT_BALANCE);
          // Initialize the ILiquidityPool pool variable
          pool.handleLpTokenTransfer(msg.sender, account, amount);
          balances[msg.sender] -= amount; // <- 余额更新
          balances[account] += amount;   // <- 余额更新
          address lpGauge = currentAddresses[_LP_GAUGE];
          if (lpGauge != address(0)){
            ILpGauge(lpGauge).userCheckpoint(msg.sender); // <- 检查点更新
            ILpGauge(lpGauge).userCheckpoint(account);    // <- 检查点更新
          }
          emit Transfer(msg.sender, account, amount);
          return true;
        }
        

        此示例来自 Code4Rena 项目 2022-04-backd [16],展示了在 transfer 函数中,用户检查点 (userCheckpoint) 的执行发生在余额更新 (balances[msg.sender]=amount;balances[msg.sender] -= amount;) 之后,导致奖励计算错误,用户可能窃取所有奖励。正确的顺序应是先更新检查点再更新余额。

  • DefiHacks:

    • 来源: 从知名的 DeFi Hacks 数据集 [9] 中收集,该数据集包含过去遭受攻击事件的脆弱代币合约。选择了 13 个明确涵盖本文十种漏洞类型的项目。

    • 特点: 包含 14 个真实逻辑漏洞,主要由加密货币代币合约项目组成,平均每个项目 2 个 Solidity 文件。

    • 用途: 用于评估 GPTScan 在已知被利用的漏洞合约上的检测能力。

    • 代码示例: 论文中 Figure 6, 7, 8 展示的新发现漏洞示例,它们是 DefiHacks 数据集中的补充。

      编译设置: 所有项目均使用 crytic-compiler [7] 以默认配置进行编译。值得注意的是,Top200 数据集中有 17 个项目无法用 crytic-compiler 编译。对于这些项目,GPTScan 的静态确认部分无法应用,任何受影响的漏洞类型都将被标记为未检测到。

5.2. 评估指标

本论文主要使用以下评估指标来衡量 GPTScan 的性能:

  1. 真阳性 (True Positives, TP):

    • 概念定义:GPTScan 成功检测到的真实存在的漏洞数量。
    • 数学公式: 无独立公式,是一个计数。
    • 符号解释: TP = 成功识别的真实漏洞实例数。
  2. 真阴性 (True Negatives, TN):

    • 概念定义:GPTScan 正确地没有报告为漏洞的非漏洞数量。
    • 数学公式: 无独立公式,是一个计数。
    • 符号解释: TN = 未被报告且确实不存在漏洞的实例数。
  3. 假阳性 (False Positives, FP):

    • 概念定义:GPTScan 错误地将不存在漏洞的代码报告为漏洞的数量。高 FP 会增加人工审查的负担。
    • 数学公式: 无独立公式,是一个计数。
    • 符号解释: FP = 错误识别为漏洞的非漏洞实例数。
  4. 假阴性 (False Negatives, FN):

    • 概念定义:GPTScan 未能检测到的真实存在的漏洞数量。高 FN 意味着存在潜在的安全风险。
    • 数学公式: 无独立公式,是一个计数。
    • 符号解释: FN = 未被识别的真实漏洞实例数。
  5. 假阳性率 (False Positive Rate):

    • 概念定义: 衡量所有实际为阴性的样本中,被错误地预测为阳性的比例。在漏洞检测中,它表示非漏洞合约被误报为漏洞的比例。
    • 数学公式: False Positive Rate=False PositivesFalse Positives+True Negatives \text{False Positive Rate} = \frac{\text{False Positives}}{\text{False Positives} + \text{True Negatives}}
    • 符号解释: False Positives 为假阳性数量,True Negatives 为真阴性数量。
  6. 精度 (Precision):

    • 概念定义: 衡量所有被 GPTScan 报告为漏洞的案例中,有多少是真正的漏洞。高精度表明报告结果的可靠性。
    • 数学公式: Precision=True PositivesTrue Positives+False Positives \text{Precision} = \frac{\text{True Positives}}{\text{True Positives} + \text{False Positives}}
    • 符号解释: True Positives 为真阳性数量,False Positives 为假阳性数量。
  7. 召回率 (Recall):

    • 概念定义: 衡量所有真实存在的漏洞中,有多少被 GPTScan 成功检测到。高召回率表明工具能发现大部分真实漏洞。
    • 数学公式: Recall=True PositivesTrue Positives+False Negatives \text{Recall} = \frac{\text{True Positives}}{\text{True Positives} + \text{False Negatives}}
    • 符号解释: True Positives 为真阳性数量,False Negatives 为假阴性数量。
  8. F1 分数 (F1 Score):

    • 概念定义: 精度和召回率的调和平均值。它综合考虑了精度和召回率,在两者之间取得平衡,尤其适用于类别不平衡的情况。
    • 数学公式: F1 Score=2×Precision×RecallPrecision+Recall \text{F1 Score} = 2 \times \frac{\text{Precision} \times \text{Recall}}{\text{Precision} + \text{Recall}}
    • 符号解释: Precision 为精度,Recall 为召回率。

5.3. 对比基线

论文将 GPTScan 的性能与以下现有工具进行了比较:

  1. Slither [37]:

    • 代表性: 一个广泛使用的开源静态分析框架,拥有超过百个漏洞检测规则。
    • 比较的规则: 针对 GPTScanUnauthorized Transfer 漏洞,Slither 中相关的规则包括 unchecked-transferarbitrary-send-etharbitrary-send-erc20
    • 局限性: 论文发现 Slither 在这些相关规则上产生了大量假阳性,且无法正确检测 Unauthorized Transfer 的变体行为。它不关联调用链信息,也无法很好地理解代码语义。
  2. MetaScan 的在线静态扫描服务 (MScan) [19, 23]:

    • 代表性: 这是一个商业级的静态扫描服务,也拥有上百个漏洞检测规则。
    • 比较的规则: 针对 GPTScanPrice Manipulation 漏洞,MScan 包含两个相关的价格操纵漏洞规则。
    • 局限性: MScanPrice Manipulation 方面达到了 100% 的精度,但召回率较低 (58.33%),且无法检测其他类型的逻辑漏洞。这是因为它主要依赖硬编码模式(包括特定函数和变量名的匹配),在模式不适用时无法泛化。
  3. 纯 GPT-based 方法 (David et al. [34]):

    • 代表性: 这是当时唯一可用的基于 GPT 的漏洞检测研究,代表了纯 LLM 解决方案的性能。

    • 比较方式: 由于该工具未发布,论文依据其研究报告中提供的统计数据进行比较。

    • 关键发现: 该方法在 GPT-4-32k 模型下实现了 4.14% 的精度、43.84% 的召回率和 7.57% 的 F1 分数;在 Claude-v1.3-100k 模型下则为 4.30% 的精度、35.62% 的召回率和 7.68% 的 F1 分数。其假阳性率远高于 GPTScan

    • 原因:GPT 方法没有像 GPTScan 那样对 GPT 输出进行验证,更容易受到 GPT 固有的问题(如幻觉、训练数据偏差和问题模糊性)的影响。

      选择这些基线的原因是它们代表了现有智能合约漏洞检测领域的不同方法:传统的开源静态分析工具 (Slither)、商业静态分析服务 (MScan) 和新兴的纯 GPT 解决方案。通过与这些基线进行比较,论文旨在全面展示 GPTScan 在解决逻辑漏洞问题上的优势。

6. 实验结果与分析

本节将详细分析 GPTScan 的实验结果,以回答前文提出的五个研究问题。

6.1. 核心结果分析

以下表格(原文 Table 3)展示了 GPTScan 在三个数据集上的整体精度评估结果:

Dataset Name TP TN FP FN Sum
Top200 0 283 13 0 296
Web3Bugs 40 154 30 8 232
DefiHacks 10 19 1 4 34
  • TP (True Positives): GPTScan 成功检测到的真实漏洞函数数量。
  • TN (True Negatives): GPTScan 正确地没有报告为漏洞的函数数量。
  • FP (False Positives): GPTScan 错误地报告为漏洞的函数数量。
  • **FN (False Negatives):GPTScan 未能检测到的真实漏洞函数数量。
  • Sum: 对于每个项目,如果测试了五种漏洞类型,那么 TP、TN、FP、FN 的总和应为 5。更具体地说,Sum 是针对每个数据集计算出的总测试实例数(项目数乘以漏洞类型数)。

6.1.1. RQ1: 衡量非漏洞顶级合约中的假阳性

  • 目的: 评估 GPTScan 在分析非漏洞合约时的误报率,以便在大规模链上合约扫描中最小化人工审查。
  • 结果分析:
    • Top200 数据集(303个非漏洞合约项目)上,GPTScan 报告了 13 个 FP 和 283 个 TN
    • GPTScan 在分析 Top200 等非漏洞顶级合约时的假阳性率 (False Positive Rate)4.39%4.39\%13/(13+283)13 / (13 + 283))。
    • GPTScan 在分析 DefiHacks(也是代币合约,平均每个项目约 2 个 Solidity 文件)时,精度 (Precision) 达到 90.91%90.91\%10/(10+1)10 / (10 + 1))。
    • 在分析 Web3Bugs(大型项目,平均每个项目 36 个 Solidity 文件)时,精度降至 57.14%57.14\%40/(40+30)40 / (40 + 30))。
  • 结论: GPTScan 在分析代币合约(如 Top200DefiHacks)时,具有低假阳性率和高精度,表明其适用于大规模链上代币合约扫描。对于大型复杂项目,精度有所下降,但仍可接受。这一下降可能因为 Web3Bugs 中的智能合约代码更加多样化。

6.1.2. RQ2: 检测漏洞合约的有效性与现有工具的比较

  • 目的: 评估 GPTScanWeb3BugsDefiHacks 数据集上检测漏洞的有效性,并与现有工具进行比较。
  • 结果分析:
    • Web3Bugs 数据集:
      • 总共分析了 232 种漏洞类型实例,检测到 40 个 TP,漏报 8 个 FN,产生 30 个 FP
      • 召回率 (Recall)83.33%83.33\%40/(40+8)40 / (40 + 8))。
      • F1 分数 (F1 Score)67.8%67.8\%
    • DefiHacks 数据集:
      • 总共分析了 34 种漏洞类型实例,检测到 10 个 TP,漏报 4 个 FN,产生 1 个 FP
      • 召回率 (Recall)71.43%71.43\%10/(10+4)10 / (10 + 4))。
      • F1 分数 (F1 Score)80%80\%
  • 结论: GPTScan 在检测这些真实逻辑漏洞方面表现出高效性。
  • 假阴性 (FN) 根源分析: 12 个 FN 中,4 个是 Price Manipulation by AMM,3 个是 Risky First Deposit。主要原因是 GPTScan 在静态检查中未实现别名分析 (Alias Analysis),导致静态数据流追踪失败。此外,Front Running (2 例) 的场景或属性匹配不准确,Slippage (2 例) 和 Unauthorized Transfer (1 例) 存在多种变体或 GPT 未能区分注释与代码不一致。
  • 假阳性 (FP) 根源分析: 在 44 个 FP 中:
    • 15 个 (34.09%) 是 Price Manipulation by AMM,11 个 (25.00%) 是 Unauthorized Transfer。这些漏洞往往需要涉及多函数调用的特定触发条件,超出了单个函数及其调用者/被调用者的范围。
    • 5 个 Risky First Deposit 和 5 个 SlippageRisky First Deposit 是由于代码段过长,GPT 难以准确理解。Slippage 则因检查逻辑链复杂且变体众多。
    • 4 个 Wrong Interest Rate Order,3 个 Approval Not Cleared 和 1 个 Wrong Checkpoint Order。这些漏洞与项目业务逻辑紧密相关,难以在缺乏全面项目设计知识的情况下减少误报。Approval Not Cleared 是因为函数可能并非总是用于转账代币。
  • 与现有工具的比较:
    • Slither: 在所有三个数据集上产生了 13,144 个警告,其中与 Unauthorized Transfer 相关的仅 146 个,但全部为假阳性。原因在于 Slither 不关联调用链信息,且无法正确检测转账行为的变体。
    • MScan:DefiHacks 数据集上,对 Price Manipulation 实现了 100%100\% 的精度和 58.33%58.33\% 的召回率。但它没有检测到其他类型的逻辑漏洞。MScan 依赖硬编码模式,无法泛化检测变体。
    • 纯 GPT-based 方法 (David et al. [34]): GPT-4-32k 模型精度为 4.14%4.14\%,召回率 43.84%43.84\%,F1 分数 7.57%7.57\%Claude-v1.3-100k 模型精度为 4.30%4.30\%,召回率 35.62%35.62\%,F1 分数 7.68%7.68\%。这些结果的假阳性率显著高于 GPTScan,主要是因为它们没有对 GPT 输出进行验证。
  • 回答 RQ2: GPTScanWeb3Bugs 数据集上召回率为 83.33%83.33\%、F1 分数为 67.8%67.8\%;在 DefiHacks 数据集上召回率为 71.43%71.43\%、F1 分数为 80%80\%,表现优于现有静态和纯 GPT 工具。

6.1.3. RQ3: 静态确认的有效性

  • 目的: 分析静态确认如何减少纯 GPT 匹配产生的假阳性。

  • 结果分析: 以下表格(原文 Table 4)展示了静态确认前后 GPTScan 报告的原始函数数量:

    Vulnerability Type Before After
    Approval Not Cleared 34 12
    Risky First Deposit 100 21
    Price Manipulation by AMM 187 114
    Price Manipulation by Buying Tokens 8 8
    Vote Manipulation by Flashloan 2 0
    Front Running 6 4
    Wrong Interest Rate Order 150 11
    Wrong Checkpoint Order 49 1
    Slippage 99 42
    Unauthorized Transfer 12 8
    Total 647 221
    • 在静态确认之前,共有 647 个原始函数被 GPT 匹配为潜在漏洞。
    • 经过静态确认后,仅剩下 221 个函数。这表明静态确认成功过滤掉了三分之二的假阳性案例 ((647221)/64765.84% (647 - 221) / 647 \approx 65.84\% )。
    • 对特定漏洞类型的效果: 静态确认对于 Wrong Interest Rate OrderWrong Checkpoint OrderRisky First Deposit 等漏洞类型尤其有效。这些类型的场景和属性描述较为粗粒度,导致大量候选函数通过 GPT 匹配。静态确认通过进一步识别相关语句和变量,过滤掉了不满足漏洞类型的函数。
    • 对假阴性的影响: 在被过滤掉的 426 个案例中,只有 3 个真实漏洞案例是先被 GPT 匹配但后来被静态分析排除,导致 3 个假阴性。另一个假阴性与编译问题有关,其余 4 个未通过 GPT 场景和属性匹配。这表明静态确认对假阴性的影响很小。
  • 回答 RQ3: 静态确认有效过滤掉了 Web3Bugs 数据集中 65.84%65.84\% 的假阳性案例,而对假阴性案例的影响很小。

6.1.4. RQ4: 性能和财务开销

  • 目的: 评估 GPTScan 在使用 OpenAI 的 GPT-3.5-turbo API 时的运行时间和财务成本。

  • 结果分析: 以下表格(原文 Table 5)展示了 GPTScan 的运行时间和财务成本:

    Dataset KL* T** C*** T/KL C/KL
    Top200 134.32 1,437.37 0.7507 10.70 0.005589
    Web3Bugs 319.88 4,980.57 3.9682 15.57 0.018658
    DefiHacks 17.82 375.41 0.2727 21.06 0.015303
    Overall 472.02 6,793.35 4.9984 14.39 0.010589

    * KL 代表千行代码 (KLoC);** TT 代表时间 (Time);*** CC 代表财务成本 (Financial Cost)。

    • 总体性能: 总共 472K 行代码的扫描花费了 6,793.35 秒和 4.9984 美元。平均每千行 Solidity 代码的扫描时间为 14.39 秒,成本为 0.010589 美元。
    • 数据集差异:
      • Top200 的扫描成本和速度最快(10.70 秒/KLoC,0.005589 美元/KLoC),因为其大部分候选函数在 GPTScan 的前两步就被过滤掉,无需进行复杂的变量和表达式查找。
      • Web3BugsDefiHacks 的扫描成本和速度相对较高(Web3Bugs 约 15.57 秒/KLoC,0.018658 美元/KLoC;DefiHacks 约 21.06 秒/KLoC,0.015303 美元/KLoC)。这归因于这些项目更复杂,有更多复杂的候选函数未能被静态过滤和场景匹配过滤掉。
  • 回答 RQ4: GPTScan 速度快、成本效益高,平均每扫描一千行 Solidity 代码仅需 14.39 秒和 0.01 美元。Web3BugsDefiHacks 成本较高、速度较慢,是由于存在更多复杂的函数未能被静态过滤和场景匹配过滤。

6.1.5. RQ5: 新发现的漏洞

  • 目的: 分析 GPTScan 是否能发现人类审计员先前遗漏的新漏洞。

  • 结果分析: GPTScan 成功在 Web3Bugs 数据集中发现了 9 个之前未在 Code4rena 审计报告中出现的漏洞,涵盖 3 种不同类型:

    • 5 个 Risky First Deposit (56%)
    • 3 个 Price Manipulation by AMM (33%)
    • 1 个 Front Running
  • 新漏洞示例:

    • Risky First Deposit (危险首次存款): 以下是原文 Figure 6 的代码示例:

      function deposit(uint _amount) external {
          uint _pool = balance();
          uint _totalSupply = totalSupply();
          if (_totalSupply == 0 && _pool > 0) { // trading fee accumulated while there were no IF LPs
              vusd.safeTransfer(governance, _pool);
              _pool = 0;
          }
          uint shares = 0;
          if ( _pool == 0 ) { // <- 漏洞点
              shares = _amount; // <- 漏洞点
          } else {
              shares = _amount * _totalSupply / _pool;
          }
      }
      

      分析: 在第 10 行,当变量 _pool 为 0 时(表示流动性池为空),存款者可以获得池中所有的份额 (shares=amountshares = _amount)。尽管第 5-8 行正确处理了 _totalSupply 为 0 的情况,但第 10 行涉及 _pool 的特定条件创造了一个可能被人类审计员忽略的漏洞。第一个存款者可以任意铸造 LP 份额,从而操纵每 LP 份额的价格。

    • Price Manipulation by AMM (通过 AMM 进行价格操纵): 以下是原文 Figure 7 的代码示例:

      function pendingRewards(uint256 _pid, address _user) external view returns (uint256) {
          PoolInfo storage pool = poolInfo[_pid];
          UserInfo storage user = userInfo[_pid][_user];
          uint256 accRewardsPerShare = pool.accRewardsPerShare;
          uint256 lpSupply = pool.lpToken.balanceOf(address(this));
          if (block.number > pool.lastRewardBlock && lpSupply != 0) {
              uint256 multiplier = getMultiplier(pool.lastRewardBlock block.number);
              uint256 rewardsAccum = multiplier.mul(rewardsPerBlock).mul(pool.allocPoint).div(totalAllocPoint);
              accRewardsPerShare = accRewardsPerShare.add( rewardsAccum.mul(1e12).div(1pSupply)); // <- 漏洞点
          }
          return user.amount.mul(accRewardsPerShare).div(1e12).sub( user.rewardDebt);
      }
      

      分析:pendingRewards 函数中,用于计算用户可申领奖励。第 9 行,当池不为空时,可赎回的奖励金额是基于池中的总供应量 (lpSupply) 计算的。然而,lpSupply 可以被用户控制,从而允许他们操纵赎回金额并利用合约。

    • Front Running (抢跑攻击): 以下是原文 Figure 8 的代码示例:

      /// @notice The lp tokens that the user contributes need to have been transferred previously, using a batchable router.
      function mint(address to)
          public
          beforeMaturity
          returns (uint256 minted)
      {
          uint256 deposit = pool.balanceOf(address(this)) - cached; // <- 漏洞点
          minted = _totalSupply * deposit / cached;
          cached += deposit;
          _mint(to, minted);
      }
      

      分析:mint 函数中,被铸造的代币应是用户之前已转移但尚未铸造的 (line 1 注释)。然而,任何人都可调用 mint 函数来铸造这些已转移但未铸造的代币,因为只检查了合约的缓存金额 (cached),而没有检查特定用户的缓存金额。这允许攻击者抢先于合法用户,在用户转移代币但未铸造时,先调用 mint 函数铸造这些代币。

  • 回答 RQ5: GPTScan 成功识别了 9 个之前未在 Code4rena 审计报告中出现的漏洞,这凸显了 GPTScan 作为人类审计员有用补充的价值。

6.2. 数据呈现 (表格)

本节已将所有表格内容嵌入到对应的 RQ 分析中,确保上下文关联性。

6.3. 消融实验/参数分析

论文中没有明确进行传统的消融实验来验证模型各组件(如过滤机制、静态确认模块)的独立贡献,但通过 RQ3 (静态确认的有效性) 的分析,实际上验证了静态确认对减少假阳性的重要作用。RQ3 的结果(静态确认过滤掉 65.84% 的假阳性)可以被视为一种特殊形式的消融分析,表明静态确认模块是 GPTScan 成功的关键组成部分。

参数分析方面,论文提到将 GPTtemperature 参数从默认值 1 调整为 0,以最小化 GPT 输出的随机性,但未对不同 temperature 值的影响进行详细的实验分析。此外,多维过滤允许 GPTScan 使用默认的 4k 词元上下文,而不是 16k,实现了成本效益,但这也不是一个详细的参数敏感性分析。

7. 总结与思考

7.1. 结论总结

本文提出了 GPTScan,这是智能合约逻辑漏洞检测领域的首个创新工具,它成功地将 GPT 的强大代码理解能力与传统的静态分析技术相结合。GPTScan 的核心在于将复杂的逻辑漏洞分解为代码级的场景和属性,利用 GPT 进行智能匹配,并通过多维过滤策略高效筛选候选函数。更重要的是,它引入了静态确认机制,通过精确的数据流追踪、值比较、顺序检查和函数调用参数检查来验证 GPT 识别出的关键变量和语句,显著降低了假阳性率。

实验结果表明,GPTScan 在检测代币合约中的逻辑漏洞方面展现出高精度(超过 90%),在处理大型复杂项目时也保持了可接受的精度(57.14%)。对于真实漏洞的检测,其召回率超过 70%,F1 分数也表现出色。在性能和成本效益方面,GPTScan 平均每千行 Solidity 代码仅需 14.39 秒和 0.01 美元,使其具有实际应用价值。特别值得一提的是,GPTScan 成功发现了 9 个人类审计员先前遗漏的新漏洞,证明了其作为人类审计员重要补充的潜力。静态确认模块在减少假阳性方面发挥了关键作用,过滤掉了三分之二的误报。

7.2. 局限性与未来工作

论文作者指出了 GPTScan 当前设计和实现中的局限性,并提出了未来的研究方向:

  • 修饰符过滤的精确性:
    • 当前局限: 现有的修饰符过滤仅使用白名单来过滤具有访问控制的修饰符,可能导致假阳性或假阴性。
    • 未来工作: 需要更精确的方法,包括检索修饰符的定义并对其进行详细的语义分析,以提高准确性。
  • 静态分析的路径敏感性:
    • 当前局限: 静态分析部分(控制流图和数据依赖图分析)采用简单方法,不具备路径敏感性 (Path-Sensitive)。这意味着在特定条件下,某些执行路径的可达性等路径相关问题可能会被忽略。
    • 未来工作: 可以通过引入符号执行引擎 (Symbolic Execution Engines) 到静态分析部分来改进这一点,从而实现更精细、路径感知的分析。
  • 其他 GPT 模型和参数的影响:
    • 当前局限: GPTScan 目前主要使用 GPT-3.5-turbo 模型,并且将 temperature 参数设置为 0 以减少随机性。初步测试显示 GPT-4 并未带来显著性能提升但成本增加 20 倍。然而,没有对不同 GPT 模型(如 Google Bard、Claude、自训练的 LLaMA 模型)和参数(如更高的 temperature 值)进行系统性测试。
    • 未来工作: 计划对不同 GPT 模型和参数进行系统性测试,以全面评估它们对 GPTScan 性能的影响。
  • 支持更多逻辑漏洞类型:
    • 当前局限: 本文手动分解了 10 种逻辑漏洞类型。
    • 未来工作: 扩展 GPTScan 对更多逻辑漏洞类型的支持,并研究如何自动化场景和属性的生成过程。

7.3. 个人启发与批判

7.3.1. 个人启发

  1. GPT 与传统分析的协同潜力: 这篇论文提供了一个非常优秀的范例,展示了 LLMs 并非要完全取代传统程序分析方法,而是可以作为一种强大的“智能助手”来增强现有工具的能力。GPT 擅长理解高层语义和抽象概念,而静态分析擅长精确验证和低层细节。二者的结合能够发挥各自优势,解决单一方法难以应对的复杂问题。这种“AI 辅助分析,传统方法确认”的模式在其他复杂系统安全审计或代码质量保障领域也具有广泛的借鉴意义。
  2. 细粒度漏洞分解的艺术: 将复杂的逻辑漏洞分解为“场景”和“属性”这种代码级语义描述,是连接 LLM 模糊理解与实际代码逻辑的桥梁。这比简单地喂给 LLM 高层概念要有效得多。这种思维方式在设计 LLM 辅助的自动化任务时非常有价值,即如何将人类专家的领域知识结构化,以便 LLM 更好地“理解”并应用。
  3. 成本效益与实用性: 在保证性能的同时,通过多维过滤和智能提示策略,使得使用成本较低的 GPT-3.5 也能取得良好效果,而非盲目追求最强大的 GPT-4,这体现了工程上的实用主义和成本意识。对于将 LLM 实际部署到生产环境而言,这是非常关键的考量。
  4. 发现新漏洞的价值: GPTScan 发现人类审计员遗漏的新漏洞,这不仅仅是性能指标上的提升,更是对自动化工具价值的直接证明。它表明 AI 工具可以作为人类认知盲区的有效补充,提高整体安全水平。

7.3.2. 批判与潜在改进

  1. 领域知识工程的开销: 尽管将漏洞分解为场景和属性是有效的,但论文指出当前这部分是手动完成的。对于大规模的漏洞类型,手动工程化成本巨大。虽然论文提到未来计划自动化,但如何确保自动生成的场景和属性的质量和完整性,是另一个挑战。GPT 本身可能存在“幻觉”现象,在生成这些关键描述时仍需人工审核。
  2. 静态确认的深度: 论文中提到的静态分析方法相对基础,例如数据流追踪缺乏别名分析,且不具备路径敏感性。这可能是导致部分假阴性的原因。引入更先进的静态分析技术(如全程序别名分析、路径敏感的符号执行)将进一步提高验证的准确性和鲁棒性,但也会增加分析复杂性和时间成本。如何在保持效率和成本效益的同时提升静态分析的深度,是一个需要权衡的问题。
  3. 对复杂业务逻辑的泛化能力: Web3Bugs 数据集上精度下降,部分原因是项目业务逻辑的复杂性和多样性。尽管 GPT 有强大的语义理解能力,但对于需要跨多个函数、甚至跨多个合约的复杂业务逻辑推理,GPTScan 目前可能仍有局限。例如,Unauthorized Transfer 的判断可能需要全局的合约状态和调用上下文。未来的工作可以探索如何将 GPT 的分析范围扩展到单个函数之外,甚至考虑整个项目或跨链交互。
  4. 提示工程的鲁棒性: “幕后模仿”提示技巧旨在减少 GPT 的随机性,但 LLM 的内在不确定性仍然存在。不同的提示措辞、上下文长度限制的边缘效应、甚至 GPT 模型版本的迭代都可能影响结果的稳定性。如何构建更加鲁棒和可解释的提示,以及如何更好地评估和量化 GPT 响应的置信度,是持续的研究方向。
  5. 可解释性: GPT 的“黑箱”特性使得其判断过程缺乏透明度。当 GPTScan 报告一个漏洞时,除了静态确认的证据,GPT 最初是如何识别的,其内部的“推理路径”是什么,对于审计员而言可能难以追溯。提高 GPT 判断的可解释性,例如通过生成解释性文本或突出关键代码片段,将有助于审计员更好地理解和信任工具的报告。

相似论文推荐

基于向量语义检索推荐的相关论文。

暂时没有找到相似论文。