点击"打开/下载题目"进去看看情况:
为了方便查看翻译成中文简体来看:
emmm,看不懂什么意思,查看源代码,js表示是一段JavaScript代码,丢给AI分析一下:
// server.js
const express = require("express");
const bodyParser = require("body-parser");
const path = require("path");
const { execSync } = require("child_process");
const app = express();
app.use(bodyParser.json());
app.use(express.static(path.join(__dirname, "public")));
let cmds = {
getsource: "cat server.js",
test: "echo 'hello, world!'",
};
let store = {};
// GET /api/store - Retrieve the current KV store
app.get("/api/store", (req, res) => {
res.json(store);
});
// POST /set - Set a key-value pair in the store
app.post("/set", (req, res) => {
const { key, value } = req.body;
const keys = key.split(".");
let current = store;
for (let i = 0; i < keys.length - 1; i++) {
const key = keys[i];
if (!current[key]) {
current[key] = {};
}
current = current[key];
}
// Set the value at the last key
current[keys[keys.length - 1]] = value;
res.json({ message: "OK" });
});
// GET /get - Get a key-value pair in the store
app.get("/get", (req, res) => {
const key = req.query.key;
const keys = key.split(".");
let current = store;
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
if (current[key] === undefined) {
res.json({ message: "Not exists." });
return;
}
current = current[key];
}
res.json({ message: current });
});
// GET /execute - Run commands which are constant and obviously safe.
app.get("/execute", (req, res) => {
const key = req.query.cmd;
const cmd = cmds[key];
res.setHeader("content-type", "text/plain");
res.send(execSync(cmd).toString());
});
app.get("*", (req, res) => {
res.sendFile(path.join(__dirname, "public", "index.html"));
});
// Start the server
const PORT = 3000;
app.listen(PORT, () => {
console.log(`KV Service is running on port ${PORT}`);
});
这段代码实现了一个简单的键值对存储服务(KV Store)和一个命令执行功能:
- 引入依赖
express: 用于创建Web服务器。
body-parser: 用于解析HTTP请求体中的JSON数据。
path: 用于处理文件路径。
child_process.execSync: 用于同步执行系统命令。
- 初始化应用
创建Express应用实例。
使用bodyParser.json()中间件来解析JSON格式的请求体。
设置静态文件目录为public,这样可以访问放在public目录下的静态文件。
- 定义命令
cmds对象定义了一些安全的命令及其对应的系统命令字符串。例如:
getsource: 获取server.js文件的内容。
test: 输出hello, world!。
- 键值对存储功能
GET /api/store: 返回当前键值对存储的内容。
POST /set: 设置一个键值对。支持嵌套键,例如a.b.c。
解析请求体中的key和value。
使用递归的方式在store对象中创建嵌套结构并设置值。
GET /get: 获取一个键值对。
解析查询参数中的key。
按照.分割键,逐层查找store对象中的值。
如果键不存在,返回Not exists.;否则返回对应的值。
- 命令执行功能
GET /execute: 执行预定义的安全命令。
解析查询参数中的cmd。
从cmds对象中获取对应的命令字符串。
使用execSync同步执行命令,并将结果以纯文本形式返回。
- 路由处理
GET /*: 处理所有其他路由请求,返回public目录下的index.html文件。
- 启动服务器
监听端口3000,并在控制台输出启动信息。
回顾一下关键代码部分:
说明会直接执行预定义的命令"cat server.js"
这下思路有了,只要想办法修改预定义的命令为cat /flag就行了
此处,我先学会儿原型链污染的知识,再回来解释
将key设置为__proto__.nanyuan,value设置为cat /flag
成功解析cat /flag
访问/execute?cmd=nanyuan,页面发生变化,并显示出flag:
成功得到flag