64

引介 | 智能合约中的签名重放漏洞

 5 years ago
source link: https://www.tuicool.com/articles/FJRnUzI
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

JRraqaN.jpg!web

密码学签名是区块链系统中的基本模块。使用对应的私钥对交易进行签名能够将交易发起人与特定帐户联系起来。如果没有此功能,区块链的记帐工作将无法正常进行。

许多在以太坊上部署的智能合约也有直接验证数字签名的功能,以使得一个或多个验证者可以通过提交离线创建的签名(甚至是由另一个智能合约生成的签名)来授权操作。这项验证通常被用于多重签名冷钱包或者投票合同,以便一起提交各种签名或委托授权。

此类实现中的常见漏洞是签名重放攻击。在 Cryptonics 对一个重要项目的智能合约审计中,我们遇到了这个问题的一个有趣例子。在本文中,我们将使用此示例来说明智能合约中签名验证是如何出错的。

与签名验证相关的漏洞通常是由于误解了底层的密码学原理和签名的目的而引起的。因此,在详细了解此特定漏洞之前,我们先快速了解一下密码学签名的工作原理。

密码学签名

大多数的密码学签名体系都基于公私钥对。私钥能够对数据进行签名,而且此签名能够被对应的公钥所验证。就像它的名字所暗示的一样,一个用户的公钥是公开的,而私钥则一定要保密。

对数据进行加密签名可实现两个重要属性:

  • 数据签名者可识别性,这是通过恢复签名者的公钥来实现的。
  • 数据完整的可验证性,意思是签名可以用于证明自签名以来数据未被修改。

虽然这些是非常强大的属性,但是需要重点注意的是签过名的数据本身不提供额外的保障。 签名不能保证一条消息的唯一性,也不能保证签名人就是发信人本身。 当然,加密签名可以被用于确认相关事实,但是应用程序也须执行必要的检查。我们可以在以太坊智能合约中调查以上事实。

以太坊中的签名验证

以太坊比特币 一样,采用 椭圆曲线数字签名算法 (ECDSA)和 secp256k1 曲线。智能合约可以通过系统方法 ecrecover 访问内置的 ECDSA 签名验证算法。以下示例展示了这个函数的用法:

address signer = ecrecover(msgHash, v, r, s);

这个方法的输入参数是签名值 v,r 和 s,以及签名数据的 keccak256 哈希值。它可以校验数据的完整性,即确认数字签名与数据的哈希值相对应,并且可以从签名中恢复签名者的以太坊地址(以太坊地址乃是从公钥中推导出来的)。

任何额外的检查,不论是检查签名地址是否为正确地址,还是检查被签名的消息是否唯一,都必须被手动添加进智能合约中。

经常有人误解了 ecrecover 的功能,然后搞出了安全漏洞。

签名重放漏洞

代码示例

让我们来看一下我们在最近的合约审计中发现的漏洞:

function unlock(
  address _to,
  uint256 _amount,
  uint8[] _v,
  bytes32[] _r,
  bytes32[] _s
)
  external
{
  require(_v.length >= 5);
  bytes32 hashData = keccak256(_to, _amount);
  for (uint i = 0; i < _v.length; i++) {
    address recAddr = ecrecover(hashData, _v[i], _r[i], _s[i]);
    require(_isValidator(recAddr));
  }
  to.transfer(_amount);
}

以上代码是我们所审计的代码的简化版本,为使代码变得简短易懂,它只保留了最基础的信息。但是其中的漏洞被完整地保留了下来。

被审计的合约是跨链桥接器的一部分,它能让数字资产从一个区块链转移到另一个上。以太币在以太坊智能合约中被锁定之时,另一条链上会创建出对应的资产。当资产在另一条链上被锁定或销毁时, unlock 函数可以释放先前被锁定的以太币。要实现这个效果时,跨链中继者可以提交一系列的验证者签名、一个解锁的数额以及一个目标地址。这个函数要求至少五个签名来解锁需要的数额并将资金传给接收方。而内部的 _isValidator 函数(为了简化,省略掉了具体实现)会检查一个地址具不具备验证者身份。

攻击情景

以上代码的问题在于被验证者用 ECDSA 算法签过名的消息中。这个消息只包含接收者的地址以及需要解锁的数量。 在这个消息中,并没有什么内容能防止相同的签名被多次重复使用 。想象如下的情景:

unlock

改进手段

以上情形被称为签名重放攻击。这种攻击能成功是由于我们无法验证所签名消息的唯一性,也不知道它之前是否被用过。

