文章讨论了GPT-4在智能合约审计中的局限性,特别是在识别关键漏洞方面的失败。通过实例合约展示了函数中的输入验证缺失,以及GPT-4未能检测到这一漏洞的实验结果,强调了对重要金融代码的审计仍然需要人类专家的参与。
答案是否定的。
GPT-4 确实很惊人,我们已经看到一些显著的推文 [1]↗ [2]↗ 展示了 ChatGPT 识别智能合约漏洞的例子。
问题是——作为上述推文之一的作者——这些例子是精心挑选的。即使是 OpenAI 最新的模型 GPT-4,也无法可靠地检测表层的关键漏洞。
让我们从一个简单的示例合约开始,该合约隐藏着一个致命的漏洞。
pragma solidity 0.8.15;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {ERC20CreditToken} from "./ERC20CreditToken.sol";
/// 代币化保险库合约
///
/// 这是一个简单的保险库合约,接受 ERC20 存款并发行
/// 信用(会计)代币。然后可以赎回会计代币
/// 以提取存款。
contract TokenizingVault {
/// 每个基础资产唯一的 ERC20 会计代币
mapping(ERC20 => ERC20CreditToken) public creditTokens;
/// ERC20CreditToken 的引用实现
ERC20CreditToken public immutable creditTokenImpl;
constructor() {
creditTokenImpl = new ERC20CreditToken();
}
function create(ERC20 underlying, uint256 amount)
external nonReentrant returns (ERC20CreditToken, uint256)
{
ERC20CreditToken creditToken = creditTokens[underlying];
// 如果没有代币存在,则回退,必须先调用 deploy
if (creditToken == ERC20CreditToken(address(0x00)))
revert('代币不存在');
// 转移基础资产
underlying.transferFrom(msg.sender, address(this), amount);
// 铸造新的信用代币
creditToken.mint(msg.sender, amount);
return (creditToken, amount);
}
function redeem(ERC20CreditToken token, uint256 amount)
external nonReentrant
{
token.burn(msg.sender, amount);
token.underlying().transfer(msg.sender, amount);
}
function deploy(ERC20 underlying)
external nonReentrant returns (ERC20CreditToken)
{
// 如果还没有代币存在则创建信用代币
ERC20CreditToken creditToken = creditTokens[underlying];
if (creditToken == ERC20CreditToken(address(0))) {
bytes memory tokenData = abi.encodePacked(underlying, address(this));
creditToken = ERC20CreditToken(address(creditTokenImpl).clone(tokenData));
creditTokens[underlying] = creditToken;
}
return creditToken;
}
}
这是一个简单的保险库合约。它接受用户的任意 ERC20 存款并给出相应的“信用”(即存款)代币。这些存款代币可以赎回原始存款。存款代币很方便,因为它允许用户可替代地交易他们的存款。你可以想象这个保险库可能支持其他功能,比如收益 farming,但这个例子被缩减到绝对最小,以便于审核。
你能发现这个漏洞吗?
没错,它出现在 redeem
函数中。这个函数是一个外部函数,且没有访问控制和输入验证。让我们看看这个函数为什么会存在漏洞。
虽然用户在缺乏足够的信用代币的情况下将无法提取资金(token_.burn
会回退),但这并不足够。核心问题在于该函数并没有验证传入的 token_
是 真实 的;也就是说,是由保险库合约发行的而不是伪造的。攻击者可以通过调用 redeem()
传入一个伪造的、攻击者生成的 ERC20CreditToken
进行利用,而其 underlying()
是一个其他用户已存入保险库的真实、有价值的 ERC20。
打个比方,想象一下这个保险库是美国联邦储备银行。这个银行系统中,人们可以存入电汇以换取美元。相应的漏洞会是,如果联邦储备允许你使用伪造的美元进行提款。
请记住,这个函数只有两行代码,且是明显缺乏输入验证。它不是一个深奥、复杂或令人疑惑的逻辑错误或设计缺陷。这是一个基本的编码错误。
现在,让我们尝试使用 ChatGPT 来审核这个智能合约。它非常小,因此适合 GPT-4 的巨大上下文窗口。
我们将使用这个提问:
像往常一样有帮助,ChatGPT 回应“准备好了”。现在让我们直接粘贴合约源代码。(注意:当我进行此实验时,我在代码中添加了一些额外的注释,从理论上讲,“审核”结果应该是相同的。)
这是 ChatGPT 的回应:
ChatGPT 不仅未能发现关键漏洞,而且信心十足。讽刺的是,它甚至指出遗漏的输入验证,尽管它具体声称发现的漏洞并不重要。
好吧。也许我们只是运气不好。让我们再试一次。
有趣的是,它提到了 redeem
函数,但不幸的是,它又虚构了一个并不重要的漏洞。尽管瞄准了正确的函数,但它却错过了可能导致整个保险库被清空的更严重的问题。
好吧,如果我们试着逐个传入代码呢?这一次,我们甚至会特别提示它将攻击者控制的输入视为潜在的恶意内容。
像往常一样有帮助。现在让我们逐个粘贴代码,每次一个函数。
这持续了一段时间,每次都要求更多代码。在另一轮中,它逐个分析函数,基本上总结了函数并指出了一些关于函数的事实。
最后的输出是:
所以再次错过了关键但相对表层的漏洞。这应该足以证明 ChatGPT 当然不能胜任审核智能合约的任务,特别是对于 任务关键的、金融代码。
随着 GPT-4 的出现,ChatGPT 作为许多任务的出色助手。但它在编写代码片段、回答一般知识问题以及提供有用的建议和评论方面非常熟练。尽管如此,ChatGPT 倾向于生成那些“感觉”正确的回应(即通过直觉检查),但实际上并不真的正确。令人担忧的是,尽管 OpenAI 尽力而为,它仍然常常自信地错误。
我们进行了一系列短期实验,测试了一个相对表层但关键的智能合约漏洞,在小型合约中,ChatGPT 在所有试验中未能识别出漏洞。这项实验显然受限于样本量小(ChatGPT 当前每 3 小时只允许 50 次生成)。但是,对于像智能合约这样的任务关键代码,10 次尝试中的假阴性率为 10 是不可接受的。
ChatGPT 和基于 LLM 的 AI 技术一般很可能成为安全研究人员工具箱中的有用辅助工具。然而,考虑到 LLM 当前的状态,预计不会使该工作变得多余。看来,如智能合约审计等高技能特种作业,在至少可预见的短期内仍将保持市场需求。
Zellic 专注于保护新兴技术。我们的安全研究人员已经发现了从财富 500 强到 DeFi 巨头等最有价值目标的漏洞。
开发人员、创始人和投资者信任我们的安全评估,以快速、自信且没有关键漏洞地交付。凭借我们在现实世界攻防安全研究方面的背景,我们发现了别人所忽视的内容。
联系我们↗ 进行更加优秀的审核。真正的审核,而不是走过场的审核。
- 原文链接: zellic.io/blog/can-gpt-a...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!