From b53f6193e8af68ec6576271a7518e6b486c8e252 Mon Sep 17 00:00:00 2001 From: luzhisheng Date: Tue, 28 Mar 2023 06:10:02 +0800 Subject: [PATCH] =?UTF-8?q?js=E5=9F=BA=E7=A1=8020-jsdom=E4=B8=8Eexpress?= =?UTF-8?q?=E4=B8=8Evm2=E5=85=A5=E9=97=A8=5F=E7=8C=BF=E4=BA=BA=E5=AD=A6-?= =?UTF-8?q?=E7=88=AC=E8=99=AB=E9=AB=98=E9=98=B6=E5=9F=B9=E8=AE=AD=E8=AF=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../readme.md | 124 ++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 猿人学逆向学习/js基础20-jsdom与express与vm2入门_猿人学-爬虫高阶培训课/readme.md diff --git a/猿人学逆向学习/js基础20-jsdom与express与vm2入门_猿人学-爬虫高阶培训课/readme.md b/猿人学逆向学习/js基础20-jsdom与express与vm2入门_猿人学-爬虫高阶培训课/readme.md new file mode 100644 index 0000000..8cd0023 --- /dev/null +++ b/猿人学逆向学习/js基础20-jsdom与express与vm2入门_猿人学-爬虫高阶培训课/readme.md @@ -0,0 +1,124 @@ +# 知识点: 变量污染,环境隔离, + +举例: + + 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 + +每次请求会叠加上一次请求内容,导致返回错误数据 + +显然这不是我们期望的结果,我们并不希望全局变量被污染,更希望的是不去改变全局的变量 + +那么我们有以下几种方案 + +### 1.对污染的全局变量进行一键缓存清理 + + 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 在没有计算完成的时候, +或者说没有赋值的时候,进行了下一次计算那么很有可能产生的结果就会混乱。导致我们传入的值跟我们输出的值发生不期待的错误。 +那么这个时候,缓存清理这种简单的方法就不行了 + +### 2.所以就需要用更复杂的方案--->沙箱 + +什么是沙箱: + +沙箱,英文是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()); + }) + +### 那么,nodejs,除了自己处理dom节点,是否有些办法能够用库去处理dom节点,让我们舒服一点呢,答案是,有的,这个库就是神奇的jsdom + +安装: + + npm install jsdom + +案例: + + const jsdom = require("jsdom"); + const { JSDOM } = jsdom; + const dom = new JSDOM(`

Hello world

`); + 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