一个防止此类攻击的简单方法是在被签名数据中包含一个消息序列号或者 nonce。 以上代码的修正版如下:

public uint256 nonce;
function unlock(
  address _to,
  uint256 _amount, 
  uint256 _nonce,
  uint8[] _v,
  bytes32[] _r,
  bytes32[] _s
)
  external
{
  require(_v.length >= 5);
  require(_nonce == nonce++);
  bytes32 hashData = keccak256(_to, _amount, _nonce);
  for (uint i = 0; i < _v.length; i++) {
    address recAddr = ecrecover(hashData, _v[i], _r[i], _s[i]);
    require(_isValidator(recAddr));
  }
  to.transfer(_amount);
}

这段代码现在要求每一个成功的解锁调用都包含一个序列号。因为消息中得包含一个独一无二的数字,所以每次成功调用所要求的签名都是独一无二的。这表示之前观测到的消息对攻击者来说没用了,因为重放会失败。

签名验证的最佳模式

上述例子只是其中一个示例,演示了不能保证唯一型的签名如何被重放。在大部分情景中,确保签名能够与每一次调用形成唯一的匹配对预防重放攻击是非常重要的。

但是,这段代码并不完美。它并没有遵循签名验证的最佳实践。原因是它没有检查 可塑性签名, 我们应检查作为已接受签名一部分的 s 值是否在较低范围内。使用 ecrecover 函数的推荐流程可以在 Open Zeppelin 的 excellent ECDSA 库 中找到。事实上,在社区审计过的代码,比如 Open Zeppelin 上进行开发,总是一个好主意。

原文链接: https://medium.com/cryptronics/signature-replay-vulnerabilities-in-smart-contracts-3b6f7596df57

作者:Stefan Beyer

翻译&校对:TrumanW & 阿剑

本文由作者授权 EthFans 翻译及再出版。


Recommend

  • 67

    第0章引言 即将面临的比特币分裂,如何保证你的币在分裂后肯定留下两种币?一个重点要防范的风险就是重放攻击。 第1章重放攻击原理 首先讲明白, 重放攻击其实根本就不是攻击。目前币圈流传的各种...

  • 55
    • www.tuicool.com 5 years ago
    • Cache

    一款ChromeHTTP请求重放插件

    工具介绍 一款用于chrome下的HTTP包重放工具HTTP请求记录又2种模式,一种为记录全部标签页的请求,另一种为记录当前devtool所在标签页的请求。 使用流程 F12打开后,选到pttools标签。 选择监听...

  • 34

    0×1前言 最近手头有个S7-300,根据之前多位大神S7协议相关的分析,决定自己动手实操一下,通过payload重放实现对PLC的启停及DO数据的读写,实验过程记录下来跟大家分享一下,欢迎各位大神来交流。 0×2实验环境...

  • 23

    在大学的时候看到某安全大会的时候,YQ大佬演示了汽车电子钥匙重放,然后成功搞定了汽车锁。我就想汽车的电子钥匙可以重放,电动车的肯定更容易,只要重复造轮子就能偷尽学校的电动车,迎娶漂亮学姐,走向人生巅峰。 (因为是大学...

  • 24

    自 ETH 2.0 采用 BLS 签名技术以来已有 2.5 年左右,以下是一些里程碑事件。 2018 年 5 月, 我在 ethresear.ch 上发表了一篇文章 ,指出...

  • 5
    • www.zenlife.tk 4 years ago
    • Cache

    binlog 的并行重放问题

    binlog 的并行重放问题2020-09-11问题描述是这样的,假设一个大的数据库集群吧,要增量同步到下游,会走一个 binlog 的系统。第一代的 binlog 系统的设计,把所有的 binlog 搜集到一个地方,然后重放,会形成一个单点。对于整个集...

  • 6
    • segmentfault.com 3 years ago
    • Cache

    面试官:啥是请求重放呀?

    面试官:啥是请求重放呀?这是why的第 103 篇原创你好呀,我是why。如图,重放攻击,这题我真的在面试的时候遇到过,两次。印象比较深的是第一次遇...

  • 11

    太长不看:UMA 构建了一个叫作多空仓位对(Long Short Pair,LSP)的新型合约模版。这个合约虽...

  • 2

    点击上方蓝字关注我,知识会给你力量

  • 12

    SharkTeam:十大智能合约安全威胁之重放攻击 SharkTeam 2022-11-10 18:04 摘要: 重放攻击是把原链网络上的交易拿到目标链网络上使用

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK