- A+
以太坊去中心化APP(dApp)是基于一致性协议(consensus protocol)的应用,dApp最常用的应用情景就是一个常规的Web应用与一个或多个智能合约进行交互,本文中,我们就对这种应用情景过程的安全性进行一个渗透测试。
智能合约(Smart Contracts) 是在 Ethereum 区块链中所属的对象。它们包含代码函数以及能够与其他合约进行交互、做出决策、保存数据与发送乙太币给其他人。合约是由创建者所定义,但是它们的运行与他们所提供的服务,都是由 Ethereum 网络本身提供。它们将存在且可被运行,只要整个网络存在,并且只会因程序中有撰写自我销毁的功能才会消失。
实例1 – CryptoKitties以太猫
当我们利用MetaMask之类的客户端插件通过Web访问某个dApp时,我们就能在网站的Web接口中使用自己的私钥对交易进行签名。
以下就是一个我们常见的dApp应用实例,我可以通过它提供的Web接口和包含我自己以太坊钱包的Chrome插件来实现交易,完成一个CryptoKitties以太猫的购买操作。
CryptoKitties是一款数字“撸猫”的游戏,它是世界首款区块链游戏,主角是一帮名叫CryptoKitty小可爱,我们要去收集并繁育它们。每只猫都拥有独一无二的特性,并且百分百属于你,除非你想卖出它,否则它不会被抢走,替代,或是销毁,用户可以通过交易这些猫咪来间接赚取以太币。
当我们的浏览器与正常的Web应用进行交互时,Web版中的app应用会与其它的内部服务器、数据库或者云端服务进行通信交流,最终整个交互过程非常简单:
而在dApp应用内部,很多的交互过程与Web版本app类似,但还存在一个第三方因素:可以公开访问的智能合约。
一些Web应用交互会涉及到对以太坊区块链上一个或多个智能合约的读写操作:
多种方法测试
dApp的部份功能目的就是方便终端用户对智能合约的使用,但在这个过程中,也没有明确的规定,说明我们必须通过dApp的Web接口,来与dApp的智能合约进行交互。由于智能合约是可以公开访问的,那好吧,我们尝试绕过Web服务器的一些交易限制逻辑,来直接操作智能合约试试。
现在,我们有两种方案来进行这种渗透测试:
标准的涉及身份认证、访问控制和会话管理等技术的Web应用渗透测试
智能合约审计
换句话说,也就是我们对Web应用以及智能合约的运行逻辑进行检查,看看其中是否存在逻辑错误。由于以太坊中会存在一些函数修改器(modifier),所以其实我们还可以构造出另一种渗透测试方式。
Modifier
Modifiers :函数修改器,用在智能合约中进行一些函数功能行为的修改,例如对函数执行前置条件的自动检查,修改器是一种可被继承合约属性,还可被继承的合约进行重写(override)。函数修改器可以实现智能合约中的管理、增发、兑换、冻结等高级功能。
在以太坊中,我们可以编写仅能从特定以太坊地址调用才能执行的函数,比如onlyOwner就是modifier的一个典型应用,如果我们正确实现了onlyOwner,那么只有合约的所有者(owner)才能运行某些函数。也就是当用这个onlyOwner修改器区修饰一个函数时,则函数必须满足onlyOwner的条件才能运行。
contract mortal {
/* Define variable owner of the type address */
address owner;
modifier onlyOwner {
require(msg.sender == owner);
_;
}
function writeData(bytes32 data) public onlyOwner returns (bool success) {
// will only run if owner sent transaction
}
…}
虽然我们可以直接与智能合约进行交互,但只有类似的onlyOwne修改器被正确实现,我们才能执行相应的函数。然而,在与dApp进行交互通信时,特定权限用户地址的私钥会存在于Web服务器之上,而且Web应用会具备某些特定逻辑,通过读取用户在Web应用上的输入,并使用其中某个私钥来调用智能合约中的某个特权函数。
由于dApp确实可以访问这些特权的以太坊地址,所以,第三个种渗透测试方式就可以是:“如何用dApp写入我们想要的智能合约中的特权函数?”
综合考虑这一点,我们可以构造出三种攻击面来:
标准的涉及身份认证、访问控制和会话管理等技术的Web应用渗透测试。这个测试过程可能不会涉及到智能合约本身,只会是一些Web应用相关的横向或者纵向的提权、数据库注入、XSS等测试。
智能合约审计。这个过程可能会涉及到一些权限问题、上行或者下行的函数溢出、包含的竞争条件等。
尝试通过Web接口伪造智能合约的特权写入。这里就要求我们是否能找到一种方式,能让Web应用以意想不到的方式与智能合约进行交互。
总结来讲,可以把dApp的攻击面描述成以下几句话:
你就往正常Web应用都会存在的漏洞方面去想:
… 现在,这个App应用有以下特征:
是从头开始构建的数据库软件
这些数据库存在对外开放可能
会在这些数据库信息中有所发现
这些问题也是以太坊App开发者同样会面临的。
用BurpSuite进行请求通信抓包分析
回到之前的CryptoKitties以太猫购买操作中去,当我们注册了Cryptokitties账户后,Web应用的逻辑处理会从你的MetaMask插件中提取你公开的以太坊地址,随后,网站会要求你输入邮箱地址和用户昵称信息。
接下来这步就比较关键了,由于dApps是基于公钥认证机制,而非密码认证机制,来对以太坊账户进行操作的。
因此,Cryptokitties网站会要求你对一条包含“Cryptokitties”的消息进行签名,以确认你拥有与该地址对应的私钥。
这个请求的抓包分析如下:
理论上讲,Cryptokitties网站会验证sign参数中的数据,即已签名的“Cryptokitties”消息是否与你以太坊地址中的地址参数对应。
该验证过程会Web应用的处理逻辑中进行,但我之前也碰到过一些dApp对签名验证的错误处理过程,我可以将请求中的以太坊地址替换成与签名不匹配的以太坊地址,如下所示:
Cryptokitties网站的签名验证流程是没问题的,但是如果当dApp运行出错,我就能用伪造的以太坊地址发起拒绝服务攻击(DoS),也能对用户的身份认证进行伪造。
实例2 – 登录测试
在登录阶段的测试中,我们用高端dApp的 Bloom(宝兰)来作举例,这是一个去中心化的信用评分系统,你可以在其官网创建一个去中心化的身份标识,它的工作原理就是把个人身份标识和以太坊地址绑定,避免像社会安全码这种能被窃取或伪造。由于Bloom是目前比较成熟的dApp之一,所以我推荐大家可以去注册尝试玩玩。
Bloom具备严格的认证处理措施,在账户注册完成之后,后续任何的发自你以太坊地址的登录都需要对相应的一条消息进行签名认证,该消息包括用户的登录意图、邮箱地址和当前时间等信息。
Bloom对这些字段的签名进行一些分解认证的原因有以下几点:
操作意图:如果用户不了解他们签名的东西,则签名内容以及签名发送数据就存在风险,所以Bloom会在那条消息文本中给出明确的签名操作意图。
邮箱地址:Bloom可从你的签名中恢复出邮箱地址,以此检查这个邮箱地址是否与绑定以太坊地址进行注册时的邮箱一致,如果两者匹配,则此次登录行为有效)。
时间戳:明显这能用来防止重放攻击,如果签名未包含有当前的时间信息,看到过这条签名的恶意攻击者可以随时对这些签名消息进行重放,用来进行一些用户身份认证。正常签名后,如果Web应用在几分钟时间内收到签名数据,则Bloom会认为这个签名有效。
以上任何一个字段出错被篡改就会提示出错,这也侧面表明Bloom在认证处理方面的措施部署地很恰当。
智能合约漏洞
我们在之前也对智能合约的某种可能的攻击方式作了讨论,比如通过审计方式去直接发现智能合约漏洞。接下来我们来分析一个在野环境中出现的某些此类漏洞。
batchOverflow
这个漏洞叫batchOverflow漏洞,从名字中我们可以知道这是一个溢出漏洞。
观察以上代码段,我给大家一个小小测试,看看大家是否有解决这个溢出漏洞的方法,也就是在上述存在溢出的batchTransfer函数,加入一行什么代码就能避免溢出漏洞发生。在查看答案之前,大家可以试一下能否找到该漏洞的具体利用方法。详细分析可参看这里。
重新初始化钱包所有者
重新初始化钱包所有者
我不会把这个漏洞归为“黑客攻击”范畴,其实是dApp自身存在的问题。以太坊Parity钱包此前就曾因某个之前我们讨论过的modifier错误执行而被黑客利用,造成了大规模的损失,在这个Parity钱包的漏洞场景中,任何可可以调用initWallet 函数,用自己的地址把自己设置成钱包所有者。
正常情况下,合约的构造函数体中应该包含钱包或合约所有者,这个构造函数会被调用一次,如果之后想修改地址,就需要在某个函数中进行操作,该函数需要之前所有者的签名。在这个Parity钱包的漏洞中,由于不存在这类校验型modifier,因此攻击者可以随时调用initWallet。可参考这里查看该Parity钱包漏洞分析。
智能合约审计工具
这方面网上已经有一些非常好的开源工具,如Trail of Bits的Manticore和ConsenSys的Mythril,在后续的文章中我会来详细介绍这两款审计工具。
总结
希望我的这篇文章,能让大家对dApp的攻击面有个初浅的理解,能认识到dApp与标准Web应用之间的差异之处。想了解以太坊或者区块链安全方面的更多内容,敬请关注我的博客,后续我会有发表更多相关文章。
*参考来源:avanaghi