DeFi 生态当前最大安全隐患:授权模型

原文标题:《以太坊 DeFi 生态当前最大的安全隐患》

原文来源:比特派

01 

DeFi 很火、Compound 很热,业内都仿佛打入鸡血一般地参与到这个生态,创新、革命,终结中心化的这一天似乎马上就能到来。

预言机、智能合约钱包、去中心化借贷、去中心化交易、去中心化 blah blah……
很多区块链行业内的从业者们开始乐观地认为 DeFi 的黄金大厦已经基本完工。
02

不过,在 DeFi 晴朗的天空上,却还飘忽着几朵令人不安的乌云。

2020 年 4 月 18 日,Uniswap 爆出智能合约漏洞,该漏洞被人利用盗取了数十万美金的资产;

2020 年 4 月 19 日,Lendf.me 因相同漏洞,被一位程序员(非黑客)盗取了数千万美金的资产;

这两次的事件,在业内引起了轩然大波,尤其是 Lendf.me 的被盗,更是引发了更广泛地讨论:

「到底应该由谁来承担责任?」

「似乎去中心化之后就很难说清楚出了问题该找谁?」

「难道 DeFi 了之后,丢币就全得是用户承担了吗?」

幸运的是,因为盗取 Lendf.me 的人只是一名普通的程序员,并不是职业的黑客——他并不懂得如何更好的隐匿自己的行踪。因其泄露了 IP,并进一步被定位,最终这位程序员只能主动退还资产以避免受到法律上的惩罚。

在这件事情上,Lendf.me 的项目方和用户可以说是极其幸运的,他们躲过了巨额资产损失及冗长的法律诉讼的风险,从行业的角度上讲,找回了肯定是好事。但好事归好事,笼罩在 DeFi 生态上的乌云仍未消散,DeFi 的未来还安全吗?
03

关于智能合约安全,历史上已经发生过很多起事故了,这朵乌云其实一直就在那里,这也是行业需要一直面临下去的风险和挑战。

不过我们今天要跟您聊的是另一朵乌云,从安全的角度上讲,另一朵乌云的复杂度要低很多,但其影响却更广泛——几乎影响到了每一个参与 DeFi 的用户。

其影响程度明明很严重,但却一直被行业内的用户和从业者们所忽视。这朵乌云如达摩克利斯之剑,悬于 DeFi 的之顶,无论你是否无视它,它一直都在那里,静静地看着你,等待着机会将你一口吞啮。

作为比特派安全实验室成立之后的第一篇文章,我们将系统的把这朵乌云给大家讲清楚,并且还会包括完整的智能合约案例来给大家演示这朵乌云对于普通用户可能造成的资产安全风险。相信通过本文,用户们就能清楚的意识到,当你去参与以太坊的 DeFi 生态时,很多你不经意地操作所带来的风险可能没那么简单,这其中的风险,可以大到没有上限。

在正式开始讨论之前,我先问大家一个问题:假设你有 100 万个以太版本的 USDT,现在你决定向一个中心化的交易所转入 1 万。如果出了问题(比如说交易所被黑客攻击或者交易所老板跑路等等),你的风险上限是多少?

答案很简单,风险只是你存入的 1 万 USDT。剩下的 99 万都在你的钱包里,无论是黑客还是交易所老板都拿这些钱没办法,他们能偷走的只有那 1 万。

好了,现在相同的场景放到 DeFi 里:还是假设你有 100 万 USDT,现在你决定往一个去中心化的 DeFi 合约里存 1 万,如果出了问题(同样是 DeFi 智能合约/项目方被黑客攻击或者是 DeFi 老板跑路),你的风险上限是多少?

还是 1 万吗?错!你现在的风险上限很可能变成了 100 万 USDT,即便剩下的 99 万 USDT 明明还是安安静静地躺在你的钱包里,甚至你可以很小心地把这些 USDT 保管在绝不触网、绝对安全的硬件冷钱包里也一样,你的百万资产极有可能一瞬间就会灰飞烟灭,BOOM!
为什么会这样呢?原因就在于以太坊生态最基础的授权模型。

