PHP弱类型与MD5绕过实战:以BUUCTF题目为例

发布时间:2026/11/2 20:28:46
PHP弱类型与MD5绕过实战:以BUUCTF题目为例

1. 题目背景与核心挑战解析

BUUCTF是国内知名的网络安全竞赛平台,[MRCTF2020]Ez_bypass是一道典型的PHP代码审计题目。这道题考察的是开发者对PHP弱类型比较和MD5哈希绕过的理解程度。根据题目名称"Ez_bypass"可以推测,解题关键在于找到合适的绕过方式。

从搜索到的信息来看,题目涉及以下核心考点:

  • GET/POST双传参方式
  • PHP的"==="强类型比较
  • MD5哈希碰撞或特殊值绕过
  • 变量相等性检查的规避技巧

2. 环境搭建与题目复现

2.1 本地测试环境配置

建议使用Docker快速搭建PHP测试环境:

docker run -d -p 8080:80 --name php-test -v "$PWD":/var/www/html php:7.4-apache

2.2 题目代码逻辑还原

根据搜索结果,题目核心逻辑大致如下:

<?php if(isset($_GET['id']) && isset($_GET['gg']) && $_GET['id'] === $_GET['gg']){ die("id和gg不能相同!"); } if(isset($_POST['passwd'])){ $passwd = $_POST['passwd']; if(!is_numeric($passwd)){ if($passwd == 1234567){ // 输出flag }else{ die("passwd错误!"); } }else{ die("passwd不能是纯数字!"); } } ?>

3. GET参数绕过技术详解

3.1 PHP弱类型比较漏洞

PHP中的"=="操作符会进行类型转换比较,而"==="会同时比较值和类型。题目要求id和gg参数不能相同但值又需要相等,这看似矛盾实则可通过以下方式绕过:

?id[]=1&gg[]=2

这样$_GET['id']和$_GET['gg']都是数组,值不相等但类型相同,满足"==="比较条件。

3.2 数组传参的底层原理

当URL参数以[]结尾时,PHP会将其解析为数组。这种特性常用于表单多选场景,但在CTF中常被用来绕过各种检查:

  • 数组与字符串比较永远返回false
  • 数组与数组比较时,即使元素不同也视为不同类型
  • 空数组与NULL比较的特殊行为

4. POST参数MD5绕过实战

4.1 非数字字符串的弱比较

题目要求passwd不能是纯数字,但弱比较时要等于1234567。这可以通过科学计数法或特殊字符串实现:

有效payload示例:

passwd=1234567a # 类型转换后等于1234567 passwd=1234567e0 # 科学计数法 passwd=0x12d687 # 十六进制表示

4.2 MD5哈希的特殊值

虽然题目描述提到MD5,但从代码看更可能是弱类型比较。不过MD5碰撞也是常见考点,需注意这些特殊值:

  • 0e开头的MD5值会被当作科学计数法
  • 240610708和QNKCDZO的MD5都是0e开头
  • 数组的MD5计算结果为NULL

5. 完整解题流程演示

5.1 分步操作指南

  1. 构造GET请求绕过id和gg检查:
http://target.com/?id[]=1&gg[]=2
  1. 使用Burp Suite拦截POST请求,添加:
passwd=1234567a
  1. 或者直接使用curl命令:
curl -X POST -d "passwd=1234567e0" "http://target.com/?id[]=1&gg[]=2"

5.2 常见错误排查

  • 确保参数名称完全匹配(注意大小写)
  • 数组传参时[]不能遗漏
  • 如果返回500错误,可能是PHP版本不兼容
  • 某些环境需要URL编码特殊字符

6. 防御方案与最佳实践

6.1 安全的比较方式

// 严格类型+严格比较 if(strcmp($a, $b) === 0){...} // 使用hash_equals防止时序攻击 if(hash_equals($a, $b)){...}

6.2 输入验证规范

// 明确类型检查 if(!is_string($input) || strlen($input) > 32){ die("Invalid input"); } // 白名单验证 $allowed = ['value1', 'value2']; if(!in_array($input, $allowed, true)){...}

7. 扩展思考与类似题型

7.1 其他常见绕过方式

  • strcmp数组绕过:传递数组使函数返回NULL
  • preg_match数组绕过:对数组返回false
  • switch弱类型比较:case穿透问题

7.2 推荐练习题目

  • [SUCTF 2019]EasySQL
  • [CISCN 2019]Love Math
  • [NCTF 2019]True XML cookbook

在实际渗透测试中,这类漏洞常出现在用户认证、密码重置等关键功能点。我曾在一个企业项目中发现通过构造科学计数法payload可以绕过短信验证码校验,原理与本案例类似。开发团队修复后,我们在代码审查环节增加了专门的弱类型检查规则。