本文介绍了如何使用Cyfrin的safe-tx-hashes工具来验证安全的多签名钱包签名,以修复Radiant Capital黑客事件的教训。文章强调了在进行多签名交易时,确保每个交易的签名数据的真实性的重要性,并提供了详细的操作步骤和代码示例。
了解如何使用 Cyfrin 的 safe-tx-hashes 工具验证 Safe 多重签名钱包的签名 - 这是对 Radiant Capital 黑客事件的修复。
非常感谢 pcaversaccio 推动这个并编写原始工具。
Radiant Capital 黑客事件(基本上)是这样的:
这个代价高昂的错误强调了理解和验证多重签名(multi-sig)交易的关键重要性。如果你想参与安全委员会、DAO、事件响应或 DevOps 团队,能够验证签名是一项必须具备的技能。即使你只是想确保自己的个人账户不被攻击。
多重签名钱包以其安全性而闻名,但为了有效利用这种安全性,你需要知道如何验证你正在签署的内容确实是你打算签署的。
让我们学习如何验证你在 Safe 多重签名 过程中的每个部分,以便你不会成为此攻击的受害者。
如果你更愿意观看,我们在 YouTube 上还有一个逐步指导的视频。
学习这个以免你损失 5000 万美元 | 多重签名(Safe)硬件钱包验证 - YouTube
Patrick Collins
162K 订阅者
学习这个以免你损失 5000 万美元 | 多重签名(Safe)硬件钱包验证
Patrick Collins
搜索
信息
购物
轻触以取消静音
如果播放没有很快开始,请尝试重启设备。
你已退出登录
你观看的视频可能会添加到电视的观看历史中并影响电视推荐。为了避免这种情况,请在计算机上取消订阅并登录 YouTube。
取消确认
分享
包含播放列表
检索共享信息时发生错误。请稍后再试。
稍后观看
分享
复制链接
在此观看
0:00
/ •直播
•
首先,你需要下载这个工具。前往 safe-tx-hashes 仓库下载 safe_hashes
可执行文件。
这个工具使我们能够快速输入安全交易数据,查看我们应该获得的内容,并验证显示在我们钱包中的内容确实是正确的。
在此过程中,首先理解我们做出的安全假设和可能的威胁向量很重要,以便能够避免它们。
使用这个工具,我们已经假设以下工具是安全的:
bash
perl
让我们从一个场景开始。
你的团队需要批准 Uniswap 路由器访问你的 USDC 进行交换 - 这是一个相对常见的 DeFi 交易。你的 Safe UI 可能看起来像这样:
当你滚动到页面底部时,你会看到一个大“签名”按钮。当你点击它时,你的钱包会显示一条消息让你进行验证,这可能看起来像这样:
这是我们需要验证并确保其操作正确的 Safe 交易消息哈希。那么,它到底在做什么?
这条消息是我们多重签名用于验证交易的 EIP-712 签名。必须有足够的用户以特定格式签署一条消息以使其被接受。如果你想了解更多,我们在博客和 Cyfrin Updraft 中讨论了 EIP-712 和 191。
安全哈希的计算如下(在 Solidity 中):
keccak256(abi.encodePacked(bytes1(0x19), bytes1(0x01), bytes32($domain_hash), bytes32($message_hash)))
消息哈希是这样计算的(使用 bash/foundry):
local message=$(cast abi-encode "SafeTxStruct(bytes32,address,uint256,bytes32,uint8,uint256,uint256,uint256,address,address,uint256)" \
"$safe_tx_typehash" \
"$to" \
"$value" \
"$data_hashed" \
"$operation" \
"$safe_tx_gas" \
"$base_gas" \
"$gas_price" \
"$gas_token" \
"$refund_receiver" \
"$nonce")
# 计算消息哈希。
local message_hash=$(cast keccak "$message")
本质上,这些哈希结合所有关键交易组件以创建唯一签名。这确保当多重签名钱包验证签名时,它能够确定该签名确实对应于该特定交易在该特定钱包实例上。
现在,重要的是我们必须完全确定这个签名包含我们期望的数据。如果有人想让我们签署不同的交易,他们只需更改哈希为 data_hashed
的数据。但是,这将返回一个不同的签名!所以如果我们保持警惕,我们可以发现这一点,而不签署。
因此,我们的过程将是离线重建我们所期望的签名,然后与我们从硬件钱包获取的签名进行比较。
当你到达 Safe UI 的这个页面时,Safe API 会“保存”这里的数据,以便我们可以调用 API 来填充我们的工具。我们可以简单地运行:
safe_hashes --address <MULTI_SIG_WALLET_ADDRESS> --nonce XX --network xxxx --untrusted
这将从 Safe UI 提取所有数据,并直接显示给我们!包括交易参数和预期签名。例如,你可以运行这个脚本自己查看输出!
safe_hashes --network sepolia --address 0x86D46EcD553d25da0E3b96A9a1B442ac72fa9e9F --nonce 7 --untrusted
你将得到如下输出:
交易数据
多重签名地址:0x86D46EcD553d25da0E3b96A9a1B442ac72fa9e9F
收件人:0x7b79995e5f793A07Bc00c21412e50Ecae098E7f9
值:0
数据:0x095ea7b3000000000000000000000000fe2f653f6579de62aaf8b186e618887d03fa31260000000000000000000000000000000000000000000000000000000000000001
编码消息:0xbb8310d486368db6bd6f849402fdd73ad53d316b5a4b2644ad6efe0f941286d80000000000000000000000007b79995e5f793a07bc00c21412e50ecae098e7f900000000000000000000000000000000000000000000000000000000000000001c62604b0ed9a9ec0e55efe8fb203b3029e147d994854cf0dd8a9fcf5b240d600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
方法:approve
参数:[\
{\
"name": "guy",\
"type": "address",\
"value": "0xfE2f653f6579dE62aAF8B186E618887d03FA3126"\
},\
{\
"name": "wad",\
"type": "uint256",\
"value": "1"\
}\
]
传统 Ledger 格式
二进制字符串字面量:\xe8\xc9\xfbR\xf3$\\xc5\xe451\x1b\xa4\xd5pAJ4=\x80\xeal7g\xa1jy\xbd*\xaa\x0c7
哈希
域哈希:0xE411DFD2D178C853945BE30E1CEFBE090E56900073377BA8B8D0B47BAEC31EDB
消息哈希:0x27B5FF2CB38C914873DAF41B5A4984C76DB35F1812877F72A9D5DEA6960ED0B1
安全交易哈希:0xe8c9fb52f3245cc5e435311ba4d570414a343d80ea6c3767a16a79bd2aaa0c37
这笔交易是基于 Safe UI 给我们的数据计算的。我们也可以看到这里发送的交易!通过这样,我们可以验证交易是正确的,并确认 安全交易哈希
是否与我们在钱包中看到的匹配。
如果黑客在他们给我们发送恶意交易时接管了 Safe UI/API,我们的脚本将重新计算预期哈希,并且我们会通过检查 method
部分看到交易数据是恶意的,或者我们会看到不同的哈希,我们会拒绝该交易!
然而,如果 Safe API 被攻破,我们就需要手动进行验证过程。
要在没有 Safe API 的情况下验证哈希,我们只需手动将数据添加到我们的工具中,并使用 --offline
标志。像这样(你也可以运行它!):
safe_hashes --offline --data 0x095ea7b3000000000000000000000000fe2f653f6579de62aaf8b186e618887d03fa31260000000000000000000000000000000000000000000000000000000000000001 --address 0x86D46EcD553d25da0E3b96A9a1B442ac72fa9e9F --network sepolia --nonce 6 --to 0x7b79995e5f793A07Bc00c21412e50Ecae098E7f9
数据是使用 cast 工具计算的:
cast calldata "approve(address,uint256) 0xfe2f653f6579de62aaf8b186e618887d03fa3126 1
你可以通过 这个视频 学习更多关于获取 calldata 和验证交易的内容。这将给你如下输出:
交易数据
多重签名地址:0x86D46EcD553d25da0E3b96A9a1B442ac72fa9e9F
收件人:0x7b79995e5f793A07Bc00c21412e50Ecae098E7f9
值:0
数据:0x095ea7b3000000000000000000000000fe2f653f6579de62aaf8b186e618887d03fa31260000000000000000000000000000000000000000000000000000000000000001
编码消息:0xbb8310d486368db6bd6f849402fdd73ad53d316b5a4b2644ad6efe0f941286d80000000000000000000000007b79995e5f793a07bc00c21412e50ecae098e7f900000000000000000000000000000000000000000000000000000000000000001c62604b0ed9a9ec0e55efe8fb203b3029e147d994854cf0dd8a9fcf5b240d600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
跳过解码数据,因为已传递原始数据
传统 Ledger 格式
二进制字符串字面量:!;\xe07'\\x94D\x9a(\xb4\xed\xea\xd7k\x0dc\xc7\xe1+R%\x7f\x9dV\x86\xd9\x8b\x9a\x1a_\xf4
哈希
域哈希:0xE411DFD2D178C853945BE30E1CEFBE090E56900073377BA8B8D0B47BAEC31EDB
消息哈希:0x4BBDE73F23B1792683730E7AE534A56A0EFAA8B7B467FF605202763CE2124DBC
安全交易哈希:0x213be037275c94449a28b4edead76b0d63c7e12b52257f9d5686d98b9a1a5ff4
这样,你甚至不需要信任 Safe API!
一旦交易至少签署过一次,你就可以通过 Safe API 获取其签名,而不需要传递 --untrusted
命令。
然后,当每个人都签署并验证后,你可以再次运行该命令,使用 --print-mst-calldata
标志查看 calldata 应该是什么样子,以便你可以进一步验证实际交易。
你可以在 GitHub 仓库 查看更多示例、文档和 safe_hashes
工具。
确保多重签名交易的安全性不仅仅是使用正确的工具,还包括理解过程及潜在的风险。通过遵循这些指南,你可以有效地保护你的加密货币资产。
请为你和你的团队制定一个验证签名的流程,以免你落入和 Radiant 团队相同的黑客陷阱!
- 原文链接: cyfrin.io/blog/verify-sa...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!