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

新手入门级 | nodejs调试

nodejs调试记录

问题 & 环境搭建

环境搭建

1,安装nodejs,这个直接网上找教程就行

2,安装vscode

3,我是直接在nodejs安装路径下,创建了一个app文件,然后在里面写js代码的。

图片

然后接下来,就是写代码,进行调试,以下代码是让node监听33456端口,然后,获取file参数,返回指定文件内容的一个功能。

 

const express = require("express");const fs = require("fs");
const app = express();
const PORT = process.env.PORT || 33456;

app.get("/", (req, res) => { try { res.setHeader("Content-Type", "text/html"); console.log(req.query.file); res.send(fs.readFileSync(req.query.file || "index.html").toString()); } catch(err) { console.log(err); res.status(500).send("Internal server error"); }});
app.listen(PORT, () => console.log(`web/simplewaf listening on port ${PORT}`));

 

问题

我在vscode中点击运行和调试后,报错:windows Cannot find module 'express',提示说找不到express这个模块

问题解决:https://juejin.cn/post/7159201118457692174

在写代码的目录下打开cmd,然后运行一下npm install express进行模块安装即可。

图片

调试过程

现在当前目录创建一个launch.json配置文件,一般在vscode左上角有创建提示,点击即可创建,然后将node_internals那一行注释掉,在将js文件改成实际的js文件名。

图片

 

