跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
PHP算法

CTF Web 入门:EZMD5 系列漏洞原理与绕过详解

综述由AI生成详细解析了 CTF Web 竞赛中 EZMD5 系列的常见漏洞类型。主要涵盖 PHP 松散比较导致的 MD5 哈希碰撞(如 0e 开头科学计数法)、数组绕过技巧(md5 返回 null)、以及强比较下的哈希碰撞问题。同时介绍了 URL 参数数组定义方法及 PHP 逻辑与位运算符的区别,提供了相应的 Payload 示例与解决方案。

战神发布于 2026/4/5更新于 2026/5/2024 浏览
CTF Web 入门:EZMD5 系列漏洞原理与绕过详解

EZMD5

文章配图

代码审计

include "flag.php";
highlight_file(__FILE__);

包含了 flag.php 文件并展示源代码。

if (isset($_GET['QC'])) {
    $qc = (string)$_GET['QC'];
    $hp = md5($qc);

要求 get 传参 QC 并且设置了一个变量保存这个 QC 的字符串格式,其后有设置一个变量$hp 为其的 md5 值。

if ($hp == $admin_hash) {
    echo "<br>Welcome, admin!<br>";
    echo $flag;
} else {
    echo "<br>Login failed.";
}

最后对比$admin_hash 和$hp 这两个变量且是松散比较(==)。若相等则返回 flag 的值。

这里观察到最开始的变量像是一个科学计数法的表示。而且当使用 == 比较两个字符串时,如果它们看起来像科学计数法表示的数字,PHP 会尝试将它们转换为数字进行比较。

  • '0e830400451993494058024219903391'会被当作科学计数法:0 × 10^830400451993494058024219903391,其计算结果为 0。
  • 同理,如果 md5($qc)的结果也是一个以 0e 开头、后面全是数字的字符串,它也会被转换为数字 0。

所以只需要找到一个 MD5 值也为 0e 开头且后面是数字的字符串。

有以下几个:QNKCDZO, 240610708, aabg7XSs, s878926199a。

最终 payload:?QC=QNKCDZO

文章配图

拓展

若这里是强比较 (===) 的话,那就不可以了。

强比较规则:

  • 值是否相等
  • 类型是否相同
  • 对于字符串,会逐字符精确比较

此时就只能进行 md5 碰撞攻击,也就是知道了 md5 值求原来的那个字符串,基本上就只能编写脚本了。

PHP 中的逻辑运算符及其优先级,短路求值

逻辑与 (AND)
  • 运算符:&&或 and
  • 说明:当两个操作数都为 true时,结果才为 true。
逻辑或 (OR)
  • 运算符:||或 or
  • 说明:当至少一个操作数为 true时,结果就为 true。
逻辑非 (NOT)
  • 运算符:!
  • 说明:对布尔值取反。
逻辑异或 (XOR)
  • 运算符:xor
  • 说明:当两个操作数一真一假时,结果才为 true(两者相同则 false)。
优先级与短路求值
  • 优先级(从高到低):! > && > || > and > xor > or
  • 短路求值:
    • 对于 &&:如果第一个操作数为 false,则不会计算第二个操作数(因为结果已确定)。
    • 对于 ||:如果第一个操作数为 true,则不会计算第二个操作数。

PHP 中的位运算符

位与 &(Bitwise AND)
  • 作用:对两个数字的每一个二进制位进行 AND 操作。
  • 规则:两位都为 1 时,结果位才为 1。
位或 |(Bitwise OR)
  • 作用:对两个数字的每一个二进制位进行 OR 操作。
  • 规则:两位中至少一个为 1 时,结果位就为 1。

特殊场景:在布尔值上使用 &和 |

当操作数是布尔值(或可转换为布尔的值)时,&和 |会先将它们转换为整数(true-> 1, false-> 0),进行位运算,再将结果转换回布尔值。这有时会导致与 &&、||不同的结果。

EZMD5_1

文章配图

代码审计

if (isset($_GET['a']) && isset($_GET['b'])) {
    $a = $_GET['a'];
    $b = $_GET['b'];

判断是否 get 传入了 a 和 b 并定义变量保存。

if ($a != $b && md5($a) == md5($b)) {
    echo "<br>Welcome, admin!<br>";
    echo $flag;

这里要求$a不能等于$b,但是它俩的 md5 值弱相等 (==)。这里很容易想到数组绕过,任何数组的 md5 值都为 Null。

Payload

?a[]=1&b[]=2

这里的数组定义是 url 上的定义方法,这方面内容也在我那个博客里提及(这个在第二题)

EZMD5_2

文章配图

代码审计

其他的代码沿用前几个题的,就不多解释了

if (substr($md5_a, 0, 2) === '0e' || substr($md5_b, 0, 2) === '0e') {
    echo "<br>0e not allowed!";

这是比上一个题多的要求,意思是不能俩变量的值都不能以'0e'开头。但是对数组绕过没有影响。

Payload

?a[]=1&b[]=2

文章配图

拓展

URL 上数组的定义方法
1. 基本语法:方括号 []

这是最常用的方法,在参数名后添加 []来告诉 PHP 这是一个数组。

// URL: page.php?colors[]=red&colors[]=green&colors[]=blue
// PHP 中获取: $colors = $_GET['colors'];
// 数组: ['red', 'green', 'blue']
// 或者明确指定索引(数字):
// URL: page.php?colors[0]=red&colors[1]=green&colors[2]=blue
2. 关联数组(指定键名)

可以在方括号内指定字符串键名来创建关联数组。

// URL: page.php?user[name]=John&user[age]=25&user[city]=Beijing
// PHP 中获取: $user = $_GET['user'];
// 数组: ['name' => 'John', 'age' => '25', 'city' => 'Beijing']
// 多维数组:
// URL: page.php?product[0][name]=Phone&product[0][price]=999&product[1][name]=Case
$product = $_GET['product'];
// 二维数组: [0 => ['name'=>'Phone','price'=>'999'], 1 => ['name'=>'Case']]
3. URL 编码注意事项

当键名或值包含特殊字符时,需要 URL 编码。

// 原始:page.php?filters[sort by]=date&filters[price range]=100-200
// 实际 URL 需要编码:
// page.php?filters[sort%20by]=date&filters[price%20range]=100-200
// PHP 会自动解码: $filters = $_GET['filters'];
// ['sort by' => 'date', 'price range' => '100-200']

以下是必须编码的字符

文章配图

EZMD5_3

文章配图

依旧类似前面的,不过==变成了===。还是不影响数组绕过 (第一种方法)。

第二种方法:需要找两个不同的字符串但 MD5 值却相等的。

文章配图

EZMD5_4

文章配图

代码审计

if (isset($_GET['QC'])) {
    $qc = (string)$_GET['QC'];
    if(substr(md5($qc),-6,6) ==='d54e23')

核心要求是截取$qc 的值从 -6 位置,截取 6 位,必须是 d54e23。只能暴力破解了,编写脚本求出 payload。

EZMD5_5

文章配图

这道题与前面的异曲同工,只是由 MD5 变成了 sha1。继续数组绕过即可。

payload ?a[]= &b[]=2

文章配图

EZMD5_6

文章配图

依旧与前面的题一样,依旧数组绕过。

payload ?a[]= &b[]=2

文章配图

目录

  1. EZMD5
  2. 代码审计
  3. 拓展
  4. PHP 中的逻辑运算符及其优先级,短路求值
  5. 逻辑与 (AND)
  6. 逻辑或 (OR)
  7. 逻辑非 (NOT)
  8. 逻辑异或 (XOR)
  9. 优先级与短路求值
  10. PHP 中的位运算符
  11. 位与 &(Bitwise AND)
  12. 位或 |(Bitwise OR)
  13. 特殊场景:在布尔值上使用 &和 |
  14. EZMD5_1
  15. 代码审计
  16. Payload
  17. EZMD5_2
  18. 代码审计
  19. Payload
  20. 拓展
  21. URL 上数组的定义方法
  22. 1. 基本语法:方括号 []
  23. 2. 关联数组(指定键名)
  24. 3. URL 编码注意事项
  25. EZMD5_3
  26. EZMD5_4
  27. 代码审计
  28. EZMD5_5
  29. EZMD5_6
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • C++ 算法实战:排序子序列、消减整数与最长上升子序列
  • 小米智能家居接入 Home Assistant 实战指南
  • 无人机视角山区泥石流和滑坡图像识别数据集
  • 2025 年数据科学、人工智能与机器学习职位薪资数据可视化分析
  • 开源墙绘机:双轴张力控制低成本绘图系统
  • Flutter 状态管理为何走上“百家争鸣”之路?
  • 爬虫与反爬虫技术原理及应对策略
  • 后仿真 SDF 反标 Warning 描述与解决方案
  • JiuwenClaw AI 智能体工具安装与核心功能解析
  • 常见排序算法详解与 Java 实现
  • 基于 YOLOv5 的深度学习火焰检测识别系统
  • Apache IoTDB 时序数据管理:写入、存储与查询优化
  • 数据结构初阶:堆的实现
  • C++ 异常机制深度解析:栈展开与控制流原理
  • 渐进式 AIGC 系统架构解析:支持多模态大模型与 Agent 工作流私有化部署
  • TWIST2 全身 VR 遥操控制系统:基于视觉观测的人形机器人自主策略学习
  • 傅里叶级数与变换:从连续到离散的完整体系梳理
  • VSCode Copilot 接入智谱 GLM-4 及任意大模型配置方案
  • Webhook 原理与 Langflow 实战集成指南
  • Google AI Studio 使用指南:Gemini 3.0 Pro 参数配置与系统指令优化

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • curl 转代码

    解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online