这份智能合约「避坑指南」建议收藏
在这篇文章中,我将分享一些基于现有漏洞而总结的小贴士,希望能让你的智能合约更加安全。虽然这些贴士不能确保让你的智能合约对黑客完全免疫,但至少可以帮助你避免一些最常见的错误。
黑客无处不在
作为一名机智的合约开发者,你的代码是唯一可以信任的东西。具有防备心是十分重要的。
不要信任你的用户
在编写代码的时候,你应该始终假设你的用户是潜在的黑客,会尽力寻找你智能合约中的漏洞,并会毫不犹豫地加以利用。作为一名安全研究人员和程序开发人员,我有很多被攻击的经验,我的经验教训是,无论漏洞看起来多微小,后果都可能是十分严重的。
用代码解决问题
编写一份智能合约就像编写 Web 应用程序一样,你要区分前端和后端。在区块链上运行的智能合约是后端。除了合约之外,你还需要编写一个前端应用程序作为用户与你的智能合约进行交互的接口。
那么问题来了,你应该在前端还是后端验证用户输入呢?例如,你正在编写一个别名服务将区块链地址与人类可读的字符串连接起来。然而,如果你想控制文本的长度,那你应该在哪里写下格式验证逻辑呢?前端还是后端?
答案肯定是后端。这可能是个细节问题,但却十分关键。虽然听起来有点荒谬,但是你可能也需要将前端开发者当作是你的敌人,假设他们也会和黑客站在另一边。聪明的合约开发者会在代码中写下所有逻辑,我们只相信我们的代码。
输入长度
Neo 智能合约中的一个大问题是它存储数据的方式。带有一对键值的 Storage.put() 被用来存储各种数据。表面上看起来,这种方式既易用又酷炫,就像我们面对的是一本字典或一副地图一样。但问题是,如果你在存储数据时没有正确地验证密钥格式,你就会有大麻烦了。例如,我们的 NEP5 智能合约中有一个 “totalSupply” 关键字,表示该 NEP5 通证的最大值,并且在合约中有如下转账功能:
目前我们在 NEP5 模板中有一个长度检查的逻辑。假设这个逻辑被有意或者无意者移除,用户就可以输入任何字串作为参数:
接下来,我们将 “to” 参数作为 “totalSupply” 输入,这样一旦这个命令被成功执行,我们就可以改变该通证的总供给量:
因此,一定要检查每个函数的输入格式。Neo 的交易目前是免费的,多添加几行检查代码并不会有什么坏处。
我还认为,作为常用的数据类型,在 Neo 智能合约中应该为地址设计特定的数据类型。
检查目标地址
在我们开始讨论这个问题之前,我想请大家先看看 NEP5 智能合约中的转账功能:
当然,这不是原来的版本,我稍微修改了一下,使其容易受到某种类型的攻击。你能解决这个问题吗?
在相同的地址间运行 From 和 To,可能会触发这个 bug。使用被分配给 From 和 To 的相同地址,第一个 PUT 语句将 newFromvalue 保存到该地址。尽管如此,第二个 PUT 语句仍将该值更改为 newToVal,该值甚至比前一个 Balance 更大。这样,你就可以凭空铸造新的通证。
现在,你是否对智能合约的安全性有了更深的了解?
上一篇:ABT 节点的若干应用实例
下一篇:如何在比特币上打造高级智能合约?