CTF解题:[NSSCTF 2022 Spring Recruit]弱类型比较绕过

一、漏洞背景介绍

在 CTF(Capture The Flag)竞赛和 Web 安全测试中,PHP 语言的类型比较漏洞是常见的考点。这类漏洞源于 PHP 的弱类型特性,即当使用==进行比较时,PHP 会自动进行类型转换,从而导致一些不符合预期的比较结果。本文将通过分析一道具体的 PHP 代码题目,深入探讨这类漏洞的原理和利用方法。

二、题目代码分析

我们先来看一下题目给出的 PHP 代码:

<?php
highlight_file(__FILE__);
include_once('flag.php');
if(isset($_POST['a'])&&!preg_match('/[0-9]/',$_POST['a'])&&intval($_POST['a'])){if(isset($_POST['b1'])&&$_POST['b2']){if($_POST['b1']!=$_POST['b2']&&md5($_POST['b1'])===md5($_POST['b2'])){if($_POST['c1']!=$_POST['c2']&&is_string($_POST['c1'])&&is_string($_POST['c2'])&&md5($_POST['c1'])==md5($_POST['c2'])){echo $flag;}else{echo "yee";}}else{echo "nop";}}else{echo "go on";}
}else{echo "let's get some php";
}
?>

2.1 条件逐层分析

这段代码通过四重条件判断来控制 flag 的输出,我们需要逐一分析每个条件的要求:
第一层条件:

isset($_POST['a']) && !preg_match('/[0-9]/', $_POST['a']) && intval($_POST['a'])

必须存在 POST 参数a
a的值不能包含任何数字字符
a的值被转换为整数后必须为真(即非零)
第二层条件:

isset($_POST['b1']) && $_POST['b2']

必须存在 POST 参数b1和b2
第三层条件:

$_POST['b1'] != $_POST['b2'] && md5($_POST['b1']) === md5($_POST['b2'])

b1和b2的值不能相等
但它们的 MD5 哈希值必须严格相等(使用===比较)
第四层条件:

$_POST['c1'] != $_POST['c2'] && is_string($_POST['c1']) && is_string($_POST['c2']) && md5($_POST['c1']) == md5($_POST['c2'])

c1和c2的值不能相等
它们都必须是字符串类型
它们的 MD5 哈希值必须宽松相等(使用==比较)

三、漏洞利用原理

3.1 第一层条件绕过:非数字的整数

第一个挑战是如何让一个字符串不包含数字,但转换为整数后却非零。PHP 的类型转换规则为我们提供了突破口。当一个字符串被转换为整数时,PHP 会从字符串的开始处提取数字部分,直到遇到非数字字符为止。如果字符串以非数字字符开头,则转换结果为 0。
解决方案:使用科学计数法表示数字。例如,字符串1e0在 PHP 中会被解释为1 * 10^0 = 1,但它并不包含数字字符0-9,因为e在科学计数法中是合法的指数符号。
验证代码:

<?php
var_dump(preg_match('/[0-9]/', '1e0')); // bool(false)
var_dump(intval('1e0')); // int(1)
?>

除了使用科学计数法,还可以利用 PHP 数组的特性绕过第一个条件。当$_POST[‘a’]是一个数组时:

preg_match('/[0-9]/', $_POST['a'])会返回false(即不匹配)

因为preg_match期望的参数是字符串,当传入数组时会触发警告,但返回值为0(表示不匹配)

intval($_POST['a'])会返回0

因为数组转换为整数时结果为0
矛盾点:虽然preg_match检查通过了,但intval($_POST[‘a’])返回0,而第三个条件要求转换结果为真(非零)。这看似是一个矛盾,但实际情况中可能存在两种解释:
PHP 版本差异:在某些 PHP 版本中,数组转换为布尔值时可能被视为true
测试代码:

<?php
$a = array('a');
var_dump((bool)$a); // 通常输出bool(true)
var_dump(intval($a)); // 输出int(0)
?>

