合约安全

合约安全:使用外部合约隐藏恶意代码

2022-12-07  本文已影响0人  梁帆

本文说的其实不算是漏洞,更像是一个项目方的后门,也是需要注意的,尤其是使用者需要警惕的。
这个案例告诉我们:开源给你看的合约代码,未必是实际执行的代码。

一、案例说明

合约开发者暴露给外部的合约如下:

contract Foo {
    Bar bar;

    constructor(address _bar) {
        bar = Bar(_bar);
    }

    function callBar() public {
        bar.log();
    }
}

contract Bar {
    event Log(string message);

    function log() public {
        emit Log("Bar was called");
    }
}

这个Foo合约是给使用者操作的合约,如果我们单看这两个合约,似乎没看到什么问题。但是请注意这里的构造函数,初始化了Bar合约的地址,但是我们并不是非得传入Bar合约的地址,我们可以传入另外一个钓鱼合约的地址,如下:

contract Mal {
    event Log(string message);

    function log() public {
        emit Log("Mal was called");
    }
}

这个Mal合约,并没有暴露给外界,而且有和Bar合约一样的方法log,这个合约部署完成后,Foo合约用Mal合约地址进行初始化,这样使用者在调用callBar的时候,实际上调用的是Mal合约上的log方法。

这种后门是比较隐蔽的,如果没有看到它每一步的部署,很可能会被项目方骗。

二、预防方法

contract Foo {
    Bar public bar;

    constructor() public {
        bar = new Bar();
    }

    function callBar() public {
        bar.log();
    }
}

可以看到改进后,bar的可见性从默认的internal变成了public;此外,constructor也不用合约地址初始化了,而是在里面new了Bar合约,这样就保证bar变量确实是Bar合约的地址,自行证明了合约的清白性。

上一篇下一篇

猜你喜欢

热点阅读