当你访问一个智能合约时,智能合约可能会为了「能更方便的操纵你的资产」的目的,向你申请授权,那这个授权调用又是个什么样子呢?

现在我们随便从链上找一笔授权交易来看一下:https://etherscan.io/tx/0x419d17e216cda75dd9635a752e9aedb8f43ed4bfe31a6f75ed8923779c73eb6e
这笔交易很简单,其实就是【0x3693】 这个地址授权给【Uniswap V2: Router 2】合约无限动用自己全部 USDT 的权力。

那这么做的好处又是什么呢?

在完成了这个授权操作后,Uniswap 就可以很方便地操作你的资产了,后续的调用少了,访问次数也少了。有的合约甚至还可以帮你兑换以太矿工费,也就是说,让你在没有 ETH 做矿工费的情况下,仍然可以调用这个合约。

这种授权方式的优点其实就是方便(主要是对项目方方便),方便到你甚至不用打开钱包了,也能帮你转币。

「什么?不用打开钱包了也能转币?谁能转我的币?」

这就是问题所在,只要你做了授权,该合约就可以不经你的许可,支配你所有的资产。记住,这跟你的私钥是如何保管的没有关系,哪怕你把你的私钥保管在硬件冷钱包里,放到冰箱里冻起来,该合约仍然能把你的币一扫而空。

好了,现在估计有人会说了,虽然合约能转走我的币,但智能合约代码如果是开源的,并且都经过了第三方审计,里面又没有转走我的币的代码,那我是不是就安全了呢?

其实跟合约授权相关的安全性跟是否开源以及有没有经过第三方审计关系不大,现在 DeFi 生态的大部分(基本上全部)复杂的智能合约,都是可以升级代码的,也就是说,今天的代码可能的确不能转走你的币,但明天 Owner 作恶更新一下代码,就能把你的币一扫而空了。(这里要特别说明一下,合约代码升级之后合约地址会发生变化,因此如果 Owner 想要转走你的币的话,还需要你再次进行授权,但考虑到各个 DeFi 项目以及各个钱包软件里对于授权操作都是一键完成的,因此,无论合约 Owner 改了几版代码,用户其实都不会关注到。因此,对于普通用户来说还是面临着同样的风险。)

看完授权交易的样例之后,我们现在再来看一个合约的样例代码:
https://github.com/bitpie-wallet/erc20-approve-issue-demo/blob/master/contracts/ExchangeDemo.sol

在这个样例中,我们模拟了一个智能合约漏洞的情况,假设合约开发者不小心将 ExchangeDemo 合约的 transfer 方法访问控制权限设置成了 public。在这种情况下,只要你对该合约进行了授权操作,哪怕你没有对该合约进行过任何转账操作,别人都能直接转走你钱包里的全部 Token,就这么简单。

当然,真实情况下的合约漏洞可能会很复杂,具体表现形态也是多种多样的,但这里我们想说明的是如果一不小心合约里写出了能被第三方动用授权者资产的漏洞,那毁掉的可就不仅是合约本身了,所有给该合约授权过的人的资产全部会被盗走。

有人可能会说了,那我们不写出能转走授权资产的漏洞就行了吧?道理没错,但现实中这是几乎不可能的。以太历史上无数次的漏洞都证明了这一点,只不过大部分漏洞只能影响到合约内的资产或者只能影响合约的执行方式,而授权相关的漏洞则会危及到所有做过授权的人的全部资产的安全,现在明白你到底在冒多大的风险了吧?
我们继续看下一个样例代码:
https://github.com/bitpie-wallet/erc20-approve-issue-demo/blob/master/contracts/ExchangeDemoV2.sol

在这个例子中,合约开发者升级了 ExchangeDemo 合约,升级之前的 claim 方法本来只能支取合约上的 token 的余额,但开发者将其修改成可以转走用户授权的 token,也就是更新之后,用户再进行授权操作,开发者就可以轻松的调用 claim 方法转走用户钱包里的币了,就这么简单。

