第十九届 CISCN & 长城杯半决赛复盘

前言

3 月 22 日,第十九届 CISCN & 长城杯的线下半决赛。这次半决赛我们被分到重庆赛区,我负责 web 方向。一天就打完:上午 4 小时 AWDP 攻防对抗,下午 4 小时 ISW 综合渗透。

这篇文章只复盘属于我的部分——web 题和内网渗透。pwn 和逆向归队友管,我也不懂,就不献丑了。

先说结果:最终排在赛区前 25,晋级总决赛。至于过程嘛,有惊喜也有遗憾,往下看。

上午 AWDP:MediaDrive 的攻与修

AWDP 的玩法一句话说清:同一套服务,既能 break(拿到 flag 换攻击分),也要 fix 自己的(提交补丁、通过 check 换防御分),平台上攻击和防御是两个入口。check 的脾气可以总结成两句话:完全没修好,报”漏洞利用成功”;补丁把服务改坏、或者修复方式不符合要求,报”服务异常”。所以修复这事特别熬人——你不知道出题人的检测规则,只能换着姿势多试。

本届 web 一共四道题:easy_time、wso2、IntraBadge、MediaDrive。我只做出来了 MediaDrive,只拿到了fix防守分

题目背景

MediaDrive 是一个企业内部的媒体管理后台,支持文件上传、预览、管理和文件编码兼容转换。出题人在题目描述里其实把攻击面提示得很客气了——”系统在处理用户偏好、文件路径转换以及文件预览时存在潜在安全风险”。这三个关键词翻译一下:

  • 用户偏好 → Cookie
  • 文件路径转换 → iconv
  • 文件预览 → preview.php

三个词串起来,审计入口基本就锁定了。审计 preview.php,关键源码就这几行:

$user = null;
if (isset($_COOKIE['user'])) {
    $user = @unserialize($_COOKIE['user']);      // ① Cookie 直接反序列化
}
if (!$user instanceof User) {
    $user = new User("guest");
    setcookie("user", serialize($user), time() + 86400, "/");
}
$f = (string)($_GET['f'] ?? "");
$rawPath = $user->basePath . $f;                 // ② basePath 来自 Cookie,可控
if (preg_match('/flag|\/flag|\.\.|php:|data:|expect:/i', $rawPath)) {  // ③ 黑名单
    http_response_code(403);
    exit;
}
$convertedPath = @iconv($user->encoding, "UTF-8//IGNORE", $rawPath);   // ④ 编码转换
$content = @file_get_contents($convertedPath);   // ⑤ 直接读文件

漏洞分析

preview.php 的反序列化:系统把用户偏好直接存在 Cookie 里,服务端取出来不加分筛就丢给了 unserialize(),还原出一个 $user 对象,其中的 basePath 属性还会参与后面文件路径的拼接。Cookie 可控 + 反序列化 + 路径拼接,这尼玛经典的 PHP 反序列化利用场景。

download.php 的路径限制问题:文件上传部分的路径处理不严,上传位置可以被操纵,意味着能把文件写到预期目录之外——和预览功能串起来就是一条完整的链。

修复(Fix)

我们的修法两个点分别下刀:

  1. preview.php:反序列化是根,两种思路——PHP 的 unserialize() 第二个参数给 allowed_classes 白名单,把能还原的类卡死;或者更干脆,偏好存储改用 json,不反序列化。$user->basePath 再补一层 realpath 校验,必须落在设定的工作目录内,路径穿越直接掐死。
  2. download.php:上传路径由服务端指定,用户输入的文件名过 basename(),不允许自定义相对路径。

赛后翻各家公开复盘,能过 check 的修法其实五花八门,列两个开阔一下思路:

路径写死。把拼接这一行直接改掉,basePath 彻底出局,反序列化当场失去意义:

// $rawPath = $user->basePath . $f;
$rawPath = "/var/www/html/uploads/" . $f;