但在条件表达式中,intval($a)明确返回0,这应该导致条件失败。因此这种解释可能不成立。
代码逻辑漏洞:出题者可能忽略了数组对preg_match的影响
当传入a[]=a时,虽然intval返回0,但出题者可能误以为数组转换为整数会得到非零值
实际测试:在大多数 PHP 环境中,a[]=a会导致第一个条件失败。但如果题目环境存在特殊配置(如错误抑制符@屏蔽了preg_match的警告),这种绕过方式可能有效。
建议:在实际 CTF 题目中,如果遇到类似情况,两种方法都应该尝试:

  1. 使用科学计数法a=1e0(通用有效)
  2. 尝试数组绕过a[]=a(可能在特定环境中有效)

3.2 第二层条件绕过:数组的 MD5 哈希

第二个挑战是找到两个不同的值,它们的 MD5 哈希值严格相等。PHP 在处理数组的哈希函数(如 md5 ()、sha1 ())时有一个特殊行为:当传入的参数是数组时,这些函数会返回NULL。
解决方案:使用数组作为参数。例如:

<?php
$b1 = array(1);
$b2 = array(2);
var_dump($b1 != $b2); // bool(true)
var_dump(md5($b1) === md5($b2)); // bool(true),因为md5($b1)和md5($b2)都为NULL
?>

3.3 第三层条件绕过:MD5 碰撞与弱类型比较

第三个挑战是找到两个不同的字符串,它们的 MD5 哈希值在宽松比较下相等。这需要利用 PHP 的弱类型特性和特定的 MD5 碰撞字符串。
当使用==比较两个字符串时,如果它们看起来像科学计数法表示的数字(即0e开头,后面跟着数字),PHP 会将它们解释为 0 的幂,因此所有这种形式的字符串在宽松比较下都相等。
解决方案:使用特定的 MD5 碰撞字符串。例如:
QNKCDZO的 MD5 值是0e83040045199349405802421990339
QLTHNDT的 MD5 值是0e40596782540195537254913908420
验证代码:

<?php
$c1 = "QNKCDZO";
$c2 = "QLTHNDT";
var_dump($c1 != $c2); // bool(true)
var_dump(is_string($c1) && is_string($c2)); // bool(true)
var_dump(md5($c1) == md5($c2)); // bool(true)
?>

四、完整 POC 与利用

方案一:科学计数法(推荐)

POST / HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 71a=1e0&b1[]=1&b2[]=2&c1=QNKCDZO&c2=QLTHNDT

方案二:数组绕过(特定环境可能有效)

POST / HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 71a[]=a&b1[]=1&b2[]=2&c1=QNKCDZO&c2=QLTHNDT

标题五、扩展知识点

5.1 PHP 弱类型比较总结

PHP 的弱类型比较是一个常见的安全风险点。下表总结了一些常见的弱类型比较陷阱:

表达式结果原因
0 == "0"true字符串 "0" 被转换为整数 0
0 == "abc"true字符串 "abc" 转换为整数 0
"10" == "010"false字符串比较不进行类型转换
10 == "010"true字符串 "010" 被转换为整数 10
md5("240610708") == md5("QNKCDZO")true两个 MD5 值都是 0e 开头的字符串,在宽松比较下相等
sha1("aaroZmOk") == sha1("aaK1STfY")true两个 SHA1 值都是 0e 开头的字符串,在宽松比较下相等

5.2 更多 MD5 碰撞字符串

除了前面提到的QNKCDZO和QLTHNDT,还有许多其他的 MD5 碰撞字符串对,例如:

240610708 和 QNKCDZO
aabg7XSs 和 aabC9RqS

这些字符串对的 MD5 值都是0e开头,因此在 PHP 的宽松比较下相等。

六、总结

