背景

比特股的创始人Daniel Larimer质疑了lisk系统中的一系列问题,绝大多数都被lisk的创始人之一Max正面回应过了,具体可以看看这个http://ethereum.stackexchange.com/questions/2104/how-does-lisk-differ-from-ethereum

但是有一个问题Max没有回应或者说还没有提出解决方案。
那就是lisk侧链的运行环境,Larimer说

“Lisk所面临的大多数问题,都可以通过一个高度定制的JavaScript 环境来解决。”

否则,lisk的系统面临两大考验:
首先,也是最重要的,lisk目前的沙箱机制不足以限制侧链代码的权限,也就是说无法运行不受信任的代码,那些代码可能会盗取服务器的关键信息,或者直接对服务器进行破坏
其次,是关于侧链开发者的,lisk的侧链代码是运行在一个拥有全部能力的javascript环境,这里面有些可以导致不确定因素的函数,比如Math.random,lisk官方的开发文档特别指出希望开发者避开这些函数,这对开发者会造成心智负担,如果是一个定制版的javascript环境呢,直接把那些导致不确定因素的函数干掉,开发者根本不需要花费额外的精力去避开那些陷阱。

#lisk的沙箱安全问题

我们先说说为什么要用沙箱。沙箱(sandbox)是云计算平台广泛采用的安全防范措施,是一种访问控制机制,其目的是为了限制应用代码的权限,防止应用代码对系统进行随意的访问和破坏,因为在云计算平台中,应用代码是由各种各样的第三方开发者实现的,他们的代码是不能被信任的,需要沙箱来做一层隔离,让这些应用代码只能做有限的事情。

lisk在区块链领域是很类似于云计算平台的,他们提供一些服务,允许第三方开发者基于这些服务构建他们自己的应用程序(即dapps)。
所以lisk也需要沙箱机制来保证dapps的作者无法作恶,lisk的做法是提供一个定制版的nodejs环境来达到这一目的。
具体实现在这段代码里,https://github.com/LiskHQ/lisk-node/blob/v0.12.14-lisk/src/node_sandbox.cc

我经过分析,发现这个sandbox名不副实,只是使用管道手段实现了进程间通讯,而且是使用一种绕弯的方式实现的。nodejs的进程间通讯可以通过javascript代码直接实现,为什么要用c++来实现呢?
我带着这个疑问,和一些期望,亲手做了一个实验。

我首先使用lisk-cli创建一个hello world侧链

lisk-cli dapp -a

接着我在侧链程序的入口处 加了一段代码

console.log(require("fs").readFileSync("../../config.json"))

然后运行之,于是我得到了这个服务器主节点的受托人的所有密码

