2023柏鹭杯wp

发布时间 2023-10-17 15:41:03作者: 淡雅的墨竹

柏鹭杯中关于NodeJS题的源代码详细分析

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

const app = express();

const PORT = process.env.PORT || 3456;

app.use((req, res, next) => {
    if([req.body, req.headers, req.query].some(
        (item) => item && JSON.stringify(item).includes("flag")//ban 掉了 flag
    )) {
        return res.send("bad hacker!");
    }
    next();
});

app.get("/", (req, res) => {
    try {
        res.setHeader("Content-Type", "text/html");
        res.send(fs.readFileSync(req.query.file || "index.html").toString());       
    }
    catch(err) {
        console.log(err);
    }
});

app.listen(PORT, () => console.log(`web/simplewaf listening on ${PORT}`));

首先来分析引用的模块的作用(类比python的import)

1.express

Express 是一个流行的 Node.js Web 应用程序框架,它简化了使用 Node.js 构建 Web 应用程序的过程。
路由和中间件:Express 提供了路由和中间件机制,使得请求的处理和路由非常灵活。您可以定义各种 HTTP 请求方法(GET、POST、PUT、DELETE 等)和对应的路由处理器,以及中间件函数来处理请求前、请求后的逻辑。这使得构建复杂的路由和处理请求的流程变得简单和可维护。
请求和响应处理:Express 提供了简化请求和响应处理的功能。您可以轻松地访问请求的参数、头部、正文等,并且可以设置响应的状态码、头部、正文等。

2.fs

fs 模块是 Node.js 核心模块之一,用于处理文件系统操作。它提供了一组丰富的方法,可以对文件进行读取、写入、删除、重命名等各种操作。

  1. 读取文件:使用 fs.readFile() 方法可以异步地读取文件的内容,并将内容作为回调函数的参数返回。如果需要同步读取文件,可以使用 fs.readFileSync() 方法。
  2. 写入文件:使用 fs.writeFile() 方法可以异步地将数据写入文件。如果需要同步写入文件,可以使用 fs.writeFileSync() 方法。
  3. 追加文件:使用 fs.appendFile() 方法可以异步地将数据追加到文件的末尾。如果需要同步追加文件,可以使用 fs.appendFileSync() 方法。
  4. 删除文件:使用 fs.unlink() 方法可以异步地删除文件。如果需要同步删除文件,可以使用 fs.unlinkSync() 方法。
  5. 重命名文件:使用 fs.rename() 方法可以异步地重命名文件或将文件移动到另一个目录。如果需要同步重命名文件,可以使用 fs.renameSync() 方法。
  6. 检查文件状态:使用 fs.stat() 方法可以异步地获取文件的状态信息,如文件大小、创建时间等。如果需要同步获取文件状态,可以使用 fs.statSync() 方法。
  7. 创建目录:使用 fs.mkdir() 方法可以异步地创建目录。如果需要同步创建目录,可以使用 fs.mkdirSync() 方法。
  8. 读取目录:使用 fs.readdir() 方法可以异步地读取目录,并返回目录中的文件和子目录列表。如果需要同步读取目录,可以使用 fs.readdirSync() 方法。
  9. 监听文件变化:使用 fs.watch() 方法可以异步地监听文件的变化,如文件的修改、删除等操作。

3.const app=express();的作用

分析 const app = express();
通过调用 express() 创建一个 Express 应用程序实例。将创建的 Express 应用程序实例赋值给一个变量,这里使用 app 作为变量名。这样,后续的代码就可以通过 app 来访问和操作 Express 应用程序。

4.分析第一个函数app.use()

首先介绍一下中间件函数。简单提一嘴,中间件函数是 Express 框架中用于处理 HTTP 请求的函数.app.use()就是一个。
req、res 和 next 参数在 Express 中间件函数中是自动提供的,无需显式定义
req:代表请求对象,包含了请求的信息,如请求头、请求体、URL 参数等。
res:代表响应对象,用于发送响应给客户端,如设置响应头、发送响应体等。
next:是一个回调函数,用于将控制权传递给下一个中间件函数或路由处理器。通过调用 next(),Express 将执行后续的中间件或路由处理器。再去了解下NodeJS的回调函数吧。还是很有特色的、
然后把这三个参数放在了数组,调用了数组方法,继续介绍
some() 是 JavaScript 数组的方法,用于检查数组中是否至少有一个元素满足指定的条件。他是会遍历数组的。在这里,some() 方法用于检查 req.body、req.headers 和 req.query 数组中是否有任何一个元素包含了 "flag" 字符串。
箭头函数 (item) => item 的作用是将传入的参数原封不动地返回。 :
JSON.stringify() 是将 JavaScript 对象转换为 JSON 字符串的方法。在这里,它用于将 req.body、req.headers 和 req.query 转换为字符串,以便进行包含 "flag" 的检查。
如果没有包含 "flag",则调用 next(),将控制权传递给下一个中间件或路由处理器。

5. 二个函数

主要是接收GET请求,关键的地方
res.send(fs.readFileSync(req.query.file || "index.html").toString()):这行代码读取文件内容并将其作为响应发送给客户端。fs.readFileSync() 用于同步读取文件,req.query.file || "index.html" 表示从查询参数中获取 file 参数的值,如果没有提供默认为 "index.html"。.toString() 方法将文件内容转换为字符串。

剩下的攻击分析WP

req.query.file 是一个表达式,用于获取 Express 框架中请求对象 req 的查询参数中名为 "file" 的值。
在 Express 中,请求对象 req 的 query 属性是一个对象,它包含了客户端发送的查询参数。通过访问 req.query,您可以获取到一个包含查询参数的对象。
req.query.file 则是通过点 (.) 运算符从 req.query 对象中获取名为 "file" 的属性值。