GPTScan: Detecting Logic Vulnerabilities in Smart Contracts by Combining GPT with Program Analysis
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 的方法存在局限性:
-
高假阳性率 (High False Positive Rate): David 等人 [34] 尝试使用 GPT 通过提供高级漏洞描述进行项目级的“是或否”查询,但这种方法产生了约 96% 的高假阳性率。
-
高级推理能力需求 (Demand for Advanced Reasoning): 纯 GPT 方法通常需要 GPT 具备高级的逻辑推理能力,这通常意味着需要更强大的模型(如 GPT-4 而非 GPT-3.5),从而增加了成本。
-
上下文长度限制 (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): 衡量所有被报告为正例的样本中,有多少是真正的正例。在漏洞检测中,高精度意味着工具报告的漏洞大部分是真实的,减少了人工审查的负担。
- 召回率 (Recall): 衡量所有真正的正例中,有多少被模型成功识别。在漏洞检测中,高召回率意味着工具能够发现大部分真实存在的漏洞。
- F1 分数 (F1 Score): 精度和召回率的调和平均值,用于综合评估模型的性能,特别是在数据不平衡时。
其中:
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 与上述前人工作的核心区别和创新点在于:
- 混合方法 (Hybrid Approach):
GPTScan是第一个将GPT与静态分析相结合以检测智能合约逻辑漏洞的工具。它避免了纯粹依赖GPT导致的高假阳性问题,也弥补了纯静态分析无法理解高层语义的不足。 - GPT 的角色转变 (Shift in GPT's Role): 不同于 David 等人 [34] 将
GPT视为一个高级推理引擎来直接判断漏洞,GPTScan将GPT定位为一个通用的代码理解工具。它利用GPT的语义理解能力来匹配抽象的场景和属性,并识别关键代码元素,而不是直接进行“是或否”的判断。 - 细粒度漏洞分解 (Fine-grained Vulnerability Decomposition):
GPTScan将逻辑漏洞类型分解为代码级的场景和属性,这使得GPT可以直接从代码语义层面进行匹配,降低了对GPT高级推理能力的需求,同时提高了匹配的精确度。 - 多维过滤与静态确认 (Multi-dimensional Filtering & Static Confirmation): 引入多维函数过滤机制,有效应对
GPT的上下文长度和成本限制。更重要的是,通过静态确认模块对GPT识别出的关键变量和语句进行验证,显著降低了假阳性率,这是纯GPT方法所不具备的优势。 - 成本效益 (Cost-Effectiveness): 借助过滤机制,
GPTScan能够使用成本更低的GPT-3.5-turbo模型和默认的 4k 词元上下文,而不是更昂贵、上下文更大的GPT-4模型,使其更适合大规模应用。
4. 方法论
本节将详细阐述 GPTScan 的设计与实现,包括其整体工作流程、核心组件以及如何克服智能合约逻辑漏洞检测中的挑战。
4.1. 概述与挑战
GPTScan 的高层工作流程如以下图像(原文 Figure 3)所示:

GPTScan 的工作流程概览:
-
合约解析 (Contract Parsing) & 过滤 (Filtering): 给定一个智能合约项目(可能包含多个 Solidity 文件),
GPTScan首先进行合约解析,然后执行调用图 (Call Graph) 分析以确定函数可达性 (Function Reachability),并进行多维过滤以提取候选函数 (Candidate Functions) 及其上下文函数。 -
GPT 匹配 (GPT Matching):
GPTScan随后利用GPT将这些候选函数与预先抽象的漏洞类型的场景 (scenarios) 和属性 (properties) 进行匹配。 -
关键变量/语句识别 (Key Variable/Statement Recognition): 对于通过匹配的函数,
GPTScan进一步指示GPT智能识别其中的关键变量和语句。 -
静态确认 (Static Confirmation): 识别出的关键变量和语句被传递给专门的静态分析模块,进行漏洞确认。
在上述三步过程中,
GPTScan需要解决三个主要挑战:
-
C1: 规模与成本问题: 智能合约项目可能包含数十个 Solidity 文件,直接将所有文件喂给
GPT是不可行或成本高昂的。此外,非漏洞函数的存在可能会干扰GPT对漏洞函数的识别。因此,如何有效地缩小GPT匹配的候选函数范围至关重要。 -
C2: GPT 的语义理解与漏洞分解: 现有的
GPT基于的漏洞检测方法通常向GPT提供高层漏洞描述进行匹配,这要么对GPT的高级推理能力要求过高,要么依赖于GPT预训练的漏洞知识。因此,如何以一种允许GPT作为通用代码理解工具直接从代码级语义识别漏洞的方式来分解漏洞类型? -
C3: 结果可靠性与验证: 考虑到
GPT可能会产生不可靠的答案或无法识别相似函数之间的细微差别,进一步确认匹配到的潜在漏洞变得至关重要。挑战
C1和C3都与C2相关。因此,GPTScan首先解决C2,然后分别解决C1和C3。
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
分解过程的思考:
- 初步筛选: 场景的第一部分描述了函数的功能性,帮助
GPTScan进行初步筛选,减少不必要的扫描。例如,Front Running漏洞要求函数涉及铸造 (minting)、归属 (vesting) 或转移其他用户代币等操作。 - 根源描述: 场景的第二部分描述了与漏洞根源相关的函数行为,如缺少安全检查或错误的会计顺序。如果函数满足场景(第一部分),
GPTScan会再次将函数发送给GPT,检查是否同时满足场景和属性。 - 自动化生成 (未来工作): 本文手动分解了十种漏洞类型。未来计划采用基于
GPT-4的方法自动从历史漏洞报告中提取初步的场景和属性语句,并通过原始漏洞代码进行验证和迭代生成。
4.2.2. 是或否的场景与属性匹配 (Yes-or-No Scenario and Property Matching)
GPTScan 使用抽象的场景和属性通过 GPT 匹配候选函数。以下图像(原文 Figure 4)展示了 GPTScan 用于场景和属性匹配的提示模板:

提示模板设计考虑:
- 分离匹配: 属性匹配只针对通过场景匹配的函数进行。这种分离使得
GPTScan可以在一个提示中查询所有场景,从而节省GPT成本。 - 双重确认: 在属性匹配阶段,
GPTScan通过查询场景和属性的组合(而不是单独查询属性)来再次确认场景,以确保完整性。 - 限制回答格式: 场景和属性匹配被设计为“是或否”问题,旨在最小化非结构化
GPT响应的影响。 - JSON 输出:
GPTScan指示GPT学习输出JSON格式,以利用GPT的指令学习能力。
4.2.3. 最小化 GPT 输出随机性 (Minimizing the Impact of GPT Output Randomness)
尽管使用“是或否”问题限制了 GPT 响应的格式,但 GPT 模型固有的随机性可能导致对相同问题给出不同答案。
- 温度参数:
GPTScan将GPT模型的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(大规模与成本问题),GPTScan 在 GPT 匹配之前,采用多维过滤来系统地选择候选函数,并进行可达性分析以保留可能被攻击者访问的函数。
4.3.1. 项目级文件过滤 (Project-wide File Filtering)
多维过滤从项目级文件过滤开始,排除:
- 非 Solidity 文件(例如,
node_modules目录下的文件)。 - 测试文件(例如,各种
test目录中的文件)。 - 第三方库文件(例如,来自知名库如
openzeppelin、uniswap和pancakeswap的文件)。 通过此过滤,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)、详细函数内容 (FCE、FCNE、FCCE和FCNCE)、函数参数 (FPT) 和函数的调用者关系 (FPNC、FNM、CFN)。不同漏洞将使用其特定的过滤规则。过滤器的选择主要基于对漏洞类型的领域知识 (Domain Knowledge)。例如,Figure 1 中展示的Risky First Deposit漏洞仅使用FCCE规则类型来选择“total”、“supply”和“liquidity”的任何组合(无论是单独出现还是共同出现),以确保存款与代币的总供应量或流动性计算相关。
4.3.4. 可达性分析 (Reachability Analysis)
过滤后,GPTScan 进行调用图分析以确定候选函数的可达性。
- AST 生成:
GPTScan利用ANTLR[21](一个词法分析器和解析器生成器)解析智能合约项目的源代码并生成抽象语法树 (AST)。 - 调用图构建: 使用
AST,为整个项目构建调用图。 - 访问控制: Solidity 中有四种访问控制注解:
public、external、internal和private。public和external函数可被任何人调用,直接对攻击者可达。internal和private函数可能被其他可达函数调用,因此分析其可达性,如果可达则包含。- 带有自定义修饰符(如
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 相关变量或表达式的提示示例:

GPT 识别过程:
-
变量/语句提取:
GPTScan指示GPT识别与特定业务逻辑(通过提示描述)相关的变量和语句。 -
短描述与验证: 对于每个提取的变量或语句,
GPTScan指示GPT提供一个简短描述。此描述有助于确定给定变量是否与问题相关,并避免不正确的答案。如果GPT提供的变量或语句在函数上下文中不存在,或者描述与所问问题不相关,GPTScan将终止判断过程,并认为不存在该漏洞。 -
静态分析确认: 如果提供的变量和语句通过验证,
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)
此方法检查两个变量或表达式是否在条件语句(如 require、assert 和 if)中进行比较。它用于确保变量或表达式在使用前经过适当检查。
- 示例: 在
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) 的执行发生在余额更新 () 之后,导致奖励计算错误,用户可能窃取所有奖励。正确的顺序应是先更新检查点再更新余额。
-
- 来源: 从最新的
-
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 的性能:
-
真阳性 (True Positives, TP):
- 概念定义: 指
GPTScan成功检测到的真实存在的漏洞数量。 - 数学公式: 无独立公式,是一个计数。
- 符号解释:
TP= 成功识别的真实漏洞实例数。
- 概念定义: 指
-
真阴性 (True Negatives, TN):
- 概念定义: 指
GPTScan正确地没有报告为漏洞的非漏洞数量。 - 数学公式: 无独立公式,是一个计数。
- 符号解释:
TN= 未被报告且确实不存在漏洞的实例数。
- 概念定义: 指
-
假阳性 (False Positives, FP):
- 概念定义: 指
GPTScan错误地将不存在漏洞的代码报告为漏洞的数量。高FP会增加人工审查的负担。 - 数学公式: 无独立公式,是一个计数。
- 符号解释:
FP= 错误识别为漏洞的非漏洞实例数。
- 概念定义: 指
-
假阴性 (False Negatives, FN):
- 概念定义: 指
GPTScan未能检测到的真实存在的漏洞数量。高FN意味着存在潜在的安全风险。 - 数学公式: 无独立公式,是一个计数。
- 符号解释:
FN= 未被识别的真实漏洞实例数。
- 概念定义: 指
-
假阳性率 (False Positive Rate):
- 概念定义: 衡量所有实际为阴性的样本中,被错误地预测为阳性的比例。在漏洞检测中,它表示非漏洞合约被误报为漏洞的比例。
- 数学公式:
- 符号解释:
False Positives为假阳性数量,True Negatives为真阴性数量。
-
精度 (Precision):
- 概念定义: 衡量所有被
GPTScan报告为漏洞的案例中,有多少是真正的漏洞。高精度表明报告结果的可靠性。 - 数学公式:
- 符号解释:
True Positives为真阳性数量,False Positives为假阳性数量。
- 概念定义: 衡量所有被
-
召回率 (Recall):
- 概念定义: 衡量所有真实存在的漏洞中,有多少被
GPTScan成功检测到。高召回率表明工具能发现大部分真实漏洞。 - 数学公式:
- 符号解释:
True Positives为真阳性数量,False Negatives为假阴性数量。
- 概念定义: 衡量所有真实存在的漏洞中,有多少被
-
F1 分数 (F1 Score):
- 概念定义: 精度和召回率的调和平均值。它综合考虑了精度和召回率,在两者之间取得平衡,尤其适用于类别不平衡的情况。
- 数学公式:
- 符号解释:
Precision为精度,Recall为召回率。
5.3. 对比基线
论文将 GPTScan 的性能与以下现有工具进行了比较:
-
Slither [37]:
- 代表性: 一个广泛使用的开源静态分析框架,拥有超过百个漏洞检测规则。
- 比较的规则: 针对
GPTScan的Unauthorized Transfer漏洞,Slither 中相关的规则包括unchecked-transfer、arbitrary-send-eth和arbitrary-send-erc20。 - 局限性: 论文发现
Slither在这些相关规则上产生了大量假阳性,且无法正确检测Unauthorized Transfer的变体行为。它不关联调用链信息,也无法很好地理解代码语义。
-
MetaScan 的在线静态扫描服务 (MScan) [19, 23]:
- 代表性: 这是一个商业级的静态扫描服务,也拥有上百个漏洞检测规则。
- 比较的规则: 针对
GPTScan的Price Manipulation漏洞,MScan包含两个相关的价格操纵漏洞规则。 - 局限性:
MScan在Price Manipulation方面达到了 100% 的精度,但召回率较低 (58.33%),且无法检测其他类型的逻辑漏洞。这是因为它主要依赖硬编码模式(包括特定函数和变量名的匹配),在模式不适用时无法泛化。
-
纯 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) 为 ()。GPTScan在分析DefiHacks(也是代币合约,平均每个项目约 2 个 Solidity 文件)时,精度 (Precision) 达到 ()。- 在分析
Web3Bugs(大型项目,平均每个项目 36 个 Solidity 文件)时,精度降至 ()。
- 在
- 结论:
GPTScan在分析代币合约(如Top200和DefiHacks)时,具有低假阳性率和高精度,表明其适用于大规模链上代币合约扫描。对于大型复杂项目,精度有所下降,但仍可接受。这一下降可能因为Web3Bugs中的智能合约代码更加多样化。
6.1.2. RQ2: 检测漏洞合约的有效性与现有工具的比较
- 目的: 评估
GPTScan在Web3Bugs和DefiHacks数据集上检测漏洞的有效性,并与现有工具进行比较。 - 结果分析:
- Web3Bugs 数据集:
- 总共分析了 232 种漏洞类型实例,检测到 40 个
TP,漏报 8 个FN,产生 30 个FP。 - 召回率 (Recall):()。
- F1 分数 (F1 Score):。
- 总共分析了 232 种漏洞类型实例,检测到 40 个
- DefiHacks 数据集:
- 总共分析了 34 种漏洞类型实例,检测到 10 个
TP,漏报 4 个FN,产生 1 个FP。 - 召回率 (Recall):()。
- F1 分数 (F1 Score):。
- 总共分析了 34 种漏洞类型实例,检测到 10 个
- Web3Bugs 数据集:
- 结论:
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 个Slippage。Risky First Deposit是由于代码段过长,GPT难以准确理解。Slippage则因检查逻辑链复杂且变体众多。 - 4 个
Wrong Interest Rate Order,3 个Approval Not Cleared和 1 个Wrong Checkpoint Order。这些漏洞与项目业务逻辑紧密相关,难以在缺乏全面项目设计知识的情况下减少误报。Approval Not Cleared是因为函数可能并非总是用于转账代币。
- 15 个 (
- 与现有工具的比较:
- Slither: 在所有三个数据集上产生了 13,144 个警告,其中与
Unauthorized Transfer相关的仅 146 个,但全部为假阳性。原因在于Slither不关联调用链信息,且无法正确检测转账行为的变体。 - MScan: 在
DefiHacks数据集上,对Price Manipulation实现了 的精度和 的召回率。但它没有检测到其他类型的逻辑漏洞。MScan依赖硬编码模式,无法泛化检测变体。 - 纯 GPT-based 方法 (David et al. [34]):
GPT-4-32k模型精度为 ,召回率 ,F1 分数 。Claude-v1.3-100k模型精度为 ,召回率 ,F1 分数 。这些结果的假阳性率显著高于GPTScan,主要是因为它们没有对GPT输出进行验证。
- Slither: 在所有三个数据集上产生了 13,144 个警告,其中与
- 回答 RQ2:
GPTScan在Web3Bugs数据集上召回率为 、F1 分数为 ;在DefiHacks数据集上召回率为 、F1 分数为 ,表现优于现有静态和纯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 个函数。这表明静态确认成功过滤掉了三分之二的假阳性案例 ( )。
- 对特定漏洞类型的效果: 静态确认对于
Wrong Interest Rate Order、Wrong Checkpoint Order和Risky First Deposit等漏洞类型尤其有效。这些类型的场景和属性描述较为粗粒度,导致大量候选函数通过GPT匹配。静态确认通过进一步识别相关语句和变量,过滤掉了不满足漏洞类型的函数。 - 对假阴性的影响: 在被过滤掉的 426 个案例中,只有 3 个真实漏洞案例是先被
GPT匹配但后来被静态分析排除,导致 3 个假阴性。另一个假阴性与编译问题有关,其余 4 个未通过GPT场景和属性匹配。这表明静态确认对假阴性的影响很小。
- 在静态确认之前,共有 647 个原始函数被
-
回答 RQ3: 静态确认有效过滤掉了
Web3Bugs数据集中 的假阳性案例,而对假阴性案例的影响很小。
6.1.4. RQ4: 性能和财务开销
-
目的: 评估
GPTScan在使用 OpenAI 的GPT-3.5-turboAPI 时的运行时间和财务成本。 -
结果分析: 以下表格(原文 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);** 代表时间 (Time);*** 代表财务成本 (Financial Cost)。- 总体性能: 总共 472K 行代码的扫描花费了 6,793.35 秒和 4.9984 美元。平均每千行 Solidity 代码的扫描时间为 14.39 秒,成本为 0.010589 美元。
- 数据集差异:
Top200的扫描成本和速度最快(10.70 秒/KLoC,0.005589 美元/KLoC),因为其大部分候选函数在GPTScan的前两步就被过滤掉,无需进行复杂的变量和表达式查找。Web3Bugs和DefiHacks的扫描成本和速度相对较高(Web3Bugs约 15.57 秒/KLoC,0.018658 美元/KLoC;DefiHacks约 21.06 秒/KLoC,0.015303 美元/KLoC)。这归因于这些项目更复杂,有更多复杂的候选函数未能被静态过滤和场景匹配过滤掉。
-
回答 RQ4:
GPTScan速度快、成本效益高,平均每扫描一千行 Solidity 代码仅需 14.39 秒和 0.01 美元。Web3Bugs和DefiHacks成本较高、速度较慢,是由于存在更多复杂的函数未能被静态过滤和场景匹配过滤。
6.1.5. RQ5: 新发现的漏洞
-
目的: 分析
GPTScan是否能发现人类审计员先前遗漏的新漏洞。 -
结果分析:
GPTScan成功在Web3Bugs数据集中发现了 9 个之前未在Code4rena审计报告中出现的漏洞,涵盖 3 种不同类型:- 5 个
Risky First Deposit(56%) - 3 个
Price Manipulation by AMM(33%) - 1 个
Front Running
- 5 个
-
新漏洞示例:
-
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 时(表示流动性池为空),存款者可以获得池中所有的份额 ()。尽管第 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 成功的关键组成部分。
参数分析方面,论文提到将 GPT 的 temperature 参数从默认值 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. 个人启发
- GPT 与传统分析的协同潜力: 这篇论文提供了一个非常优秀的范例,展示了
LLMs并非要完全取代传统程序分析方法,而是可以作为一种强大的“智能助手”来增强现有工具的能力。GPT擅长理解高层语义和抽象概念,而静态分析擅长精确验证和低层细节。二者的结合能够发挥各自优势,解决单一方法难以应对的复杂问题。这种“AI辅助分析,传统方法确认”的模式在其他复杂系统安全审计或代码质量保障领域也具有广泛的借鉴意义。 - 细粒度漏洞分解的艺术: 将复杂的逻辑漏洞分解为“场景”和“属性”这种代码级语义描述,是连接
LLM模糊理解与实际代码逻辑的桥梁。这比简单地喂给LLM高层概念要有效得多。这种思维方式在设计LLM辅助的自动化任务时非常有价值,即如何将人类专家的领域知识结构化,以便LLM更好地“理解”并应用。 - 成本效益与实用性: 在保证性能的同时,通过多维过滤和智能提示策略,使得使用成本较低的
GPT-3.5也能取得良好效果,而非盲目追求最强大的GPT-4,这体现了工程上的实用主义和成本意识。对于将LLM实际部署到生产环境而言,这是非常关键的考量。 - 发现新漏洞的价值:
GPTScan发现人类审计员遗漏的新漏洞,这不仅仅是性能指标上的提升,更是对自动化工具价值的直接证明。它表明AI工具可以作为人类认知盲区的有效补充,提高整体安全水平。
7.3.2. 批判与潜在改进
- 领域知识工程的开销: 尽管将漏洞分解为场景和属性是有效的,但论文指出当前这部分是手动完成的。对于大规模的漏洞类型,手动工程化成本巨大。虽然论文提到未来计划自动化,但如何确保自动生成的场景和属性的质量和完整性,是另一个挑战。
GPT本身可能存在“幻觉”现象,在生成这些关键描述时仍需人工审核。 - 静态确认的深度: 论文中提到的静态分析方法相对基础,例如数据流追踪缺乏别名分析,且不具备路径敏感性。这可能是导致部分假阴性的原因。引入更先进的静态分析技术(如全程序别名分析、路径敏感的符号执行)将进一步提高验证的准确性和鲁棒性,但也会增加分析复杂性和时间成本。如何在保持效率和成本效益的同时提升静态分析的深度,是一个需要权衡的问题。
- 对复杂业务逻辑的泛化能力:
Web3Bugs数据集上精度下降,部分原因是项目业务逻辑的复杂性和多样性。尽管GPT有强大的语义理解能力,但对于需要跨多个函数、甚至跨多个合约的复杂业务逻辑推理,GPTScan目前可能仍有局限。例如,Unauthorized Transfer的判断可能需要全局的合约状态和调用上下文。未来的工作可以探索如何将GPT的分析范围扩展到单个函数之外,甚至考虑整个项目或跨链交互。 - 提示工程的鲁棒性: “幕后模仿”提示技巧旨在减少
GPT的随机性,但LLM的内在不确定性仍然存在。不同的提示措辞、上下文长度限制的边缘效应、甚至GPT模型版本的迭代都可能影响结果的稳定性。如何构建更加鲁棒和可解释的提示,以及如何更好地评估和量化GPT响应的置信度,是持续的研究方向。 - 可解释性:
GPT的“黑箱”特性使得其判断过程缺乏透明度。当GPTScan报告一个漏洞时,除了静态确认的证据,GPT最初是如何识别的,其内部的“推理路径”是什么,对于审计员而言可能难以追溯。提高GPT判断的可解释性,例如通过生成解释性文本或突出关键代码片段,将有助于审计员更好地理解和信任工具的报告。
相似论文推荐
基于向量语义检索推荐的相关论文。