Cookie 先过滤再反序列化。有的队伍把 download.php、index.php、preview.php、profile.php 四个文件开头的反序列化统一改造成:先过一道关键词黑名单 + strlen($user) > 50 的长度卡死,命中就 header("Location: /") 弹走,不命中才放行给 unserialize():

if (isset($_COOKIE['user'])) {
    $user = $_COOKIE['user'];
    // 正则过长有删节,原版把 flag/select/union/引号/空字节/百分号/数字等全 ban 了
    if (preg_match("/flag|select|union|\\$|'|\"|--|#|\\0|into|file|\=|or|
        \x09|\x0a|\x0b|\x0c|\xa0|\%|\<|\>|\^|\x00|[0-9]|\x7c|and|where|\x26|
        sleep|benchmark|regexp|from|count|ascii|substr|load_file|join|show|
        update|concat|delete|alter|insert|create|drop|not|between|like|user|
        greatest|mid|char|hex|ord|limit|conv|table|rpad|\&|\*|\.|/is", $user)
        || strlen($user) > 50) {
        header("Location: /");
        die();
    }
    $user = @unserialize($user);
}

粗暴,但对这种无签名的反序列化是真管用。

修复的心得就一条:防御分按轮次发,改完先本地把正常功能跑通、确认漏洞真的堵死了再提交;另外修复代码里有语法错误等于白给,线下高压环境下这种低级失误并不少见,提交前多看一眼。

上午收工,MediaDrive 的fix修补第二轮就完成了,上午光靠这个题一直吃分

其他 web 题一览

  • easy_time:一道”双服务”题,Dockerfile 里起了两个 web 服务——对外是 python 服务,内部还藏着一个 php。审计点是加载远程头像处的 SSRF,配合插件上传的 zip 路径穿越写马,flag 据说还藏在 /tmp 里,不少队找半天。修复方向是把远程头像加载和上传功能禁掉,还有个坑:上传新代码服务并不会自动重启,得想办法让进程重新拉起。
  • wso2:基于真实企业级中间件 WSO2 改编的 Java 题。审计点是系统做数据库连接测试时对用户提交的 SQL 不做校验,攻击者可以利用 H2 数据库的特性执行恶意语句——官方描述还贴心提醒”记得考虑无回显情况”;防御侧只允许改一个 jar 文件,改多了容器启动超时直接判负。我们队那道 Java 完全没看懂是在干嘛,白白准备了很久。这题难到什么程度呢——赛后听说有队伍靠 rm /flag 过了 check,修不动漏洞就把 flag 物理消灭,也是个人才。
  • IntraBadge:企业内部”徽章卡片系统”,员工可以自定义展示模板、填写头像 URL,系统会自动去抓取头像、缓存之后渲染页面——avatar_refresh 接口没限制 URL 协议,连 redis:// 都能打内网,典型的 SSRF 面,还叠了一个从 Cookie 直接取用户身份的认证缺陷。

(pwn 方向另有四道题,队友fix成功了一道,帮我们稳固了排名)

下午 ISW:从 shiro 然后PK提权

下午的 ISW 综合渗透是另一种完全不同的体验:只做了一台靶机ISW-1

入口是一台双网卡机器:对外 8080 端口跑着 Shiro

flag1:Shiro 反序列化

按惯例 fscan 先扫一遍入口机,直接扫出了shiro反序列化 Pasted image 20260928160953.png

直接用ShiroAttack2工具一把梭拿到flag

Pasted image 20260928161128.png

拿到的只是普通用户权限,

find / -perm -4000 -type f 2>/dev/null

suid发现有pkexec,这是个CVE-2021-4034(PwnKit)

上传pwnkit的exp,直接提权到root

./pwnkit
5C1750F0-BD67-4440-AEBF-066C9A2A0DEA_1_105_c.jpeg

结果

八小时打完,最终排在赛区前 25,拿到总决赛门票,4 月福州见。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