DeFiVulnLabs靶场全系列详解(三十七)不正确的abi.encodePacked编码导致哈希一致

admin 2025年5月20日03:27:49评论1 views字数 2294阅读7分38秒阅读模式
01
前言
此内容仅作为展示Solidity常见错误的概念证明。它严格用于教育目的,不应被解释为鼓励或认可任何形式的非法活动或实际的黑客攻击企图。所提供的信息仅供参考和学习,基于此内容采取的任何行动均由个人全权负责。使用这些信息应遵守适用的法律、法规和道德标准。
DeFiVulnLabs一共有47个漏洞实验,包括各种经典的合约漏洞和一些少见的可能造成安全问题的不安全代码,本系列将逐一解析每个漏洞,包括官方的解释和自己的理解。
02
不正确的abi.encodePacked编码导致哈希一致
漏洞解析:

首先复习一下solidity中的4种编码函数

    1、abi.encode:用于将数据编码为可以在合约之间传递的二进制格式。

abi.encodePacked(123"Hello, World!");

    2、abi.encodePacked:将数据编码为紧凑的 ABI 格式,不包含填充字节。

 abi.encodePacked(123"Hello, World!");

    3、abi.encodeWithSelector

abi.encodeWithSelector(bytes4(keccak256("transfer(address,uint256)")), address(0x123...), 100);

    4、abi.encodeWithSelector,但使用完整的函数签名而不是函数选择器。

abi.encodeWithSignature("transfer(address,uint256)", address(0x123...), 100);

这里使用的abi.encodePacked编码能够将给定参数根据其所需最低空间编码,主要用于节省空间,但是节省空间的同时可能也会带来安全问题。

代码地址:
https://github.com/SunWeb3Sec/DeFiVulnLabs/blob/main/src/test/Hash-collisions.sol
代码解析:
    如下代码存在一个存款函数deposit,用户每次转入ETH都可以自定义密码,然后使用这个密码来生成一串Hash值来被当做存款编号。
    但是由于生成Hash的函数的之前的压缩编码过程使用不当,进而导致Hash可以被碰撞导致可以生成相同的Hash,对用户存款的资金产生威胁。
pragma solidity ^0.8.0;contract HashCollisionBug {    mapping(bytes32 => uint256) public balances;  //创造balances数组,内容为uint256//创造一个hashfunctioncreateHash(  string memory _string1,  string memory _string2publicpurereturns (bytes32) {  return keccak256(abi.encodePacked(_string1, _string2));    }//存款方法functiondeposit(  string memory _string1,  string memory _string2externalpayable{//存入ETHER  require(msg.value > 0"Deposit amount must be greater than zero");  //获取hash值        bytes32 hash = createHash(_string1, _string2);  // createHash(AAA, BBB) -> AAABBB  // createHash(AA, ABBB) -> AAABBB  // Check if the hash already exists in the balances mapping  //如果该hash键的值为0,才能存入以太坊,不然被视为碰撞  require(balances[hash] == 0"Hash collision detected");  //生成hash键,值为传入的ether值        balances[hash] = msg.value;    }}
03
remix复现

    传入值,生成hash,然后调用deposit进行转账ether,该转账ether对应的值记录在对应hash上,可以理解为"[订单编号(hash):ETH value]"

DeFiVulnLabs靶场全系列详解(三十七)不正确的abi.encodePacked编码导致哈希一致

    但是由于采用了encodePacked进行压缩,encodePacked是最低编码,会省略其中的所有的0单位,尤其还是字符串都是可控的情况下,所以会产生问题,如下图所示

DeFiVulnLabs靶场全系列详解(三十七)不正确的abi.encodePacked编码导致哈希一致

使用abi.encodePacked生成的编码值为最低编码值

所以计算出来的值为keccak256(0x31323334)

DeFiVulnLabs靶场全系列详解(三十七)不正确的abi.encodePacked编码导致哈希一致

可以看到,传入值12,34  和1,234所产生出来的值是一样的,自然所计算出来的hash也是一样的。

04
如何修复该问题

使用abi.encode替换abi.encodePacked即可,它会为每个参数添加长度前缀,并确保编码结果是固定长度的

        例如:1 = 131  ,12=23132  ,234= 3323334
        可以看到他们如果添加了0填充后,数值就不一样了,使用这个数值进行keccak256哈希自然也不一样
DeFiVulnLabs靶场全系列详解(三十七)不正确的abi.encodePacked编码导致哈希一致
05
感谢关注
个人语雀账号:https://www.yuque.com/iceqaq

原文始发于微信公众号(Ice ThirdSpace):DeFiVulnLabs靶场全系列详解(三十七)不正确的abi.encodePacked编码导致哈希一致

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年5月20日03:27:49
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   DeFiVulnLabs靶场全系列详解(三十七)不正确的abi.encodePacked编码导致哈希一致https://cn-sec.com/archives/4082181.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息