当前位置: 首页 > news >正文

Nodejs沙箱逃逸--总结

一、沙箱逃逸概念

  • JavaScript和Nodejs之间有什么区别:JavaScript用在浏览器前端,后来将Chrome中的v8引擎单独拿出来为JavaScript单独开发了一个运行环境,因此JavaScript也可以作为一门后端语言,写在后端(服务端)的JavaScript就叫叫做Nodejs。
  • 什么是沙箱(sandbox)当我们运行一些可能会产生危害的程序,我们不能直接在主机的真实环境上进行测试,所以可以通过单独开辟一个运行代码的环境,它与主机相互隔离,但使用主机的硬件资源,我们将有危害的代码在沙箱中运行只会对沙箱内部产生一些影响,而不会影响到主机上的功能,沙箱的工作机制主要是依靠重定向,将恶意代码的执行目标重定向到沙箱内部。
  • 沙箱(sandbox)和 虚拟机(VM)和 容器(Docker)之间的区别:sandbox和VM使用的都是虚拟化技术,但二者间使用的目的不一样。沙箱用来隔离有害程序,而虚拟机则实现了我们在一台电脑上使用多个操作系统的功能。Docker属于sandbox的一种,通过创造一个有边界的运行环境将程序放在里面,使程序被边界困住,从而使程序与程序,程序与主机之间相互隔离开。在实际防护时,使用Docker和sandbox嵌套的方式更多一点,安全性也更高。
  • 在Nodejs中,我们可以通过引入vm模块来创建一个“沙箱”,但其实这个vm模块的隔离功能并不完善,还有很多缺陷,因此Node后续升级了vm,也就是现在的vm2沙箱,vm2引用了vm模块的功能,并在其基础上做了一些优化。

二、Node将字符串执行为代码

方法一 eval

首先我在目录下创建一个age.txt

var age = 18

创建一个y1.js

const fs = require('fs')let content = fs.readFileSync('age.txt', 'utf-8')console.log(content)eval(content)console.log(age)

这里因为我没有配置Node.js,所以我将代码改为.txt在浏览器中为大家调试(结果一样)

fetch('age.txt').then(response => response.text()).then(content => {console.log(content);eval(content);console.log(age);}).catch(error => console.error('An error occurred:', error));

 结果:

 可以发现我们通过eval执行了一个字符串,但是这种执行方式如果在当前作用域下已经有了同名的age变量,这个程序就会报错。

 相同变量程序报错:

 在js中每一个模块都有自己独立的作用域,所以用eval执行字符串代码很容易出现上面的这个问题,我们再看另外一种方法。

方法二:new Function

上面的方法因为模块间的作用域被限制了使用,那么我们考虑一下如果能够自己创建一个作用域是不是就可以更加方便的执行代码呢?new Function的第一个参数是形参名称,第二个参数是函数体。

我们都知道函数内和函数外是两个作用域,不过当在函数中的作用域想要使用函数外的变量时,要通过形参来传递,当参数过多时这种方法就变的麻烦起来了。

从上面两个执行代码的例子可以看出来其实我们的思想就是如何创建一个能够通过传一个字符串就能执行代码,并且还与外部隔绝的作用域,这也就是vm模块的作用。

三、Nodejs作用域

说到作用域,我们就要说一下Node中的作用域是怎么分配的(在Node中一般把作用域叫上下文)。

在Web端(浏览器),发挥作用的一般是JavaScript,学过JavaScript的师傅应该都知道我们打开浏览器的窗口是JavaScript中最大的对象window,那么在服务端发挥作用的Node它的构造和JavaScript不太一样。

我们在写一个Node项目时往往要在一个文件里ruquire其他的js文件,这些文件我们都给它们叫做“包”。每一个包都有一个自己的上下文,包之间的作用域是互相隔离不互通的,也就是说就算我在y1.js中require了y2.js,那么我在y1.js中也无法直接调用y2.js中的变量和函数,举个例子。

在同一级目录下有y1.jsy2.js两个文件

y1.js:

var age = 20

y2.js:

const a = require("./y1")console.log(a.age)
运行y2.js发现报错:

那么我们想y2中引入并使用y1中的元素应该怎么办呢,Node给我们提供了一个将js文件中元素输出的接口exports ,把y1修改成下面这样:

y1.js:

var age = 20exports.age = age

我们再运行y2就可以拿到age的值了

图解:

 这个时候就有人会问左上角的global是什么?这里就要说到Nodejs中的全局对象了。

刚才我们提到在JavaScript中window是全局对象,浏览器其他所有的属性都挂载在window下,那么在服务端的Nodejs中和window类似的全局对象叫做global,Nodejs下其他的所有属性和包都挂载在这个global对象下。在global下挂载了一些全局变量,我们在访问这些全局变量时不需要用global.xxx的方式来访问,直接用xxx就可以调用这个变量。举个例子,console就是挂载在global下的一个全局变量,我们在用console.log输出时并不需要写成global.console.log,其他常见全局变量还有process(一会逃逸要用到)。

我们也可以手动声明一个全局变量,但全局变量在每个包中都是共享的,所以尽量不要声明全局变量,不然容易导致变量污染。用上面的代码举个例子:

http://www.lryc.cn/news/132337.html

相关文章:

  • No115.精选前端面试题,享受每天的挑战和学习
  • Elasticsearch:语义搜索 - Semantic Search in python
  • Flink学习笔记(一)
  • [Raspberry Pi]如何用VNC遠端控制樹莓派(Ubuntu desktop 23.04)?
  • 17.HPA和rancher
  • VS2022远程Linux使用cmake开发c++工程配置方法
  • 《强化学习:原理与Python实战》——可曾听闻RLHF
  • STM32——RTC实时时钟
  • webSocket 开发
  • c#设计模式-结构型模式 之 代理模式
  • openpnp - 自动换刀的设置
  • 《HeadFirst设计模式(第二版)》第十章代码——状态模式
  • day-25 代码随想录算法训练营(19)回溯part02
  • PG逻辑备份与恢复
  • 图数据库_Neo4j和SpringBoot整合使用_实战创建明星关系图谱---Neo4j图数据库工作笔记0010
  • Linux网络编程:Socket套接字编程(Server服务器 Client客户端)
  • Mac OS下应用Python+Selenium实现web自动化测试
  • 每天一道leetcode:934. 最短的桥(图论中等广度优先遍历)
  • 【学习日记】【FreeRTOS】FreeRTOS 移植到 STM32F103C8
  • Qt 屏幕偶发性失灵
  • 如何在pycharm中指定GPU
  • C#判断字符串中有没有字母,正则表达式、IsLetter
  • Jtti:Ubuntu怎么限制指定端口和IP访问
  • 机器学习/深度学习需要掌握的linux基础命令
  • C++11 std::async推荐使用 std::launch::async 模式
  • 没有使用springboot 单独使用spring-boot-starter-logging
  • 创建Azure资源锁
  • 卷积神经网络教程 (CNN) – 使用 TensorFlow 在 Python 中开发图像分类器
  • MyBatis XML映射处理CLOB和BLOB类型
  • FPGA_学习_14_第一个自写模块的感悟和ila在线调试教程与技巧(寻找APD的击穿偏压)