"forging": {
"secret": [
"wKyoJM1vS4ucHmWvxDSdcpC23mJwqfg3G6MKZoXaFfcnWHTqo7",
"2aTWYPpQidVunxTg3y8YESYps7za6f9d4wYn9Gy2GuGnE7JX7V",
"65uZNjL36Bdg2tkJnueYkd2n6YPe76fpdeYtgu7fso1m385mwD",
…………

果然,这个沙箱并没有起隔离的作用,拥有管理员的权限,这等于给黑客敞开了大门。
有人说,lisk系统设置了二级密码,你获取了他的一级密码,还是没法盗取他们的钱。
也有人说,可以通过linux自身的权限机制,给侧链代码一个低级用户,使之无法访问其他用户的文件。

这些都是治标不治本的办法,根本解决途径是按照lisk预先设想的那样,要让沙箱名副其实,做到真正的环境隔离,要让侧链代码对外界一无所知。

解决方案

那么,如何实现真正的沙箱呢?有很多种方案,比如跳过nodejs,直接使用v8引擎,或者使用进程级别的权限控制,比如windows系统的SetWindowsHookEx,当然,lisk目前并不打算支持windows版本的完整版钱包,那么在linux系统中可以使用seccomp技术。
我这里有种更简单的方法,那就是利用nodejs自带的vm模块。

第一步 创建原生的javascript虚拟机

var vm = require('vm');
var context = vm.createContext();
vm.runInContext(sideChainCode, context);

这几行代码完成了对侧链代码的隔离,sideChainCode中只能进行纯粹的运算逻辑,只能使用少量的v8引擎内置的javascript标准库。甚至连setTimeout,console.log都没有。
我们需要做些额外的工作。

比如,给运行环境添加setTimeout和clearTimeout

context.setTimeout= function(fn, delay) {
if (typeof(fn) == 'string') {
setTimeout(new Function(fn), delay)
} else {
setTimeout(fn, delay)
}
};
context.clearTimeout = clearTimeout;

添加日志打印功能,让侧链的日志,转发到主系统的中

global.print = send.bind(global, 'stdout');
global.console = { log: send.bind(global, 'stdout') };
global.process = {
stdout: { write: send.bind(global, 'stdout') }
};
global.postMessage = send.bind(global, 'message');

另外,还可以禁用那些导致不确定因素的函数

global.Math.random = undefined;

这些都做完以后,侧链代码的访问权限就被限制在一个狭小的范围内了。它们无法使用require,fs,http等nodejs内置的标准库。
这样安全的目的达到了,但是引发另一个问题,那就是功能性的问题了,不能使用那些额外的库,只有js的标准库也太不方便了,很多复杂功能无法实现,特别是没有了require之后,连模块化都做不到了。
所以我们需要第二步。

第二步 webpack

webpack本来是一个前端常用的打包方案,用于模块化的管理前端项目。很多人忽略了其实在后端webpack同样适用,并且可以把node_modules里的库,甚至nodejs的一部分内置库一起打包。
也就是说前端能用的js库,除了UI相关的之外,在侧链沙箱内,也都可以用,比如async,bytebuffer,crypto,js-nacl,bignum等等,这对于侧链来说够用了。
那些不能用的库,比如文件系统、多进程、网络模块,正是我们想要抛弃的。
vm + webpack的组合堪称完美。
这是日新月异的前端技术带给javascript这门语言的福利,也是以太坊的solidity等新语言望尘莫及的。
不过我们还需要一些收尾的工作

第三步 扫清障碍

目前侧链代码中有些地方使用了一些比较复杂的库,比如ed2curve,涉及到非常多的依赖,我们认为是没有必要的,这部分功能可以在主链中提供,通过进程间通讯以api的方式提供给侧链使用。
这样也可以减轻侧链代码的累赘,还可以让侧链开发者更加轻松。这些代码对整个框架的影响非常小,可以忽略不计,但是它们依赖的库却占用了一半以上的代码量,其中还包括了沙箱环境不允许的一些操作。
经过分析,我发现只需要禁用modules/api/crypto.js中的两个函数即可

Crypto.prototype.encrypt
Crypto.prototype.decrypt

另外,js-nacl这个库里依赖了fs模块,但是相关函数并没有被用到,暂时通过手工修改的方式,把fs相关代码去掉就可以正常打包并运行了。

最后,我把一个完整的侧链项目和主链框架中的关键代码打包放在这里了。http://o7dyh3w0x.bkt.clouddn.com/asch-sandbox-solution.tar.gz

Lisk沙箱漏洞分析及解决方案的更多相关文章

  1. SpringBoot Log4j 安全漏洞分析及解决方案

    一.序言 SpringBoot作为Java基础框架大行其道,前不久爆发出Log4j安全漏洞,大众更多关心Log4j的危害是多么严重,然而鲜有关心SpringBoot这一底层框架的安全性问题,换而言之, ...

  2. Zabbix 漏洞分析

    之前看到Zabbix 出现SQL注入漏洞,自己来尝试分析. PS:我没找到3.0.3版本的 Zabbix ,暂用的是zabbix 2.2.0版本,如果有问题,请大牛指点. 0x00 Zabbix简介 ...

  3. Java反序列化漏洞分析

    相关学习资料 http://www.freebuf.com/vuls/90840.html https://security.tencent.com/index.php/blog/msg/97 htt ...

  4. CVE-2014-1767 漏洞分析(2015.1)

    CVE-2014-1767 漏洞分析 1. 简介 该漏洞是由于Windows的afd.sys驱动在对系统内存的管理操作中,存在着悬垂指针的问题.在特定情况下攻击者可以通过该悬垂指针造成内存的doubl ...

  5. FFmpeg任意文件读取漏洞分析

    这次的漏洞实际上与之前曝出的一个 CVE 非常之类似,可以说是旧瓶装新酒,老树开新花. 之前漏洞的一篇分析文章: SSRF 和本地文件泄露(CVE-2016-1897/8)http://static. ...

  6. 从乌云的错误漏洞分析看Mifare Classic安全

    前言 12年2月初国内著名安全问题反馈平台-乌云发布了有关某公司员工卡的金额效验算法破解的安全问题.从整个漏洞分析来看,漏洞的提交者把员工卡的数据分析得非常仔细,以至很多刚刚接触或者未曾接触的都纷纷赞 ...

  7. CVE-2019-0708 漏洞分析及相关测试

    在CVE-2019-0708公布后几天就已经尝试过复现该漏洞,但借助当时exp并没能成功复现反弹shell的过程遂放弃,故借助这次漏洞复现报告再来尝试复现该漏洞,因为还在大三学习中,有很多知识还没有掌 ...

  8. Java安全之Shiro 550反序列化漏洞分析

    Java安全之Shiro 550反序列化漏洞分析 首发自安全客:Java安全之Shiro 550反序列化漏洞分析 0x00 前言 在近些时间基本都能在一些渗透或者是攻防演练中看到Shiro的身影,也是 ...

  9. 从0开始fastjson漏洞分析

    关于fastjson漏洞利用参考:https://www.cnblogs.com/piaomiaohongchen/p/10799466.html fastjson这个漏洞出来了很久,一直没时间分析, ...

随机推荐

  1. PHP Math 函数

    abs() 绝对值. 3 acos() 反余弦. 3 acosh() 反双曲余弦. 4 asin() 反正弦. 3 asinh() 反双曲正弦. 4 atan() 反正切. 3 atan2() 两个参 ...

  2. 优化一个奇葩表设计上的全表扫描SQL

    之前在一个比较繁忙的系统抓到的耗时长.消耗CPU多的一条SQL,如下:SELECT * FROM Z_VISU_DATA_ALARM_LOG TWHERE TO_DATE(T.T_TIMESTR, ' ...

  3. CozyRSS1.0 - 有可用性版本

    bin:还是不提供了,有兴趣的加QQ群373862115讨论 src:https://github.com/zpublic/cozy/tree/a202ae0944936c1ca56c2c3f4b73 ...

  4. CozyRSS开发记录11-够用的RSS源管理

    CozyRSS开发记录11-够用的RSS源管理 1.分析需求 先随手画个用例图来看看有哪些参与者会访问我们的源管理: 2.搞一个Controller类 根据前面分析得出的用例图,我们就可以来设计实现一 ...

  5. 程序员玩转A股

    最近买了点股票....赔了25%......劝各位程序员还是买键盘,买电脑吧.不用理财.... 基本情况 毕业一年多点,手里有点闲钱,闲得慌,10月底开了账户买股票.两只半仓股,赔了15%+,全仓一支 ...

  6. 详细讲述MySQL中的子查询操作 (来自脚本之家)

    继续做以下的前期准备工作: 新建一个测试数据库TestDB: ? 1 create database TestDB; 创建测试表table1和table2: ? 1 2 3 4 5 6 7 8 9 1 ...

  7. ubuntu 安装phpstorm

    1.清除 sudo apt-get purge openjdk* 2.添加源及更新源列表 sudo add-apt-repository ppa:webupd8team/java sudo apt-g ...

  8. bfrd collector性能排查

     1.2.09上昨天timeout在18点23分-22点10分 2.检测2.17网卡流量,sar -f /var/log/sa/sa06 -n DEV,发现这段时间刚好是rxpck/s超过6400. ...

  9. [译]App Framework 2.1 (1)之 Quickstart

    最近有移动App项目,选择了 Hybrid 的框架Cordova  和  App Framework 框架开发. 本来应该从配置循序渐进开始写的,但由于上班时间太忙,这段时间抽不出空来,只能根据心情和 ...

  10. 【ORACLE】 表空间信息

    Linux 查看磁盘空间命令 格式: df -hl 显示格式为: 文件系统 容量 已用 可用 已用% 挂载点 [root@localhost opt]# dfFilesystem     1K-blo ...