corCTF2022
Web
jsonquiz.be.ax
js看源码找接口,修改传入的参数,默认不管你做题得了多少分都是传入0分,所以可以在最后一个选项的时候用burp抓包,然后修改score的值就能拿到flag
msfrog-generator
尝试目录穿越得到报错回显,试了一下,不让读非图片的文件
可以看到使用反引号包裹的,尝试执行多条命令
拿到flag
simplewaf
这是一道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")
// 将
)) {
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());
// 传入一个参数file,通过fs.readFileSync函数读取文件,并返回渲染
}
catch(err) {
console.log(err);
res.status(500).send("Internal server error");
}
});
app.listen(PORT, () => console.log(`web/simplewaf listening on port ${PORT}`));
允许传入URL对象,URL对象会自动对参数进行url解码,再进行一次浏览器解码,所以可以通过传入url对象进行绕过,但是这里传入的参数是通过req.query.file参数进行解析的,只能允许传入字符串。但是可以通过数组的方式传入对象
分析一下fs.readFileSync函数
function readFileSync(path, options) {
options = getOptions(options, { flag: 'r' });
const isUserFd = isFd(path); // File descriptor ownership
const fd = isUserFd ? path : fs.openSync(path, options.flag, 0o666);
// 创建一个文件句柄,如果不是文件描述符就调用fs.openSync读取文件
const stats = tryStatSync(fd, isUserFd);
const size = isFileType(stats, S_IFREG) ? stats[8] : 0;
let pos = 0;
let buffer; // Single buffer with file data
let buffers; // List for when size is unknown
if (size === 0) {
buffers = [];
} else {
buffer = tryCreateBuffer(size, fd, isUserFd);
}
let bytesRead;
if (size !== 0) {
do {
bytesRead = tryReadSync(fd, isUserFd, buffer, pos, size - pos);
pos += bytesRead;
} while (bytesRead !== 0 && pos < size);
} else {
do {
// The kernel lies about many files.
// Go ahead and try to read some bytes.
buffer = Buffer.allocUnsafe(8192);
bytesRead = tryReadSync(fd, isUserFd, buffer, 0, 8192);
if (bytesRead !== 0) {
ArrayPrototypePush(buffers, buffer.slice(0, bytesRead));
}
pos += bytesRead;
} while (bytesRead !== 0);
}
if (!isUserFd)
fs.closeSync(fd);
if (size === 0) {
// Data was collected into the buffers list.
buffer = Buffer.concat(buffers, pos);
} else if (pos < size) {
buffer = buffer.slice(0, pos);
}
if (options.encoding) buffer = buffer.toString(options.encoding);
return buffer;
}
很显然会调用到fs.openSync(path, options.flag, 0o666)这里去,继续跟进
function openSync(path, flags, mode) {
path = getValidatedPath(path);
//检测url,跟进看看
const flagsNumber = stringToFlags(flags);
mode = parseFileMode(mode, 'mode', 0o666);
const ctx = { path };
const result = binding.open(pathModule.toNamespacedPath(path),
flagsNumber, mode,
undefined, ctx);
handleErrorFromBinding(ctx);
return result;
}
getValidatedPath
function getValidatedPath (fileURLOrPath) {
const path = fileURLOrPath != null && fileURLOrPath.href && fileURLOrPath.origin
? fileURLToPath(fileURLOrPath)
: fileURLOrPath
return path
}
这里有个函数fileurltopath,看名字估计是将url对象转换为时间文件地址的功能,继续跟进
const fileURLToPath = (path) => {
if (typeof path === 'string') {
path = new URL(path)
} else if (!isURLInstance(path)) {
throw new ERR_INVALID_ARG_TYPE('path', ['string', 'URL'], path)
}
if (path.protocol !== 'file:') {
throw new ERR_INVALID_URL_SCHEME('file')
}
//令path.protocol属性为file:
return isWindows
? getPathFromURLWin32(path)
: getPathFromURLPosix(path)
//进入getPathFromURLPosix
}
const isURLInstance = (input) => {
return input != null && input.href && input.origin
//存在href和origin属性就返回真
}
跟进getPathFromURLPosix
const getPathFromURLPosix = (url) => {
if (url.hostname !== '') {
throw new ERR_INVALID_FILE_URL_HOST(process.platform)
}
//令path.hostname为空
const pathname = url.pathname
for (let n = 0; n < pathname.length; n++) {
if (pathname[n] === '%') {
const third = pathname.codePointAt(n + 2) | 0x20
if (pathname[n + 1] === '2' && third === 102) {
throw new ERR_INVALID_FILE_URL_PATH('must not include encoded / characters')
}
}
//这里对pathname进行解码
}
到这里就结束了,总结一下
protocol属性为file:
存在href和origin属性
hostname填url编码后的值
本地复现成功
数组传参,转对象,成功拿到flag
参考文章
https://nanimokangaeteinai.hateblo.jp/entry/2022/08/09/022238
3 条评论
师傅,请问那个fs.readFileSync的源码在哪看呀
https://github.com/nodejs/node/blob/v18.1.0/lib/fs.js
师傅,请问那个fs.readFileSync在哪看呀