CTF Web PHP弱类型与进制绕过(过滤)
题目代码分析
if(isset($_GET['pangoulin'])){ // 有pangoulin参数$pangoulin = $_GET['pangoulin'];if($pangoulin==="4476"){ // 严格等于"4476"拦截die("no no no!");}if(preg_match("/[a-z]/i", $pangoulin)){ // 有字母拦截die("no no no!");}if(!strpos($pangoulin, "0")){ // 没有"0"或"0"在首位拦截die("no no no!");}if(intval($pangoulin,0)===4476){ // 转换为数字等于4476则输出flagecho $flag;}
}
绕过条件分解
1.严格字符串拦截
=== "4476"
要求参数不能为字符串"4476"
,但可通过其他形式(如浮点、进制)表示4476。
2.字母过滤
正则/[a-z]/i
禁止任何字母,排除十六进制(如0x117c
)或科学计数法(如4476e0
)的解法。
3.数字0的位置限制
!strpos($pangoulin, "0")
需满足:
- 必须包含字符
"0"
(否则strpos
返回false
,!false
触发拦截)。 "0"
不能在首位(否则strpos
返回0
,!0
触发拦截)。
4.intval转换规则
intval($pangoulin, 0)
的自动进制识别逻辑:
0x
前缀:十六进制(受0的位置限制)0
前缀:八进制(受0的位置限制)- 其他:十进制
- 需最终十进制值为4476。
有效解法与原理
浮点形式"4476.0"
- 不匹配
=== "4476"
- 无字母,通过正则
strpos("4476.0", "0")
返回5(非首位),!5
为false
intval("4476.0", 0)
截断小数部分,得到4476
思考的流程图
最终Payload
?pangoulin=4476.0
总结
本题考查PHP弱类型、进制识别和strpos返回值陷阱,只允许数字且"0"不能在首位。
利用"4476.0"(浮点数形式)既能通过所有过滤,又能被intval转为4476,成功拿到flag。