通过分析这道 CTF 题目,我们深入了解了 PHP 弱类型比较漏洞的原理和利用方法。这类漏洞虽然在现代 PHP 应用中已经较少见,但在一些老旧系统或代码中仍然可能存在。理解这些漏洞的工作原理,不仅有助于我们在安全测试中发现问题,也能指导我们写出更安全的 PHP 代码。
在实际渗透测试和 CTF 竞赛中,遇到类似的多条件验证题目时,我们需要逐一分析每个条件的绕过方法,结合编程语言的特性和漏洞利用技巧,构造出能够通过所有验证的 POC。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/85221.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/85221.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【SQL】存储过程 vs 普通 SQL

一、存储过程 vs 普通 SQL 的核心区别 先明确两者的本质&#xff1a; 普通 SQL&#xff1a;是直接执行的查询 / 操作语句&#xff08;如SELECT、INSERT&#xff09;&#xff0c;每次执行都要编译&#xff0c;逻辑写在应用端或直接运行。存储过程&#xff1a;是预编译并存储在…

Vue.js第一节

初识Vue、插值操作、属性绑定 初识&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>D…

前端打断点

这个按钮有个点击事件&#xff0c;然后点击这个js 即可进入到代码中 如果这时想打一些临时的表达式&#xff0c;可以按esc弹出console控制台&#xff0c; 右上角有可以使用的变量

Jmeter接口测试与性能测试

&#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 目前最新版本发展到5.0版本&#xff0c;需要Java7以上版本环境&#xff0c;下载解压目录后&#xff0c;进入\apache-jmeter-5.0\bin\&#xff0c;双击ApacheJMete…

如何利用大模型搭建本地知识库

要利用大模型搭建本地知识库&#xff0c;核心在于&#xff1a;构建高质量知识内容源、使用向量化技术实现语义检索、部署大语言模型以实现自然语言问答接口、设计本地知识库的数据更新机制、注重隐私与合规性控制。其中&#xff0c;使用向量化技术实现语义检索至关重要&#xf…

vscode连接不上服务器问题修复

原因&#xff1a;运维人员修复漏洞&#xff0c;升级了服务器openssh版本&#xff0c;导致无法新建连接连上vscode 操作&#xff1a; 1.删除云桌面上C:\Users\.ssh 路径下known_hosts文件&#xff1b; 2.设置免密登录 1&#xff09;执行 ssh-keygen -t rsa -C "your_em…

架构优化——submodule转为subtree

文章目录 背景subtree优势submodule切换到subtree脚本subtree使用切开发分支推送代码同步代码 背景 submodule过多&#xff0c;目前20个submodule需要切出20个分支&#xff0c;查看提交记录、切分支等使用起来麻烦。 团队深受困扰&#xff01; subtree优势 继承submodule的…

车载软件架构 --- 汽车中央控制单元HPC软件架构方案实例

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 做到欲望极简,了解自己的真实欲望,不受外在潮流的影响,不盲从,不跟风。把自己的精力全部用在自己。一是去掉多余,凡事找规律,基础是诚信;二是…

零基础开始的网工之路第二十一天------性能优化

目录 一、性能优化概述 二、性能监控工具 1. 基础工具 2. 高级工具 三、子系统优化策略 1. CPU优化 2. 内存优化 3. 磁盘I/O优化 4. 网络优化 四、资源限制优化 1. ulimit 2. cgroups&#xff08;控制组&#xff09; 五、安全与注意事项 六、综合案例 案例1&…

【Google Chrome】谷歌浏览器历史版本下载

最新版&#xff1a; Chrome for Testing availability 谷歌浏览器 Chrome 最新版离线安装包下载地址 v137.0.7151.104 - 每日自动更新 | 异次元软件 历史版本&#xff1a; Download Google Chrome 105.0.5195.102 for Windows - Filehippo.com chrome浏览器,chrome插件,谷…

线性表实训(头歌实践平台课程答案详细解说)

