在 Javascript 中安全地执行动态脚本

动态脚本,在每种编程语言都有涉及,比如微软的 Office 里面的 VBA 脚本,比如浏览器插件的 Tampermonky,比如很多在线工具类网站的脚本在线执行,甚至在国外很火的 SaaS 以及其衍生平台中的开发者功能都是可以通过动态脚本来实现的。

而动态脚本也大体分为两种,一是在用户客户端里执行的代码,比如 Tampermonkey ,它可以让用户使用各种自定义的代码来完成特定的功能,而这些动态脚本都有一个局部性就是只在指定客户端生效。

而第二种就是运行在服务端的动态脚本。由于客户端的脚本功能有限,很多强大的功能,比如操作文件,访问数据库都是没法访问的,为了解决这种问题,很多 SaaS 或其它平台为用户提供了自定义开发的功能,而实现自定义开发,最快捷的就是运行用户自己的动态脚本,让用户可以操作文件,甚至部署一个服务端的服务。

但是,动态脚本虽然好,如果执行了一些恶意脚本,无论是对客户端还是服务端来说都是一场噩梦,轻则数据泄露,重则整个应用服务都会被影响导致崩溃。

那么,在 Javascript 中,怎样才能去动态并且安全地执行脚本呢?

evalnew Function

这二者在 Javascript 中是无论客户端还是服务端都可以使用的函数,可以用他们去动态解析并执行动态脚本,但是由于用他们执行的代码拥有着和应用中其它正常代码一样的的权限,能访问「执行上下文」中的局部变量,也能访问所有「全局变量」,在服务端的环境下,使用它们其实是非常危险的。

eval 为例,在服务器环境下执行以下代码

eval('process.exit()')

对于服务器环境而言,process 是一个全局变量,上诉代码会让整个应用直接退出,简单点说,一旦运行了以上脚本,我们的 NodeJS 服务就挂了。

当然,如果将 evalES6 中的 Proxy 结合使用,可以限制一些上下文或者全局变量的访问,比如以下代码

function evalute(code,sandbox) {
   
  sandbox = sandbox || Object.create(null);
  const fn = new Function('sandbox', `with(sandbox){return (${
     code})}`);
  const proxy = new Proxy(sandbox, {
   
    has(target, key) {
   
      // 让动态执行的代码认为属性已存在
      return true; 
    }
  });
  return fn(proxy);
}
evalute('1+2') // 3
evalute('console.log(1)') // Cannot read property 'log' of undefined

这段代码会通过 Proxy 去阻止脚本获取上下文的变量,从而让动态脚本变得更安全了一些,不过由于使用到了 with 关键字,其性能也相对较差。

NodeJS 中的其它选择?

如果只讨论服务端也就是 NodeJS,其自带的模块中有一个名为 VM 的模块,VM 模块提供了一系列 API 用于在 V8 虚拟机环境中编译和运行代码。Javascript 代码可以被编译并立即运行,或编译、保存然后再运行。以下是官方提供的例子:

const vm = require('vm');

const x = 1;

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值