2022年7月5日 Chance Hudson @vimwitch 发现了Solidity代码生成器的漏洞。

漏洞影响范围是 0.5.8 ≤ version < 0.8.16, 被认定为中危。

该漏洞简单来说就是,如果合约encoding同一个tuple两次,那么第二次encoding时,动态类型的元素将会变为0。

触发条件

漏洞函数满足如下条件:

例如如下函数:


function f(bool a, bytes calldata b, bytes32[2] calldata c) public 
    returns (bool, bytes calldata, bytes32[2] calldata)
{
    return (a, b, c);
}

漏洞效果

设有漏洞函数如下, 函数功能是直接返回调用者输入的calldata。该函数会触发两次编码,一次在调用者组织参数时,另一次在函数returns返回函数值时。故触发漏洞。

contract E {
    function f(bool a, bytes calldata b, bytes32[2] calldata c)
        public
        returns (bool, bytes calldata, bytes32[2] calldata)
    {
        return (a, b, c);
    }
}

我们调用 E.f(true, "abcd", [bytes32("a"), "b"])

预期返回如下

0x0000000000000000000000000000000000000000000000000000000000000001 true
0x0000000000000000000000000000000000000000000000000000000000000080 参数2的offset
0x6100000000000000000000000000000000000000000000000000000000000000 c[0]
0x6200000000000000000000000000000000000000000000000000000000000000 c[1]
0x0000000000000000000000000000000000000000000000000000000000000004 参数2的长度
0x6162636400000000000000000000000000000000000000000000000000000000 参数2的内容

实际返回如下

0x0000000000000000000000000000000000000000000000000000000000000001 true
0x0000000000000000000000000000000000000000000000000000000000000000 ERROR 参数2的offset
0x6100000000000000000000000000000000000000000000000000000000000000 c[0]
0x6200000000000000000000000000000000000000000000000000000000000000 c[1]
0x0000000000000000000000000000000000000000000000000000000000000000 ERROR 参数2的长度
0x6162636400000000000000000000000000000000000000000000000000000000 ERROR 参数2的内容

Remix decoded output 如下

可见漏洞触发。bytes参数的值消失。

Untitled

漏洞原理