4.7 KiB
Raw Blame History

知识点: 变量污染,环境隔离,jsdom补dom环境

举例:

function 变量污染(参数) {
    if (!global.key) {
        global.key = 5000
    }
    global.key += Number(参数) + 50
}

app.get('/%E5%8F%98%E9%87%8F%E6%B1%A1%E6%9F%93', (req, res) => {
    变量污染(req.query.a)
    res.send(global.key.toString());
})

执行get请求

http://localhost:3000/变量污染?a=100

每次请求会叠加上一次请求内容,导致返回错误数据

显然这不是我们期望的结果,我们并不希望全局变量被污染,更希望的是不去改变全局的变量

那么我们有以下几种方案

一.对污染的全局变量进行一键缓存清理

function 缓存清理() {
    _env = ['global', 'clearInterval', 'clearTimeout', 'setInterval', 'setTimeout', 'queueMicrotask', 'performance', 'clearImmediate', 'setImmediate',]
    for (i in global) {
        if (_env.indexOf(i) === -1) {
            delete global[i]
        }
    }
}

app.get('/%E5%8F%98%E9%87%8F%E6%B1%A1%E6%9F%932', (req, res) => {
    变量污染(req.query.a)
    res.send(global.key.toString());
    缓存清理()
})

但是这种情况在并发角度有很大的弊端大家可以思考一下如果在一个大并发的业务逻辑下global.key 在没有计算完成的时候, 或者说没有赋值的时候,进行了下一次计算那么很有可能产生的结果就会混乱。导致我们传入的值跟我们输出的值发生不期待的错误。 那么这个时候,缓存清理这种简单的方法就不行了

二.所以就需要用更复杂的方案--->沙箱

什么是沙箱:

沙箱英文是sandbox敲程序的应该都听过或许用过类似理念的只是自己不知道简单说就是让你的程序运行在一个隔离的环境下不对外界的其他程序造成影响。沙箱主要是一种安全机制把一些不信任的代码运行在沙箱之内不能访问沙箱之外的代码。比如在线编辑器、执行第三方js、vue服务端渲染等只要是运行不信任的程序沙箱隔离就会使用到。

简言之沙箱就是一个独立的js环境在这个环境里所有的变量都是独立的没有办法访问到外界的内容常见的eval和new Function可以提供一个运行外部代码的环境但是没有解决访问全局的问题

沙箱是绝对安全的么?

并不是,沙箱在理论上是绝对安全的,但是由于实现的各种情况不同,代码的逻辑问题等,几乎不可避免的会存在逃逸漏洞,也就是说沙箱内的代码可能会影响 到外部的内容,甚至于实现权限的跨越。有些安全开发会利用一些安全逃逸的漏洞和特性针对性的制造防御代码。但是一般情况下,我们不必理会,因为这种 对抗已经很难靠规范的逻辑和方法论去处理了。

沙箱逃逸的一些相关知识:https://xz.aliyun.com/t/11859

安装:

npm install vm2

案例:

const {VM} = require('vm2');

function 沙箱运算(参数){
    const vm = new VM();
    result = vm.run(
        `
        if (!global.key) {
                global.key = 5000
            }
            global.key += Number(参数) + 50
        global.key
        `.replace('参数', 参数))
    return result
}
app.get('/%E5%8F%98%E9%87%8F%E6%B1%A1%E6%9F%933', (req, res) => {
    res.send(沙箱运算(req.query.a).toString());
})

三.jsdom处理dom节点

那么nodejs除了自己处理dom节点是否有些办法能够用库去处理dom节点让我们舒服一点呢答案是有的这个库就是神奇的jsdom

安装:

npm install jsdom

案例:

const jsdom = require("jsdom");
const { JSDOM } = jsdom;
const dom = new JSDOM(`<!DOCTYPE html><p>Hello world</p>`);
console.log(dom.window.document.querySelector("p").textContent); // "Hello world"
debugger;

dom.window.top === dom.window;
dom.window.location.href === "about:blank";

dom.reconfigure({ windowTop: myFakeTopForTesting, url: "https://example.com/" });

dom.window.top === myFakeTopForTesting;
dom.window.location.href === "https://example.com/";

jsdom 缺陷

  1. 内存占用极高,相当于开了一个无头浏览器一样
  2. 特征点非常多被检测概率非常大只要专门去检测这个东西基本十拿九稳100%拦截
  3. 对某些特殊的API接口支持不好

jsdom 优势

  1. 一键补环境,非常方便舒适快捷
  2. 可以只利用里面的一部分东西,降低被检测风险
  3. 可以配合canvas库实现 canvas的大部分功能。

详情看文档以及更新日志

https://github.com/jsdom/jsdom/blob/master/Changelog.md