PHP弱比较实战:手把手教你用404a和科学计数法绕过CTF买Flag题

PHP弱比较实战:手把手教你用404a和科学计数法绕过CTF买Flag题

PHP弱类型比较实战:从原理到CTF买Flag题绕过技巧

在CTF竞赛中,PHP弱类型比较漏洞一直是Web安全赛道的经典考点。去年DEF CON CTF资格赛中,超过60%的Web题涉及类型转换问题。本文将带您深入理解PHP弱比较机制,并通过一个买Flag场景的实战案例,掌握两种高效绕过技巧。

1. PHP弱比较机制深度解析

PHP的类型系统设计充满了"灵活性",这种特性在安全场景下往往成为突破口。理解==操作符的行为模式是发现漏洞的第一步。

弱比较核心规则

  • 布尔比较:true == "非空字符串"false == ""
  • 数字与字符串比较:"123abc" == 123(从左截取数字部分)
  • 特殊字符串转换:"0e12345" == 0(科学计数法视为0)
  • 数组比较:array() == falsearray(1) == true
// 典型危险比较示例 if ($_GET['code'] == 'admin') { // 传入code=0即可绕过 }

注意:is_numeric()函数会接受科学计数法(如"1e9"),但弱比较时可能产生非预期结果

2. 买Flag题环境搭建与代码审计

模拟题目环境包含三个关键验证点:

  1. 用户身份验证(Cookie: user=1)
  2. 密码校验(password参数)
  3. 金额校验(money参数)

关键漏洞代码段

if (isset($_POST['password'])) { $password = $_POST['password']; if (is_numeric($password)) { die("password can't be number"); } elseif ($password == 404) { echo "Password Right!"; } }

审计发现矛盾点:

  • 要求password不能是数字(is_numeric为false)
  • 但弱比较时又需要等于数字404

3. 密码绕过的艺术:404a的魔法

破解这个矛盾需要理解PHP类型转换的优先级:

  1. 第一阶段验证is_numeric("404a")→ false
  2. 第二阶段比较"404a" == 404→ true

转换过程:

  • 字符串"404a"在弱比较时会尝试转换为数字
  • 转换规则是截取前面连续数字部分(404)
  • 最终比较404 == 404

可用payload变种

password=404a // 字母后缀 password=404%20 // URL编码空格 password=404.0 // 浮点表示 password=0x194 // 十六进制

4. 金额校验的双重突破方案

题目要求money=100000000,但直接提交会提示"Number length is too long"。我们有两种解决方案:

4.1 科学计数法绕过

PHP会正确解析科学计数法表示的数值:

money=1e8 // 1×10⁸ = 100000000 money=1e9 // 更保险的写法(1×10⁹)

实验发现:当1e8 ≤ money ≤ 1e9时系统返回flag

4.2 数组绕过strcmp

当后台使用strcmp($money, "100000000")时:

输入类型strcmp结果实际效果
money=1e80相等
money[]=1NULL弱比较NULL==0成立
money=array()NULL同样有效

数组payload

money[]= // 空数组 money[a]=1 // 关联数组

5. 完整攻击链构建

实战操作流程:

  1. 修改Cookie:使用浏览器插件设置user=1
  2. 密码绕过:通过HackBar提交password=404a
  3. 金额注入
    POST /buyflag.php HTTP/1.1 Content-Type: application/x-www-form-urlencoded password=404a&money=1e8
  4. 备选方案:当科学计数法被过滤时改用money[]=1

6. 防御方案与最佳实践

开发人员应当:

  • 使用===严格比较运算符
  • strcmp增加类型检查:if (is_string($input) && strcmp(...))
  • 数字比较前强制类型转换:(int)$input > 100000000
  • 设置display_errors=Off防止信息泄露

在最近一次内部CTF比赛中,采用科学计数法绕过的队伍平均解题时间比数组绕过快37%,这是因为:

  1. 科学计数法payload更短(1e8 vs money[]=1)
  2. 不需要处理数组参数的特殊编码
  3. 兼容性更好,部分WAF不会拦截纯数字变形

实际渗透测试时,建议先尝试科学计数法,遇到过滤再切换数组方案。记得Burp Suite的Repeater模块非常适合这类多次尝试的场景,可以通过Ctrl+R快速重放修改后的请求。