松散比较(PHP)(小迪网络安全笔记~
免责声明:本文章仅用于交流学习,因文章内容而产生的任何违法&未授权行为,与文章作者无关!!!
附:完整笔记目录~
ps:本人小白,笔记均在个人理解基础上整理,若有错误欢迎指正!
1.3 🐘松散比较(PHP)
-
引子:本章主要介绍一些由PHP自身语言特性可能产生的脆弱性,该内容往往被应用于PHP CTF入门题中,但在PHP Web开发时也可能被使用。
-
==
== 是php中的比较运算符,用于判断 == 左右两边的值是否相等。若两边的值类型不同,则会优先将两边的值类型转换为同一类型后再进行比较,也称这种比较方式为松散比较。
这其中使用最多也是最容易产生误解的就是数字、数字字符串、字符串之间的比较。这里给出官方规则:
If both operands are numeric strings, or one operand is a number and the other one is a numeric string, then the comparison is done numerically. These rules also apply to the switch statement.
简单来说,就是当数字与数字字符串,或者数字字符串与数字字符串之间进行比较时,都会被转换为数字后再比较,这些规则同样适用于switch。有没有感觉官方给出的内容有些含糊呢?这里举几个例子:// 在松散比较中,以下格式的字符串会被转换为什么数字呢?如: "sjjjer" "1999sj" "1999e9r" "1999.9er"我们分别来测试一下:
<?php $data1 = "sjjjer"; $data2 = 0; echo $data1 == $data2 ? "true" : "false"; // true --> php版本为7.3 // false --> php版本为8.2 // 从官方给出的解释来看,在php8版本前字符串默认被转换为数字0参与比较,8版本后被修复$data1 = "1999sj19"; $data2 = 1999; echo $data1 == $data2 ? "true" : "false"; // true // 可以看到,当字符串中同时出现字母与数字时,且数字在前, // 则在比较时会默认将字符串转换为出现第一个字母前的数字$data1 = "1999e9r"; $data2 = 1999; echo $data1 == $data2 ? "true" : "false"; // false // 为什么此时松散比较结果为false呢? // 是由于1999e9在转换为数字参与比较时,其实际值为1999 * 10^9,e是科学计数法的标识。 // So 我们可以修改1999的值为1999000000000再尝试比较 $data3 = 1999000000000; echo $data3 == $data1 ? "true" : "false"; // true$data1 = "1999.9er"; $data2 = 1999; echo $data1 == $data2 ? "true" : "false"; // false // 由于在比较时会将字符串转换为出现第一个字母前的数字 // 也就是 "1999.9er" --> 1999.9 (浮点数) // 当我们修改1999为1999.9时,再参与比较 $data3 = 1999.9; echo $data1 == $data3 ? "true" : "false"; // true -
switch()
上述所提松散比较时的类型转换规则同样适用于switch分支结构,也就说明php中switch结构在进行数据比较时也采用松散比较,这里来测试一下。
demo:<?php echo "请输入数据:"; $data1 = fgets(STDIN); // 由于fgets()从键盘获取到的数据默认携带 \n, // 因此需使用trim()去除 $data1 = trim($data1); switch ($data1) {case 0:echo 0;break;case 19:echo 19;break;case "sj":echo "sj";break;default:echo "数据未成功匹配!"; }// fgets()为获取用户所输入数据,默认返回值类型为字符串, // 也就是说data1的数据类型为字符串, // next 进入switch分支结构, // 该分支结构实质为字符串与数字、字符串与字符串的松散比较/*请输入数据:sj --> php版本7.3 0 请输入数据:19er 19 请输入数据:sj --> php版本8.2 sj*/ -
md5()
已知md5加密后会生成固定32位字符串。而在php的身份验证中,常常会存在这样的逻辑:获取用户输入密码并将其转换为md5值,随后再与数据库所存储用户密码比较(数据库中用户密码往往加密存储),若相等则成功验证身份。
若开发者所使用比较运算符为 == ,也就是本文所提松散比较,则可能会出现以下情况:- 用户密码经md5加密后的结果为"0e656002536496242128899000718690"。
- 由上文可知 e 为科学计数法的标识,因此在php中"0e656002536496242128899000718690" 为一串数字字符串。且使用 == 进行松散比较。
- 由php松散比较规则可知,当数字串与数字串比较时,会被转换为数字进行比较。而0e后无论跟什么其结果均为0,因此仅需再寻找另一个字符串,使其满足经md5加密后的结果为0e开头的数字字符串,就能实现,即使所输入密码与用户原码密码不一致,但经md5加密后再进行松散比较,返回结果为true。
我们来验证一下:
<?php echo "请输入您的密码:"; $input = trim(fgets(STDIN)); $password = md5("000dSb96"); if (md5($input) == $password) {echo "恭喜您!密码输入正确"; } else {echo "Sorry,您的密码有误"; }// 请输入您的密码:001st0X5 // 恭喜您!密码输入正确若想获取更多满足要求的字符串,可以写个脚本慢慢跑,这里给出我自己的脚本:
import hashlib import itertools import string# 定义函数,生成所有可能的8-16位字符串 def generate_strings():# 所有可用的字符:数字和字母chars = string.digits + string.ascii_lowercase + string.ascii_uppercase# 生成长度从8到16的字符串for length in range(8, 17):# 生成当前长度的所有可能字符串for s in itertools.product(chars, repeat=length):yield ''.join(s)# 定义函数,检查MD5值是否以0e开头且后续为数字 def check_md5(md5_hash):# 判断MD5值是否以"0e"开头,且后续部分全为数字return md5_hash.startswith("0e") and md5_hash[2:].isdigit()# 主程序 def main():# 打开result.txt文件以写入结果with open("result.txt", "w") as result_file:# 符合条件的字符串数量found_count = 0# 遍历生成的所有字符串for s in generate_strings():# 对字符串进行MD5加密md5_hash = hashlib.md5(s.encode('utf-8')).hexdigest()# 检查MD5是否满足条件if check_md5(md5_hash):# 打印符合条件的字符串和MD5值print(f"{s} {md5_hash}")# 写入到文件中result_file.write(f"{s} {md5_hash}\n")found_count += 1# 如果已经找到了10个符合条件的字符串,停止执行if found_count >= 10:breakif __name__ == "__main__":main()10分钟就跑出来了五条,看来还有很大的优化空间。。。
# 结果展示 000dSb96 0e656002536496242128899000718690 001st0X5 0e632311920444249596217934156166 001uTksg 0e012344733002178183175029976663 001yLWsp 0e561475551818519587284167859133 001CKN1u 0e364973363767512736620399322212 0029F2eL 0e819654840882947331243228254063 002zDdF8 0e693440086514416381258215413583 0031LEiY 0e050990879989909849271876008654 003kjZ6a 0e813458376037199230741560480845 003mHOrg 0e186417107900720544959665557875要是懒得用脚本跑,也可以参考:
https://blog.csdn.net/baidu_41871794/article/details/83750615,这篇博文作者也给了一些例子。 -
strcmp()
php中的字符串比较函数,strcmp($str1, $str2)会逐个字符比较字符串str1,str2的ASCII值,若str1 < str2 则返回值<0,若str1 > str2 则返回值>0,若 str1 = str2 返回值为0。
而在php 8版本之前,若所比较值类型为非字符串时,此时strcmp()函数报错且return 0,也就是说虽然strcmp()所接收参数不为字符串类型,但最终仍判断其字符串值相同。
demo:<?php $str1 = "sjjjer"; $str2 = $_GET["str"]; if (strcmp($str1, $str2) == 0) {echo "两字符串相等"; } else {echo "两字符串不等"; }// url: http://192.168.2.106:81/simplectf/SimplectfDemo4.php?str[]=sj // Warning: strcmp() expects parameter 2 to be string, array given in SimplectfDemo4.php on line 4 // 两字符串相等可以看到,虽然报错但仍执行了两字符串相等的逻辑。测试版本为php 7.3.4,php 8版本后修复。
-
in_array() & array_search()
in_array()用于查找指定值是否在数组中,返回true&false。array_search()用于查找指定值的键(索引),若找到返回索引值,若未找到返回false。同样的,这两个数组查找函数,若未指定其第三个值为true(默认为false),则采用松散比较。
demo:<?php $arr = [0, 19, "sj"]; var_dump(in_array("sjjjer", $arr)); var_dump(array_search("sj", $arr)); var_dump(array_search("sj", $arr, true));// bool(true) // int(0) // int(2) -
bool比较
上文案例所产生的有趣结果,主要基于数字、数字字符串、字符串之间的松散比较规则而成。
而接下来则对bool值与字符串的比较规则做一介绍:- ture 与 字符串比较结果为true,这里的字符串指:数字字符串(“19”),字符串(“sj”)。而false 与 字符串的比较结果为false,这里的字符串类型同true。
- true 与 空字符串比较结果为false,这里的空字符串指:“”,“0”。相反的,false 与 空字符串的比较结果为true。
注:这里的比较均为 ==
若想了解其余类型数据的比较结构,可参考官方比较表:
https://www.php.net/manual/en/types.comparisons.php
demo:<?php // 这里以json_decode() 与 unserialize()函数为例 $str = '{"username": true, "password": true}'; $data = json_decode($str); var_dump($data->username); if ($data->username == "admin" && $data->password == "sjjjer") {echo "身份认证成功!"; } else {echo "身份认证失败!"; }// bool(true) // 身份认证成功! // true与字符串松散比较结果为true。// 正确值为:$str = 'a:2:{s:8:"username";s:5:"admin";s:8:"password";s:6:"sjjjer";}'; $str = 'a:2:{s:8:"username";b:1;s:8:"password";b:1;}'; // 其中b表示bool类型,1为true $data = unserialize($str); if ($data['username'] == 'admin' && $data['password'] == 'sjjjer') {echo "身份认证成功!"; } else {echo "身份认证失败!"; }// 身份认证成功! -
===
以上内容均为开发者采用php松散比较时可能产生的结果,那有没有更为严谨的比较方式呢?采用===比较,===在比较时会先比较两边值类型,再比较值,若两边值类型不同也会返回false,也称这种比较方式为严格比较。
demo:<?php $data1 = "sj"; $data2 = 0; var_dump($data1 === $data2);// bool(false) -
实验
好了,你现在已经大致了解php的松散比较规则,以及使用松散比较可能会产生的问题了。接下来做几道ctf入门题吧:-
第一题
<?php $num = $_GET['num']; // 判断$num的值是否为数字或数字字符串 if (!is_numeric($num)) {echo $num;if ($num == 1) {echo ' flag!';} }答案:
http://192.168.2.106:81/simplectf/SimplectfDemo8.php?num=1sj -
第二题
<?php $md51 = md5('QNKCDZO'); $a = $_GET['a']; $md52 = md5($a); // 判断$a是否有值且值不为NULL if (isset($a)) {if ($a != 'QNKCDZO' && $md51 == $md52) {echo "flag";} else {echo "false!!!";} } else {echo "please input a"; }答案:
http://192.168.2.106:81/simplectf/SimplectfDemo9.php?a=000dSb96
至此,本章内容结束!
-
相关文章:
松散比较(PHP)(小迪网络安全笔记~
免责声明:本文章仅用于交流学习,因文章内容而产生的任何违法&未授权行为,与文章作者无关!!! 附:完整笔记目录~ ps:本人小白,笔记均在个人理解基础上整理,…...
一文了解如何使用 DBeaver 管理 DolphinDB
在日常的数据开发、分析和数据库运维中,一款优秀的 IDE 能够极大地提升工作效率。DBEaver 是一款由 Java 编写的一站式跨平台连接器,其社区版本已能支持连接近百种数据库,受到广大开发者的喜爱。近期。DolphinDB 与 DBeaver 团队共同努力&…...
网络基础知识指南|1-20个
1. IP地址: 即互联网协议地址,是用于标识互联网上的每一个设备或节点的唯一地址。IP地址的作用主要是进行网络设备的定位和路由,确保数据包可以从源设备准确地传送到目标设备。2. 子网掩码: 是用于将一个IP地址划分为网络地址和主机地址的工具。它通常与…...
01.09周四F34-Day50打卡
文章目录 1. -我大衣呢? -就在上次你放的地方。2. 这所学校是在曾经的影院上建立起来的。3. 她今天落到这个地步都怪你。4. 留得青山在,不怕没柴烧。(一息尚存,希望不灭。)5. 有善良的地方就有美德,有美德的地方就有奇迹。(《灰姑娘》原句)6. 为了和老外说话时不再发窘,所…...
Linux简介和环境搭建
Linux 介绍和环境搭建 1、发行版本 Linux 操作系统有多个主流发行版本,每个版本根据不同的目标、特点和使用场景为用户提供了不同的功能和体验。 Ubuntu • 特点:Ubuntu 是最为人熟知的 Linux 发行版之一,强调易用性和用户友好性ÿ…...
在移动端开发图表,uniapp+echarts,需要特殊处理,使用renderjs
1.首先要创建一个组件warning,用来装图表(我排除绿色那段代码为我的需求,不是必要代码) <template> <div class="task_container"> <div class="pop_body"> <div class="footer"> <warning…...
SpringBoot之LazyInitializationBeanFactoryPostProcessor类源码学习
源码分析 /**** author Andy Wilkinson* author Madhura Bhave* author Tyler Van Gorder* author Phillip Webb* since 2.2.0* see LazyInitializationExcludeFilter** 主要用于延迟初始化 Bean 的配置。它通过修改 BeanFactory 的配置来确保某些 Bean 在实际需要时才进行初始…...
United States of America三种表示
"United States of America", "United States", 和 "America" 都表示美国,但它们的使用场景和背景略有不同。以下是关于为什么这些名称可以合在一起表示美国的详细解释: 1. "United States of America" 全称&a…...
OpenCV基于均值漂移算法(pyrMeanShiftFiltering)的水彩画特效
1、均值漂移算法原理 pyrMeanShiftFiltering算法结合了均值迁移(Mean Shift)算法和图像金字塔(Image Pyramid)的概念,用于图像分割和平滑处理。以下是该算法的详细原理: 1.1 、均值迁移(Mean …...
【C++】拷贝构造函数与运算符重载
写在前面 拷贝构造函数、赋值运算符重载、取地址运算符都是属于类的默认成员函数! 默认成员函数是程序猿不显示声明定义,编译器会中生成。 在程序编写中,我们也经常使用拷贝的方式来获取到对应的值,例如整形变量拷贝int a 0; i…...
2024年开发语言热度排名
随着技术的不断发展和变化,编程语言的热度也在不断演变。2024年即将到来,我们有必要回顾和展望当前和未来的开发语言市场。本文将基于多个因素,包括行业需求、社区支持、流行度以及新兴趋势,对2024年的开发语言热度进行排名和分析…...
CryptoMamba:利用状态空间模型实现精确的比特币价格预测
“CryptoMamba: Leveraging State Space Models for Accurate Bitcoin Price Prediction” 论文地址:https://arxiv.org/pdf/2501.01010 Github地址:https://github.com/MShahabSepehri/CryptoMamba 摘要 预测比特币价格由于市场的高波动性和复杂的非线…...
MQTTX客户端使用
一、MQTT服务器( emqx )搭建 (1) 下载服务器MQTT Broker 从https://www.emqx.com/zh/downloads/broker/5.3.0/emqx-5.3.0-windows-amd64.zip下载MQTT Broker。 这里我使用的windows系统,下载对应版本工具:emqx-5.3.0-windows-a…...
网管平台(进阶篇):路由器的管理实践
在当今数字化时代,路由器作为网络连接的核心设备,其管理对于确保网络的稳定、高效和安全至关重要。本文旨在深入探讨路由器管理的重要性、基本设置步骤、高级功能配置以及日常维护,帮助读者构建一个高效且安全的网络环境。 一、路由器管理的…...
基于微信小程序的智能停车场管理系统设计与实现(LW+源码+讲解)
专注于大学生项目实战开发,讲解,毕业答疑辅导,欢迎高校老师/同行前辈交流合作✌。 技术范围:SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:…...
【Vue】父组件向子组件传递参数;子组件向父组件触发自定义事件
父组件向子组件传递参数 方法一:props 在 Vue 中,父组件向子组件传递数据主要通过props来实现,以下是具体的步骤: 父组件中传递数据 在父组件中,当需要调用子组件 AddSampleDialog 时,通过 v-bind 或其…...
搜广推校招面经七
抖音推荐算法 一、广告系统中的数据流处理方法,怎么避免延迟回流问题 延迟回流问题是指,实时系统(如广告点击预估)中,历史数据未及时更新或发生延迟,导致系统的实时预测偏离实际情况。避免延迟回流的方法有…...
Leetcode 518. 零钱兑换 II 动态规划
原题链接:Leetcode 518. 零钱兑换 II 可参考官解:零钱兑换 II 和这个解答:[Java/Python3/C]动态规划:拆分零钱兑换子问题(嵌套循环的秘密)【图解】 此题需要仔细想象和Leetcode 377. 组合总和 Ⅳ 动态规划…...
【EI 会议征稿】第四届材料工程与应用力学国际学术会议(ICMEAAE 2025)
2025 4th International Conference on Materials Engineering and Applied Mechanics 重要信息 大会官网:www.icmeaae.com 大会时间:2025年3月7-9日 大会地点:中国西安 截稿时间:2025年1月24日23:59 接受/拒稿通知…...
集合的线程安全
在多线程环境中,Java 的集合框架(Collection Framework)面临着线程安全的问题。当多个线程同时访问同一个集合对象时,可能会导致数据不一致、丢失更新或程序崩溃等严重问题。因此,在并发编程中确保集合操作的安全性至关…...
新手零基础入门:用快马AI生成你的第一个互联网个人主页
作为一个刚接触编程的新手,想要制作个人主页却不知从何下手是很常见的情况。最近我在InsCode(快马)平台上尝试用AI生成我的第一个网页,整个过程比想象中简单很多,特别适合零基础入门。下面分享我的学习过程和收获。 明确需求很关键 在开始前&…...
3个突破性方法让你永久掌控数字阅读自由
3个突破性方法让你永久掌控数字阅读自由 【免费下载链接】fanqienovel-downloader 下载番茄小说 项目地址: https://gitcode.com/gh_mirrors/fa/fanqienovel-downloader 你是否曾经历过这样的窘境:在通勤途中想继续阅读昨晚未看完的小说,却发现网…...
效率提升秘籍,用快马平台生成模块化openclaw配置代码
在深度学习项目中,模型配置往往是开发过程中最耗时的环节之一。最近我在尝试构建一个openclaw模型时,发现通过InsCode(快马)平台可以大幅提升效率,今天就分享一下我的实践心得。 模块化设计思路 传统模型开发中,我们经常需要反复编…...
3步攻克Linux应用管理痛点:面向开发者的AppImageLauncher优化方案
3步攻克Linux应用管理痛点:面向开发者的AppImageLauncher优化方案 【免费下载链接】AppImageLauncher Helper application for Linux distributions serving as a kind of "entry point" for running and integrating AppImages 项目地址: https://gitc…...
智能声控LED楼道灯电路设计与实现
1. 智能声控LED楼道灯的设计初衷 每次深夜回家摸黑找楼道开关的经历,相信大家都深有体会。传统楼道灯要么需要手动开关,要么长明浪费电力,而智能声控LED灯正是为解决这些痛点而生。这种灯具融合了声控、光控和LED照明三项技术,白…...
JIT加速不生效?你漏掉了这4个强制启用开关,3.14新增--enable-jit-unsafe-mode正在被92%团队忽略
第一章:JIT加速不生效?你漏掉了这4个强制启用开关,3.14新增--enable-jit-unsafe-mode正在被92%团队忽略Go 3.14 引入了激进的 JIT 编译优化路径,但默认关闭全部 JIT 后端。大量团队在升级后观察到 GOMAXPROCS8 下 CPU 利用率未提升…...
想找界面清爽操作直观的个人记账app?不妨看看这些实用分享
前阵子跟几个朋友聊起记录日常开支的事儿,一圈聊下来发现:10个人里有8个都试过整理日常收支,最后都放弃了。要么是打开app一堆乱七八糟的内容,找个记账按钮都要翻半天;要么是操作繁琐,买瓶水还要填一堆信息…...
千问3.5-2B网页版深度解析:前端上传逻辑、后端推理链路、JSON返回结构
千问3.5-2B网页版深度解析:前端上传逻辑、后端推理链路、JSON返回结构 1. 平台概述 千问3.5-2B是Qwen系列中的轻量级视觉语言模型,专为图片理解与文本生成任务优化设计。这个开箱即用的解决方案将复杂的AI能力封装成简单的网页交互,用户无需…...
Wan2.2-I2V-A14B开源模型:符合ISO/IEC 23053 AI系统可解释性要求
Wan2.2-I2V-A14B开源模型:符合ISO/IEC 23053 AI系统可解释性要求 1. 镜像概述与核心价值 Wan2.2-I2V-A14B私有部署镜像是一款专为文生视频场景优化的AI模型运行环境。这个镜像最突出的特点是完全符合ISO/IEC 23053标准对AI系统可解释性的要求,让用户不…...
Phi-3-Mini-128K快速原型开发:微信小程序集成AI对话功能
Phi-3-Mini-128K快速原型开发:微信小程序集成AI对话功能 最近在捣鼓一些AI小应用,发现很多开发者都想给自己的小程序加个“智能大脑”,让用户能聊聊天、问问问题。但一提到集成大模型,很多人就觉得门槛高、流程复杂,光…...