上述样例中完整的测试用例及代码可以在 https://github.com/bitpie-wallet/erc20-approve-issue-demo/blob/master/test/ExchangeDemo.test.js 上看到,有兴趣的同学们可以试试。

通过 ExchangeDemo V1 和 V2 两个版本的智能合约样例我们可以看出,因为滥用授权,即便用户没有或者只向合约转入了很少的资产,如果合约有授权转账相关的漏洞,则所有授权过的用户钱包内的资产都将面临风险。即便是没有漏洞,合约开发者也具备更新代码后拿走授权用户钱包内全部资产的权力。

这里我们还可以再进一步展开来谈,一个向你索取无限授权的合约,其目的显然是为了能方便的操纵你的资产,而合约本身的功能当然也会与操纵你的资产相关,无论是交易、借贷、理财等等的,都要操纵资产。

因此,合约本身至少会有相关接口来进行转币操作,当然这个转币操作都是功能性的,比如说为了抵押的目的向合约地址存入 5 万 USDT,或者为了兑换的目的向合约地址存入 1 千 USDT,好了,现在的问题是,既然合约本身就有这类的接口,合约 Owner 也就有可能(这里需要看合约代码的写法)未经你的许可继续使用相同调用让你往合约里存入更多的资产,也就是说,即便不升级代码或者没有相关漏洞,这种可能性也是存在的,尤其是那种可以替你代付了以太矿工费的合约,说明连调用的发起审核都可能是由合约 Owner 来负责的。

也就是说,如果一个智能合约在你授权后能够有一个方法将你的一千元转入合约地址,自然也可以用相同的方法转入一万、十万、一百万,而转入合约地址或者其它相关地址之后,合约 Owner 其实就有能力拿走这些资产了。

这里我们要说明一下,像 0x 这类的合约在这一点上是做了一些防范的,他们在调用接口时验证了用户的签名,也就是说至少能确保调用操作是用户发起的。但这种其实就很依赖于合约代码的编写方法了,合约代码里可以验证用户签名,也可以验证合约 Owner 的签名,当然还可以啥都不验证,合约方法也可以是由用户调用或者是由合约 Owner 调用,不同的写法会把你钱包里币的控制权给了不同的角色,听着是不是很吓人呢?

估计又有人要说了,如果智能合约的 Owner 不作恶,不就没这个问题了吗?

这里我们要说明一点:去中心化首先要做到的是无需第三方信任,如果一个去中心化项目要求你必须信任合约 Owner,那去中心化的意义何在呢?

另外,更为重要的是,你本来以为合约 Owner 对于你的资产的影响仅仅局限于你参与到该智能合约的部分,比如说你为了交易而转给 dex、为了理财而转给去中心化借贷合约的币,你以为合约 Owner 只能影响到你存进去的那部分资产,现在就应该明白了,合约 Owner 能影响到的不止是这一部分,他还能影响你钱包里的剩余资产,无论你的钱包是热的还是冷的,没关系,都可以是我的。

接着说,即便是我们假设合约 Owner 是道德上极其完美的人,但随着智能合约越来越复杂,众所周知出现漏洞的风险也就越来越高,在之前的理解里,大部分人可能认为的都是如果出现漏洞,主要的资产风险还是合约内的,攻击者最多也就是把你存在合约里的币都给拿走。但本文中的样例告诉了你这么一个事实,如果合约漏洞恰好是跟授权转账相关的,那风险就扩散了,所有曾经给该合约授权过的地址都会被一扫而空,只要攻击者扫描一下都有那些地址进行过授权操作,然后挨个把这些地址上的币都给转走就好了。