C 和 C 支持 4 种基本数据类型&#xff08;整型、浮点型、字符型、布尔型&#xff09;和 3 种复合型数据类型&#xff08;数组、指针、结构&#xff09;。复合类型的数据对于数据结构至关重要&#xff0c;因为从某种程度上来说数据量的多少和数据结构的好坏决定了程序的复杂程度…

【前端】threeJS学习(长期更新)

简介 Three.js是用JavaScript编写的第三方库&#xff0c;用于实现3D功能&#xff0c;基于WebGL进行封装。 一个3D模型的建立主要由以下几个部分组成&#xff08;基本版&#xff09;&#xff1a; * 创建场景scene--相机camera--渲染器renderer--(灯光light)&#xff1b; *…

Linux系统--权限

大家好&#xff0c;上一次我们学习了关于Linux中的基础指令&#xff0c;那么我们今天来继续学习Linux的新的内容&#xff1a;权限。那么话不多说&#xff0c;我们开始今天的学习&#xff1a; 目录 Linux权限 1. Linux权限的概念 2. Linux权限管理 3. ⽂件权限值的表⽰⽅法…

论文笔记 <交通灯> <多智能体>DERLight双重经验回放灯机制

今天看的论文是这篇 主要提出了传统优先级经验回放&#xff08;PER&#xff09;在复杂交通场景中效率低下&#xff0c;使用二叉树存储样本&#xff0c;导致大规模样本时计算复杂度高。而且不丢弃样本&#xff0c;造成存储空间浪费。 双重经验池&#xff1a; 为了解决以上问题…

Chromium 136 编译指南 macOS篇:环境准备与系统配置(一)

1. 引言 在浏览器技术的星空中&#xff0c;Chromium 犹如一颗最亮的明星&#xff0c;照亮了整个互联网的发展轨迹。作为推动现代 Web 技术革命的核心引擎&#xff0c;Chromium 不仅是 Google Chrome 的技术基石&#xff0c;更是 Microsoft Edge、Opera、以及众多定制浏览器的共…

linux机器间无密码如何传输文件

1. scp传输时的问题 $ scp deepseek_r1_distill_qwen1.5b_content_audit_fp16_20250613_2_Q4_K_M.gguf xxx192.168.xxx:/home/xxx/pretrained_model/output The authenticity of host 192.168.xxx (192.168.xxx) cant be established. ED25519 key fingerprint is SHA256:deOs…

PySpark 使用pyarrow指定版本

背景说明 在 PySpark 3.1.3 环境中&#xff0c;当需要使用与集群环境不同版本的 PyArrow (如 1.0.0 版本)时&#xff0c;可以通过以下方法实现&#xff0c;而无需更改集群环境配置 完整操作说明 去pyarrowPyPI下载对应版本的whl文件后缀whl直接改成zip解压后有两个文件夹&am…

安卓APP投屏调试工具使用教程

安卓APP投屏调试工具使用教程 一、准备工作&#xff08;一&#xff09;下载ADB工具&#xff08;二&#xff09;配置ADB的环境变量&#xff08;三&#xff09;检查是否成功安装&#xff08;四&#xff09;adb核心命令说明 二、无线调试流程&#xff08;一&#xff09;环境要求&a…

huggingface网站里的模型和数据集

直接下载肯定是不太行&#xff0c;平时访问都不容易&#xff0c;更别提下载东西了&#xff0c;但是我们可以通过国内镜像进行快速下载。 镜像网址&#xff1a; hf-mirror地址&#xff1a;HF-Mirror 进入网站之后&#xff0c;在搜索框里搜索你想下载的内容&#xff0c;接下来…

Node.js 路由请求方式大全解:深度剖析与工程实践

文章目录 &#x1f310; Node.js 路由请求方式大全解&#xff1a;深度剖析与工程实践一、&#x1f4dc; HTTP 请求方法全景图&#x1f3c6; 核心方法深度对比HTTP 请求方法概念对比表&#x1f6e0;️ 特殊方法应用场景 二、&#x1f3a8; 各方法深度解析1. GET - 数据查看器&am…