想象一下,智能合约就像一台构建在区块链上的自动执行的自动售货机。一旦你投入金钱并按下按钮,它就会自动给你零食。你无法在事后更改机器内部的齿轮;它是“不可篡改的”。如果齿轮出现了缺陷,黑客可能会偷走里面所有的钱,而且除了重新制造一台全新的机器外,没有任何办法可以修复它。
这篇论文旨在尝试在这些售货机部署之前,就找出那些损坏的齿轮。研究人员提出了一个简单的问题:“仅仅通过观察一个自动售货机的蓝图有多复杂,我们能否判断它是否容易出现故障?”
以下是他们研究结果的拆解,使用了日常生活的类比:
1. 核心理念:复杂度是一个“红旗”(警示信号)
研究人员查看了 21 种衡量代码多么“混乱”或“复杂”的不同方式。可以将这些指标视为衡量以下内容的东西:
- SLOC(源代码行数): 说明书有多少页?
- 嵌套(Nesting): “如果这样,那么那样”的盒子层层嵌套了多少层?(就像俄罗斯套娃一样)。
- 耦合(Coupling): 这台机器为了工作,还需要与多少其他机器进行通信?
研究发现: 他们发现混乱的蓝图通常意味着损坏的机器。
当他们观察那些被黑客攻击过的(存在漏洞的)合约时,这些合约的蓝图几乎总是比安全合约的蓝图更复杂、更长且更纠缠不清。
2. “水晶球”问题(单一指标)
研究人员试图观察是否可以通过某一个特定的测量值来预测一次黑客攻击。
- 类比: 想象一下,你试图仅通过观察杯架的数量来猜测一辆汽车是否会发生碰撞。
- 结果: 这项尝试效果并不理想。没有任何单一指标(比如仅仅计算代码行数)是一个完美的“水晶球”。如果你只看行数,你就无法可靠地断言:“这个合约肯定会被黑客攻击。”这种联系确实存在,但很微弱。
3. “团队协作”的成功(组合指标)
然而,当他们将所有测量指标放在一起观察时,画面变得非常清晰。
- 类比: 你不能仅通过品尝盐罐来判断汤是否咸,但如果你品尝了整碗汤,你就确切知道它有多咸。
- 结果: 虽然单一指标不够,但组合后的指标在区分安全合约和危险合约方面表现得非常出色。“有漏洞”的合约在各项指标上(更多的行数、更深的嵌套、更多的连接)始终高于安全合约。
4. 令人惊讶的例外情况
有三个情况违背了“复杂度越高 = 危险越大”的规则:
- 注释(CLOC): 安全的合约拥有更多的注释(程序员编写的解释代码的笔记)。有漏洞的合约则注释较少。
- 启示: 在你的蓝图上写下笔记似乎有助于保持机器的安全。
- 后代(NOD): 安全的合约拥有更多的“后代”(版本或子合约)。有漏洞的合约则较少。
- 参数(Parameters): 有漏洞的合约平均拥有的输入/参数实际上略少一些。
5. 这对开发者意味着什么
论文得出结论,复杂度并不是黑客攻击的原因(像病毒一样),但它是一个非常响亮的警告信号。
- 类比: 如果你看到一栋房子里电线纠缠在一起、管道裸露在外且平面图混乱,你并不确定它是否一定会起火,但你知道它比那些布线整洁有序的房子更容易起火。
- 建议: 开发者应该尽量保持代码简单。如果一个合约变得过于复杂,这是一个停止并检查安全漏洞的信号。此外,多写注释;数据表明,文档齐全的代码更安全。
总结
这篇论文证明了复杂度是智能合约风险的一个强有力指标。你不能依靠单一数字来预测黑客攻击,但如果你观察代码整体的“混乱程度”,你可以比完全忽略复杂度时更好地识别出危险的合约。这是一个帮助审计员和开发者优先处理哪些合约需要最仔细检查的工具。
技术摘要:通过代码复杂度指标评估智能合约的脆弱性
问题陈述
部署在以太坊等区块链平台上的智能合约具有不可篡改性,且通常处理高价值的金融交易,这使得安全性保障至关重要。虽然底层区块链是安全的,但智能合约本身容易受到因程序员疏忽或编码错误而导致的漏洞攻击。传统的静态分析工具通常依赖于模式匹配来检测特定的漏洞类型。然而,目前需要了解代码的结构属性(即软件复杂度)是否可以作为识别脆弱区域的补充指标。作者假设,偏离既定最佳实践(即复杂度较高)的代码可能会表现出更高的安全缺陷暴露风险,但复杂度指标与 Solidity 智能合约漏洞之间的具体关系仍是一个需要通过实证验证的开放性问题。
研究方法
本研究采用定量、实证的方法,分析了 21 个不同的软件复杂度指标与 Solidity 智能合约中漏洞存在之间的关系。
- 数据集: 研究利用了源自 Liu 等人的数据集,该数据集包含从 Etherscan 抓取的 16,239 个独立合约(其中 258 个为易受攻击合约,15,981 个为中性合约)。易受攻击的合约根据八种特定的漏洞类型进行了标记:整数溢出/下溢(Integer Underflow/Overflow)、危险的以太硬相等性(Dangerous Ether Strict Equality)、重入攻击(Reentrancy)、时间戳依赖(Timestamp Dependency)、区块高度依赖(Block Number Dependency)、危险的委托调用(Dangerous Delegatecall)、以太冻结(Ether Frozen)以及未检查的外部调用(Unchecked External Call)。
- 指标提取: 使用静态分析工具 Solmet 为每个合约提取了 21 个复杂度指标。这些指标包括规模指标(SLOC, LLOC, CLOC)、结构指标(NF, WMC, NOS)、嵌套指标(NL, NLE)、继承指标(DIT, NOA, NOD)、耦合指标(CBO, NOI, NA)以及这些指标的平均值。
- 统计分析:
- 相关性分析: 使用 Spearman 秩相关系数来评估指标之间的单调关系,并识别指标之间的冗余性。
- 组间比较: 采用 Mann-Whitney U 检验来确定指标值的分布在易受攻击合约与中性合约之间是否存在显著差异。
- 效应量: 计算 Cliff's Delta (δ) 以量化两组之间的差异程度。
- 置信区间: 用于比较易受攻击组与中性组之间指标的中心趋势(均值)。
核心贡献
论文通过四个特定的研究问题(RQs)来评估复杂度指标的效用:
- RQ1(指标间依赖性): 研究识别了某些指标之间显著的冗余性。例如,SLOC 与 NOI、NOS、WMC 和 NF 强相关。同样,嵌套指标(NL, NLE)及其平均值也表现出高度相关,这表明并非所有 21 个指标都能提供独特的信息用于漏洞检测。
- RQ2(指标与漏洞的相关性): 分析显示,尽管所有 21 个指标与漏洞的存在都显示出统计学上的显著相关性(p<0.05),但这些相关性的强度普遍较弱(系数大多低于 0.3)。这与传统编程语言中的发现形成对比,在传统语言中相关性通常更强。因此,没有任何单一指标可以作为强力的独立预测因子。
- RQ3(判别能力): 尽管单个指标的相关性较弱,但 Mann-Whitney U 检验证实,所有指标在统计学上都能区分易受攻击代码与中性代码(p<0.05)。大多数指标都表现出大的效应量(例如 SLOC, LLOC, NF, WMC, NL, NOS, CBO, NA, NOI),表明这两组之间的指标分布在实际层面是不同的。
- RQ4(差异的方向性): 研究发现,对于大多数指标,易受攻击的合约通常表现出比中性合约更高的平均复杂度得分。然而,有三个值得注意的例外,即易受攻击合约的数值较低:
- CLOC(注释行): 中性合约拥有更多的注释,这表明文档化可能有助于减轻漏洞风险。
- NOD(后代数量): 易受攻击的合约后代数量较少。
- Avg. NUMPAR(平均参数量): 易受攻击的合约平均参数量较少。
结果与意义
论文得出结论,复杂度指标是漏洞的指示器而非直接原因。研究结果的主要意义在于以下几点:
- 集体效用: 虽然单个指标的预测能力较弱,但研究证明,当进行整体分析时,复杂度指标具有强大的判别能力。这支持了将它们作为自动化漏洞检测工具中补充特征的应用。
- 冗余管理: 对高度相关指标(如 SLOC 与 WMC 与 NF)的识别表明,可以通过选择非冗余的特征子集来优化漏洞预测模型,从而在不牺牲准确性的情况下提高效率。
- 上下文细微差别: 研究结果突出了 Solidity 与传统软件相比的独特特征。例如,与注释密度(CLOC)的反向关系表明,在智能合约语境下,缺乏文档化是风险的一个特定标志。
- 实际应用: 作者建议可以将这些指标集成到现有的静态分析工具中,以优先开展审计工作。高复杂度得分的合约可以被标记以进行更深入的人工审查,开发者也可以利用这些见解来遵循最佳实践,例如减少嵌套、降低耦合以及确保充分的文档记录。
作者保持了审慎的态度,强调所观察到的关系是统计上的关联。他们承认高复杂度通常与更大的“问题领域”(例如,复杂的 DeFi 协议自然需要更多的代码)相关联,这可能是导致漏洞风险增加的潜在驱动因素,而非复杂度指标本身是唯一的因果机制。未来的工作建议包括领域特定的分层研究以及对认知复杂度指标的探索。
每周获取最佳 computer science 论文。
受到斯坦福、剑桥和法国科学院研究人员的信赖。
请查收邮箱确认订阅。
出了点问题,再试一次?
无垃圾邮件,随时退订。