//launch.json:
{ // 使用 IntelliSense 了解相关属性。 // 悬停以查看现有属性的描述。 // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { "type": "node", "request": "launch", "name": "启动程序", "skipFiles": [ // "<node_internals>/**" ], "program": "${workspaceFolder}\\main.js" } ]}

对于下面这句话不是很理解,因此尝试自己手动调试看结果会更理解一些。

 

express 使用 qs npm 模块来提供 req.query.file (file 为查询字符串参数名) ,这意味着它可以与字符串以外的其他类型一起使用。
如:?file[]=1&file[]=2 或者 ?file=1&file=2 ,这样最后 req.query.file 获取到的就是一个数组 ['1', '2'] ; 还有 ?file[a]=b&file[c]=d , req.query.file 获取到的是一个对象 {'a': 'b', 'c': 'd'}

首先,我们得先理解:req.query.file的作用是,req.query是获取URL中传递的参数,req.query.file就是获取URL中传递的file参数,同时呢,它除了字符串类型的传参file=abcd,还可以传参数组file=1&file=2以及对象file[a]=b

代码就是上面的代码,我们直接访问本地的33456传参查看结果:

可以看到,当我们进行重复传参file=b&file=areq.query.file

图片

图片

当我们传参数组,那么得到的就是一个对象,file[a]=b&file[c]=d,其中含有a属性,值为b,c属性,值为d

图片

图片

readFileSync调试

有以上前置知识,接下来我们进入readFileSync调试,来看看如何拿到/app/flag.txt中的flag.

在以上传参过程中,我们在vscode中,可以很明显的看到readFileSync的报错:The "path" argument must be of type string or an instance of Buffer or URL. Received an instance of Object,这个报错提示我们,readFileSync方法接收的路径必须是 字符串 、Buffer实例化对象以及URL实例化对象

图片

而我们的传参file=b&file=a 以及file[a]=b&file[c]=d,一个是数组,一个是普通对象,显然readFileSync方法是不接受的。

接下来我们另写一段代码,并且在当前目录创建一个flag.txt,进行验证:

 

const fs = require('fs');// 注意:路径需要绝对路径let file1 = new URL("file:///G:/Software/nodejs/app/fl%61g.txt"); // URL类是内置的类,可以直接new URL对象let file2 = Buffer.from("G:/Software/nodejs/app/flag.txt"); // Bufferlet file3 = "G:/Software/nodejs/app/flag.txt"; // 字符串
console.log(fs.readFileSync(file1).toString());
console.log(fs.readFileSync(file2).toString());
console.log(fs.readFileSync(file3).toString());

正常读取flag,那么我们在做simplewaf这一题时,首先就是要想办法传入一个能够读取到flag的URL类,或者字符串,至于Buffer貌似是没法构造的【毕竟我不是这方面的master】,并且在路径中存在URL编码也同样可以正常读取文件。

图片

接下来,我们来进行下断点调试,看看当readFileSync方法接收到参数之后,在其内部是如何进行处理的,看看是否能通过其工作原理,来达到我们绕过的目的。

我们将其他无关紧要的代码全部注释掉,只留下核心代码进行DEBUG。

 

const fs = require('fs');let file1 = new URL("file:///G:/Software/nodejs/app/fl%61g.txt"); console.log(fs.readFileSync(file1).toString());

在第三行下断点,代码运行后,我们跟进,进入到readFileSync方法内部:

第一行代码,根据英文释义,这应该是设置对文件如何进行操作的标志位,默认应该是r读取操作。这一行可以直接步过

第二行是类似于文件描述符样的东西,这一行也可以直接步过

第三行,是一个三目运算符,由于前面一行代码运行完之后,isUserFd为false,所以会进入到表达式fs.openSync当中。

图片

此时path会传入到openSync方法当中进行一些处理,可以看到openSync的代码,我们在步过方法当中的第一行代码之后,传入的path从"file:///G:/Software/nodejs/app/fl%61g.txt"变成了"file:///G:/Software/nodejs/app/flag.txt",这说明在方法getValidatedPath中对我们传入的path进行了解码操作。

图片

我们可以进入到getValidatedPath内部,看看它对我们传的URL对象是如何处理的:可以看到,第一行代码就调用了toPathIfFileURL,那么进入这个方法看看

图片

进来之后,可以看到由调用了isURLInstance方法,继续跟进,看看该方法如何处理

图片

跟进之后可以看到,首先判断是否为空,然后判断是否有href属性以及 origin属性,最终的结果返回一个布尔值,我们可以判断一下,因为我们传入的是一个URL对象,因此 不等于null,并且是具有href和origin属性的,因此三个都为true(这个地方如果有不懂的,可以停止程序,出去将这三者都输出一下就知道结果了),最终返回结果true。

图片

代码继续往下运行:因为isURLInstance方法得出结果为true,所以!true即为false,代码运行到1515行,此时又调用了一个fileURLToPath方法对URL对象path进行处理,进入该函数看看:

图片

第一个if判断,判断是不是string类型,显然不是,是一个URL对象

第二判断,判断是不是URL对象,是

第三个判断,判断protocol是不是file:,是file:,来到return这一行,不是的话就抛出异常;

图片

来到return 三目运算,isWindows是判断当前是linux系统还是windows系统,因为我这里调试使用的是windows系统,所以isWindows是有值的,所以会进入到 getPathFromURLWin32 方法

图片

进入该方法看看:大致阅读代码,会从传入的url中检测是否包含%,并且不能包含有编码后的\\/,否则会抛出异常,然后会对字符串进行替换,将/全部替换成\\,然后使用decodeURIComponent方法进行URL解码。

图片

解码之后还会检测是否为绝对路径,如果不是绝对路径会抛出异常,返回URL解码后的路径。

再往下看,判断hostname属性是否为空,不为空则会返回一个UNC路径,为空往下继续(在对应的linux方法中只判断hostname是否为空,如果为空则继续,不为空则抛出异常,毕竟linux下默认是没有SMB服务的):

图片

接下来获取盘符,判断盘符是否合法a-Z,接着获取冒号,判断路径是否为绝对路径(这个判断在windows对应的方法下有,linux下没有,毕竟linux下没有盘符的说法):

图片

最终,将路径前面多余的\\去掉并返回:

图片

出来之后便进入到validatePath函数,

图片

validatePath函数主要是对路径是否为字符串以及是否为空的检测,如果未通过则抛出异常,显然是通过的,直接步过这个函数。

图片

之后就是对flag.txt的读取操作了。

因此,这里我们可以画个草图方便理解:

图片

因此,我们要获取flag需要满足以下条件:

1,传参要为URL对象(避免引发readFileSync报错)

2,存在href属性

3,存在origin属性(只要具有href、origin属性且不为null,isURLInstance方法就返回true)

4,protocol的属性值必须为file:

5,hostname`属性值必须为空

6,进行双重url编码(因为express模块会进行一次编码),绕过对flag关键字的检测(并且在getPathFromURLWin32或getPathFromURLPosix方法中会进行一次URL解码,因此可以进行URL编码绕过)

7,pathname设置为要读取的文件路径,注意包含flag字符就需要进行url编码绕过

 

linux:
?file[href]=1&file[origin]=2&file[protocol]=file:&file[hostname]=&file[pathname]=/etc/passwd
?file[href]=1&file[origin]=2&file[protocol]=file:&file[hostname]=&file[pathname]=/app/fl%2561g.txt
windows:
?file[href]=1&file[origin]=2&file[protocol]=file:&file[hostname]=&file[pathname]=/G:/Software/nodejs/app/fl%2561g.txt

图片

图片

最后解释一下为什么windows下,路径长这样/G:/Software/nodejs/app/fl%2561g.txt,前面多了一个斜杠

因为在getPathFromURLWin32方法中,letter会获取盘符,取的是字符串中的下标为1的字符,因此需要多加一个斜杠,并且seq取冒号,取得是字符串中的下标为2的字符。在使用file协议的时候,通常也会是用file:///路径的形式。

图片

图片

参考资料

https://cloud.tencent.com/developer/article/2123023

https://brycec.me/posts/corctf_2022_challenges#simplewaf

感谢大佬的分享,【膜膜膜】

   申明:本账号所分享内容仅用于网络安全技术讨论,切勿用于违法途径,所有渗透都需获取授权,违者后果自行承担,与本号及作者无关,请谨记守法。

免费领取安全学习资料包!

渗透工具

技术文档、书籍

 

面试题

帮助你在面试中脱颖而出

视频

基础到进阶

环境搭建、HTML,PHP,MySQL基础学习,信息收集,SQL注入,XSS,CSRF,暴力破解等等

 

应急响应笔记

学习路线

http://www.xdnf.cn/news/837019.html

相关文章:

  • My_blog个人博客系统
  • 谁动了你的HTTPS流量?
  • “古董级” 诺基亚功能机跑Linux是怎样的画风?
  • 还在用命令行看日志?快用Kibana吧,可视化日志分析YYDS!
  • spread spectrum 展频的工作原理
  • 云渲染如何使用?其实很简单,只需3步就搞定了!
  • Thinkpad(T420 + WIN7)驱动与软件的安装
  • eboot.php如何转成iso,如何转换成iso格式
  • C# Winform应用系统如何快速开发?看完这篇文章就懂了
  • 微信小程序开发(超详细保姆式教程)
  • 域名邮箱申请指南:从概念到实践的一站式解答
  • 小白学Linux之内核模块编程
  • 关于ASO优化刷榜、冲榜、维榜、锁榜科普百科
  • 快速入门:低代码开发APP软件的步骤详解
  • 浅入深出LC谐振电路
  • PHP 零基础初学者手册(二)
  • 西门子TP900精智系列触摸屏与菱Q系列PLC以太网通信的嵌入式组态步骤
  • 家庭财务管理系统APP(开题报告+源码)
  • 自学python真的可以学会吗?这位朋友的真实经历告诉你_python自学成功几率多大(1)
  • 易基因|m6A RNA甲基化研究的数据挖掘思路:干货系列
  • 阿里研究员:软件测试中的18个难题
  • SEO辅助工具大全,让网站优化事半功
  • 十款开源测试开发工具分享(自动化、性能、造数据、流量复制)
  • 苹果公司开发者账号申请流程
  • 移动端基础
  • Python TensorFlow框架 实现手写数字识别系统
  • 第三章 Ext框架基础及核心简介
  • win7 64位系统不支持curl解决办法
  • 莱佛士学生在Joo Chiat T恤设计比赛中获得最高奖项
  • ASP.NET虚拟主机安全漏洞解决方案 【 这篇文章不错 】