更重要的是,这还给了智能合约的开发者们如何安全的保管 Owner key 提出了更高的要求,如果哪天你的 Owner key 丢了,那完蛋的可不仅仅是存在合约里的币,完蛋的是所有授权用户钱包里的全部资产,这又有谁能承担呢?
看到这里,你是不是就明白为什么本文的标题是「以太坊 DeFi 生态当前最大的安全隐患」了吧?
04
由于以太坊生态里对于授权的滥用已经到了非常严重的程度,我们甚至可以说几乎所有的 DeFi 合约都在毫无节制的索取无限授权,在这种情况下,出于小白鼠的目的实验各种 DeFi 项目的行为本身无可厚非,但如果告诉你,所冒的风险是你的全部资产,而并非仅仅是拿来参与 DeFi 的那点儿币,你又该作何感想呢?

区块链行业内对于以太坊生态的授权滥用情况之前曾有过一点点声音,但其实还远远不够,无论是开发者、从业者、用户等群体,99.9% 的人对此一无所知,滥用授权的情况几乎是全部,是时候来改变这一现状了。

这里我们列出了一些滥用授权(无限)的项目案例:
Compound

Uniswap

Kyber

Maker

0x

Balancer

dYdX

EtherDelta

IDEX

上述列表中的前面几个 Compound、Uniswap、Kyber 正是当前 DeFi 世界中炽手可热的明星项目,但这些项目却无一例外的选择了让用户无限授权以获得用户资产的完全控制权,也就是说任何用户只要是使用过上述项目,你的钱包里的币就有可能随时会面临本文中所提到的风险,这其实是很遗憾的一件事情。

我们对一部分无限授权了的地址进行了筛查,发现多数的地址上都仍存有资产,其中好多地址更是不乏拥有百万千万甚至亿级别的资产,而这些地址的拥有者,其实已经在自己不知情的情况下把资产的支配权交予了别人。

上述合约都应调整自己的授权代码,将其改为按需授权,比如说,你只需要兑换 1000 USDT,那就只授权 1000 USDT,额外的所要授权都是越权行为。

使用这些合约的用户也应该改变自己的 DeFi 合约使用行为,应该将不参与 DeFi 的币放到另一个不会授权给任何应用的地址,以保护自己的资产安全。

由于以太生态的发展演化非常快,我们专门在比特派里设计了以太安全中心,当你切换到以太体系之后就能看到,在以太安全中心里我们目前开发了合约授权检测功能,除了可以看你在比特派里的地址是否有哪些滥用授权的情况,还可以随便看外部的任意一个地址的当前授权情况。对于被滥用的授权,还可以进行授权回收操作。

关于比特派的合约检测功能,我们将专门写一篇说明文章来指导大家如何使用,您的地址现在安不安全?检测一下就知道了。

说到授权被广泛滥用,比特派在这块是怎么做的呢?

以比特派钱包中很常用的批量转账功能为例,我们的做法是有限授权,也就是说,如果你需要将 100 个 USDT 转到 50 个地址上,比特派只会授权 100 个 USDT,不会产生任何额外的授权。

再比如说,比特派的代付 USDT 矿工费功能,我们就完全没有使用合约授权,哪怕明明是使用授权方式实现起来更简单,我们都没这么去做,其实就是因为这个道理,项目方应该以用户的权益放在首位,任何徒增用户风险的行为都应该被抵制。
05
考虑到这朵乌云之下的安全,普通用户参与 DeFi 应该采取哪些防范措施呢?

1、定期使用像比特派这样的钱包中提供的授权扫描功能,来看看都有哪些合约获得了你的授权(无限授权);
2、使用多个以太坊地址,将存币地址和参与 DeFi 地址分开,把仅用于 DeFi 活动的币放到 DeFi 地址中,这样即便是乌云压顶了,存币地址里的币还是安全的;
3、回收一些应用的授权,降低风险,至少你应该清楚哪些应用可以不经你的许可直接转走你钱包里的币才行;
4、呼吁项目方不要滥用授权,按需授权,以降低用户的安全风险。
结语

去中心化金融的确代表着未来,也是区块链技术非常重要的应用场景。
但将我们聚在一起的,从来不是天翻地覆的概念、不是深奥晦涩的代码、不是天花乱坠的技术,一直都是私有财产神圣不可侵犯的信念。
只有它能让我们继续走下去,直到拨云见日。

原文地址