1. 开赛前两小时:赛制信号与目标赛题摸底
AWDP这种模式,和纯CTF的解题赛完全是两种打法。解题赛你可以按自己的节奏,先挑软的捏,慢慢磨难题;AWDP的核心逻辑只有三个字:抢时间。你比对手早一分钟拿到flag,就多一分主动权;你比对手晚一分钟回去补漏洞,就可能在分数榜上被拉开一个身位。
半决赛那天早上到场地的时候,我先做的不是翻规则文档,而是把整场比赛的计分逻辑重新捋了一遍。AWDP的典型结构一般是:主办方给每个参赛队下发一套完全相同的Web靶机环境,除了初始防护策略可能略有差异外,漏洞点基本一致。你的得分来源分三块:一是每道赛题预设的flag,在固定时间点刷新,你需要在刷新后尽快通过漏洞打进去拿到flag提交;二是你攻破别人靶机后,可以植入指定的"破坏性文件"或者篡改页面内容,按存活时间和范围判分;三是你守好自己的靶机,阻断别人打进来,防御行为本身也有一定的基础分。
这里有个很多人容易忽视的点:AWDP是同一套环境,意味着你发现一个洞,所有队伍的环境理论上都有同一个洞。 所以前半程的核心不是"会不会做这道题",而是"能不能在别人把洞堵上之前把分拿到"。半决赛前几分钟,我看到下发靶机的端口开放情况是典型的Web服务集合——80端口的业务站点、3306端口的MySQL、6379的Redis暴露在外网,还有一个不太常见的9000端口,后来确认是内网使用的目录浏览服务。这种暴露面越大,说明主办方故意留的口子越多,考察的不是单纯的漏洞挖掘,而是你在多个口子之间的优先排序能力。
我当时的初始判断是:这一场半决赛的赛题风格偏向"复杂业务逻辑+已知组件漏洞组合利用",不太可能出那种看一眼就知道是CMS几行代码注入的题目。接下来的比赛节奏也印证了这一点——真正拉开差距的地方,往往在一个你忽略的次要端口,或者一套老组件里埋着的二次开发代码。
2. 半决赛实战拆解:三道最具代表性的赛题复盘
2.1 第一道题:老版本框架反序列化点与本地文件读取的组合利用
第一道题的业务场景是一个类似"内部工单系统"的PHP应用。打开首页,登录框、工单列表、附件下载,功能倒是齐全,但整套系统的款式一眼就能看出是拿几年前流行过的一套开源框架改的。这类题的典型套路是:开发者在原框架之上做二次开发,结果把框架自带的调试组件暴露了出来。
我现在的习惯是,拿到一个Web题先做三件事:
- 看响应头里带的服务器版本、框架标识、X-Powered-By信息;
- 翻静态资源路径,看有没有已暴露的JS、图片、样式文件可以反推目录结构;
- 扫一遍常见备份文件、调试接口、路由配置文件。
这道题在第二步就有了收获——站点根目录下一个debug.php.bak文件直接暴露了调试组件的启用状态。现在的比赛环境虽然不会让你那么轻松拿到源码,但这个备份文件里恰好写了一个反序列化入口,参数名是data,接收base64编码后的数据,直接传入一个没有做任何过滤的unserialize()函数。
当时我用了两条路线并行:
- 一条路线是拿已知的PHP框架反序列化POP链打RCE;
- 另一条路线是利用这个入口做文件读取,先拿
/etc/passwd验证执行路径,再读取Web目录下的配置文件。
最后走的实际上是第二条路线。原因是主办方给这个入口加了一层disable_functions,把system、exec、passthru这些常见命令执行函数全禁掉了。你就算拿到了RCE权限,也执行不了命令,只能做文件读写和目录遍历。这时候反而变成了一道"受限条件下的文件利用题"。
解题的关键动作变成了:
- 通过反序列化入口读取
/var/www/html/config/database.php,拿到MySQL账号密码; - 用PDO的MySQL连接能力,尝试
select ... into outfile写Webshell; - 如果写不进Web根目录,就换个思路——查找系统里有没有定时任务、SS
