默认情况下,Node.js 是否防止目录/路径遍历?

6

Expressjs的"express.static()"默认情况下可以防止目录/路径遍历,但我认为Nodejs默认情况下没有保护措施来防止目录/路径遍历?最近试图学习一些Web开发安全(目录/路径遍历),我创建了这个:

const http = require("http");
const fs = require("fs");

http
  .createServer(function (req, res) {
    if (req.url === "/") {
      fs.readFile("./public/index.html", "UTF-8", function (err, data) {
        if (err) throw err;
        res.writeHead(200, { "Content-Type": "text/html" });
        res.end(data);
      });
    } else {
      if (req.url === "/favicon.ico") {
        res.writeHead(200, { "Content-Type": "image/ico" });
        res.end("404 file not found");
      } else {  
        fs.readFile(req.url, "utf8", function (err, data) {
          if (err) throw err;
          res.writeHead(200, { "Content-Type": "text/plain" });
          res.end(data);
        });
      }
    }
  })
  .listen(3000);

console.log("The server is running on port 3000");

模拟目录/路径遍历安全漏洞,但我尝试使用“../../../secret.txt”,当我检查“req.url”时,它显示“/secret.txt”而不是“../../../secret.txt”。我还尝试使用“%2e”和“%2f”,但仍然无法正常工作,我仍然无法获取“secret.txt”。


(我的文件夹结构)

- node_modules
- public
  - css
    - style.css
  - images
    - dog.jpeg
  - js
    - script.js
  index.html
- package.json
- README.md
- server.js
- secret.txt
1个回答

3
根据 express.static [1] 的文档,该函数会引导到 serve-static 模块的文档 [2]。你提供的目录是 根目录,这意味着故意禁止访问其外部的任何内容。

使用 Express 内置的 express.static 中间件函数来提供静态文件,如图像、CSS 文件和 JavaScript 文件。

函数签名为:

express.static(root, [options])

root 参数指定要提供静态资源的根目录。有关 options 参数的更多信息,请参阅 express.static [3]。

[1] https://expressjs.com/zh-cn/starter/static-files.html

[2] https://expressjs.com/zh-cn/resources/middleware/serve-static.html#API

[3] https://expressjs.com/zh-cn/4x/api.html#express.static


无关紧要,但是需要知道:你提供给 fs 等的路径是相对于脚本调用位置而言的。

例如,如果从应用程序的根文件夹调用 node server.js,路径 "./public/index.html" 可以正常工作,但如果从其他路径调用它,例如 node /home/user/projects/this-project/server.js,则会失败。

因此,你应该始终使用 __dirname 来连接路径,例如:

+const path = require("path");

-fs.readFile("./public/index.html", "UTF-8", function (err, data) {
+fs.readFile(path.join(__dirname, "./public/index.html"), "UTF-8", function (err, data) {
}

这将使路径相对于当前文件所在的目录,符合您的期望。

1
是的,如果我使用“express.static”和ExpressJS,我只能访问public文件夹中的文件,因为“express.static”会防止目录/路径遍历,所以我无法访问public文件夹之外的任何内容,但是如果没有任何框架,仅使用NodeJS呢?通过我的问题,我试图创建一个具有目录/路径遍历安全漏洞(用于学习目的),但我似乎无法创建一个... - JustANewCoder
1
你现在使用的请求方式是错误的。我猜你正在使用 curl -L localhost:3000/../../secret.txt 来测试你的服务器。问题在于 req.url 被解析成了 "/secret.txt" -- 使用 req.query 参数 (curl -L localhost:3000?path=../../secret) 或者 req.body (你需要中间件来解析它们)。然后,一旦你收到路径,这个 "漏洞" 就会成功 -- 你可能不需要再使用服务器,直接将路径硬编码到 fs.readFile 中即可。 - Kipras Melnikovas
明白了 :),还有一个问题,如果我想要防止目录/路径遍历安全漏洞问题,最好的方法是什么...我认为 path.join 可以去除 "../",但这是否足够...我需要做其他事情吗?如果是你,你会如何编写代码来防止这种安全问题?(没有框架,只使用 Node.js) :) - JustANewCoder
1
总的来说,如果你不是安全/密码学专家,建议不要自己实现它,除非仅用于教育目的。请注意;遗憾的是我不知道你问题的答案——你需要自己研究相关资料。 - Kipras Melnikovas
1
明白了,没问题,你已经帮我解决了很多之前的问题,谢谢 :) - JustANewCoder
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接