2022年7月5日 Chance Hudson @vimwitch 发现了Solidity代码生成器的漏洞。
漏洞影响范围是 0.5.8 ≤ version < 0.8.16, 被认定为中危。
该漏洞简单来说就是,如果合约encoding同一个tuple两次,那么第二次encoding时,动态类型的元素将会变为0。
漏洞函数满足如下条件:
bytes32[10]
or uint[2][2][2]
bytes
or string
例如如下函数:
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参数的值消失。