PHP md5()函数详解,PHP计算MD5,md5()绕过,md5()漏洞原理剖析

「作者主页」:士别三日wyx
「作者简介」:CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者
「推荐专栏」:对网络安全感兴趣的小伙伴可以关注专栏《网络安全入门到精通》

md5() 可以计算字符串的「MD5散列值」

语法

string md5( $str, raw)

参数

  • $str :需要计算的字符串
  • raw :指定十六进制或二进制输出格式

返回值

计算成功,就返回MD5值;计算失败,就返回false。

1、基础使用

平时使用最多的就是「计算MD5」

实例:

echo md5('hello');

输出:

5d41402abc4b2a76b9719d911017c592

2、输出格式

raw 参数控制输出的「格式」

  • true :16个字符的「二进制格式」
  • false :(默认)32个字符的十六进制格式

如果你在项目中遇到MD5「加密结果不一致」的问题,可以观察两个加密结果的长度是否相同,比如一个结果是16位,而另一个结果是32位,这种情况就可以考虑更换输出格式来解决。

实例:

var_dump(md5('hello', true));
var_dump(md5('hello', false));

输出:

string(16) "]A@*�K*v�q��Œ"
string(32) "5d41402abc4b2a76b9719d911017c592"

3、科学计数法(0e绕过)

md5() 遇到「公式」,会先「运算」,再对运算结果「计算」MD5。

由于0和任何数相乘都等于0,所以0e开头的任何数,其MD5都是相同的。

比如 md5('0e1234'),会先运算成 md5(0),再计算MD5值。

补充:

0e是科学计数法,大小写等价,即 0e 和 0E 的结果相同。
科学记数法是一种记数的方法。把一个数表示成a与10的n次幂相乘的形式。
格式为:aEb=a×10^b,即a乘以10的b次幂。

实例:

echo md5(0).PHP_EOL;
echo md5(0e123).PHP_EOL;
echo md5(0e456).PHP_EOL;
echo md5(0E456);

输出:

cfcd208495d565ef66e7dff9f98764da
cfcd208495d565ef66e7dff9f98764da
cfcd208495d565ef66e7dff9f98764da
cfcd208495d565ef66e7dff9f98764da

绕过思路1:遇到弱比较( md5(a)==md5(b) )时,可以使用 0e绕过。

实例:

var_dump(md5(0e123) === md5(0e456));
var_dump(md5(0e123) == md5(0e456));

输出:

bool(true)
bool(true)

0e绕过还有一种变体:如果某个字符串的MD5值是0e开头的,在比较时,PHP也会先把它计算成 0,再参与比较。

绕过思路2:遇到若比较( md5(a)==0 ),可以传入QNKCDZO等绕过。

echo md5('QNKCDZO').PHP_EOL;
var_dump(md5('QNKCDZO') == 0);

输出:

0e830400451993494058024219903391
bool(true)

一些MD5值为0e开头的字符串:

QNKCDZO   => 0e830400451993494058024219903391
240610708 => 0e462097431906509019562988736854
s878926199a => 0e545993274517709034328855841020
s155964671a => 0e342768416822451524974117254469
s214587387a => 0e848240448830537924465865611904
s214587387a => 0e848240448830537924465865611904

4、数组类型(数组绕过)

md5() 不能处理数组,数组都返回null。同时会报一个Warning,不影响执行,不用管。

实例:

var_dump(md5([1,2]));
var_dump(md5([3,4]));

输出:

Warning: md5() expects parameter 1 to be string,
NULL
Warning: md5() expects parameter 1 to be string,
NULL

绕过思路:遇到强比较(a===b)时,可以使用数组绕过。GET传参时,以 a[]=1&b[]=2 这种形式传递数组。

实例:

$a = array(1,2,3);
$b = array(4,5,6);

var_dump(md5($a)===md5($b));

输出:

Warning: md5() expects parameter 1 to be string,
Warning: md5() expects parameter 1 to be string,
bool(true)

5、算数运算配合自动类型转换

md5() 遇到运算符,会先运算,再计算结果的MD5值。

实例:

echo md5(1+2).PHP_EOL;
echo md5(3).PHP_EOL;
echo md5(1*2).PHP_EOL;
echo md5(2).PHP_EOL;
echo md5(1&1).PHP_EOL;
echo md5(true);

输出:

eccbc87e4b5ce2fe28308fd9f2a7baf3
eccbc87e4b5ce2fe28308fd9f2a7baf3
c81e728d9d4c2f636f067f89cc14862c
c81e728d9d4c2f636f067f89cc14862c
c4ca4238a0b923820dcc509a6f75849b
c4ca4238a0b923820dcc509a6f75849b

当字符串与数字类型运算时,会将字符串转换成数字类型,再参与运算,最后计算运算结果的MD5值。

实例:

echo md5('1'+2).PHP_EOL;
echo md5(3).PHP_EOL;
echo md5('1'*2).PHP_EOL;
echo md5(2);

输出:

eccbc87e4b5ce2fe28308fd9f2a7baf3
eccbc87e4b5ce2fe28308fd9f2a7baf3
c81e728d9d4c2f636f067f89cc14862c
c81e728d9d4c2f636f067f89cc14862c

6、数值类型

虽然 md5() 要求传入字符串,但传入整数或小数也不会报错;数字相同时,数值型和字符串的计算结果是相同的。

实例:

var_dump(md5(123));
var_dump(md5('123'));
var_dump(md5(10.1));
var_dump(md5('10.1'));

输出:

string(32) "202cb962ac59075b964b07152d234b70"
string(32) "202cb962ac59075b964b07152d234b70"
string(32) "88d1955de012defb14b2db6f4797ff20"
string(32) "88d1955de012defb14b2db6f4797ff20"

<think>好的,我现在需要帮助用户理解MD5的0E绕过技术。首先,我应该回顾一下用户提供的引用内容,确保准确理解他们的需求。用户提到了三个引用,其中引用[1]解释了MD5的基本原理,引用[2]和[3]则涉及具体的CTF题目中的绕过方法,特别是使用ffifdyop字符串和PHPmd5函数的参数问题。 首先,我需要明确0E绕过原理。根据引用[1],MD5生成的是128位的哈希值,通常表示为32位的十六进制字符串。当这个字符串以0E开头,后面跟随纯数字时,PHP等弱类型语言在科学计数法比较时会将其视为0的指数,从而等于0。例如,0e123会被视为0^123,即0。因此,如果两个不同的字符串经过MD5哈希后都得到0e开头的哈希值,且后面的字符都是数字,那么它们在弱类型比较(==)时会被判定为相等,尽管它们的实际值不同。 接下来,用户提供的引用[2]中提到使用ffifdyop字符串进行绕过。我需要验证这个字符串的MD5哈希值是否符合0E开头的条件。计算md5('ffifdyop', true)的结果是原始二进制格式,转换成十六进制应该是276f722736c95d99e921722cf9ed621c,但根据引用[2],当第二个参数为true时,PHP返回的是16字节的二进制数据。如果这个二进制数据在转换为字符串时包含类似' or '这样的结构,可能会引发SQL注入。例如,如果二进制数据是某些特定字符,可能在SQL查询中被解释为永真条件,从而绕过密码检查。 然后,引用[3]中的代码示例展示了如何通过GET参数a和b的不等但MD5哈希值在弱比较下相等的情况。这里需要找到两个不同的输入,它们的MD5哈希值都以0E开头,后面跟随数字。例如,已知的字符串如240610708和QNKCDZO,它们的MD5哈希分别是0e462097431906509019562988736854和0e830400451993494058024219903391,这样在==比较时会被视为0 == 0,从而满足条件。 现在,我需要将这些信息整理成一个清晰的解释,说明0E绕过的技术原理和实现方法。同时,确保使用正确的LaTeX格式,行内公式用$...$,独立公式用$$...$$,并引用正确的来源。最后,生成相关问题,帮助用户进一步理解。 在整理过程中,需要注意用户提到的ffifdyop的应用场景可能涉及SQL注入,而不仅仅是0E比较,这需要区分不同情况下的绕过方法。例如,当md5函数的第二个参数为true时,返回原始二进制可能包含特殊字符导致SQL注入,而0E绕过则主要应用于弱类型比较的情况。因此,在回答中需要明确区分这两种不同的绕过技术,避免混淆。 总结起来,回答的结构应该包括: 1. 0E绕过原理,涉及弱类型语言的科学计数法比较。 2. 实现方法,提供已知的字符串示例和PHP代码示例。 3. 注意事项,如仅适用于弱类型比较,其他场景可能需要其他方法。 4. 相关引用标注,确保引用来源正确。 5. 生成相关问题,帮助用户深入探讨。 现在需要检查是否有遗漏或错误,比如确认示例字符串的MD5哈希是否正确,以及引用是否准确。例如,QNKCDZO的MD5确实是0e830400451993494058024219903391,而240610708的哈希是0e462097431906509019562988736854,这些都需要验证正确性。此外,在SQL注入的例子中,ffifdyop的二进制结果是否会导致永真条件,可能需要进一步解释其转换后的字符串形式,例如转换成字符串后是否为' 'or'6�]��!r,��b',这样的结构在SQL查询中可能形成类似'...'or'1'的条件,从而绕过验证。 最后,确保使用中文回答,并遵循用户的格式要求,包括代码块和引用标识的正确放置。</think>### MD5 0E绕过技术原理及实现方法 #### 技术原理 MD5的0E绕过是一种利用**弱类型语言特性**和**特定哈希值结构**的漏洞攻击技术。当两个不同的字符串经过MD5哈希后,若结果满足以下条件: 1. 哈希值以`0e`开头; 2. `0e`后跟随**纯数字**(如`0e123`), 则在PHP等弱类型语言中,这类字符串在科学计数法比较时会被视为`0`(即$0^N = 0$),从而实现绕过逻辑判断[^3]。 例如: 字符串`QNKCDZO`的MD5哈希为$0e830400451993494058024219903391$,另一字符串`240610708`的哈希为$0e462097431906509019562988736854$。在弱类型比较(`==`)时,两者会被判定为相等。 #### 实现方法 1. **构造特定字符串** 使用已知的MD5哈希结果为`0e+数字`的字符串,例如: ```php $a = "QNKCDZO"; // md5($a) = 0e830400451993494058024219903391 $b = "240610708"; // md5($b) = 0e462097431906509019562988736854 if ($a != $b && md5($a) == md5($b)) { echo "Bypass success!"; } ``` 此时条件成立,触发漏洞。 2. **利用二进制原始输出** 当PHP的`md5($str, true)`参数为`true`时,返回**16字节二进制数据**。某些二进制数据在转换为字符串后可能包含SQL注入的关键词(如`'or'`),例如: ```php md5("ffifdyop", true) = 'or'6�]��!r,��b' // 原始二进制转换为字符串后形成永真条件 ``` 这会导致SQL语句如`SELECT * FROM admin WHERE password='...'`被注入为`... WHERE password=''or'6...'`,从而绕过验证[^2]。 #### 注意事项 - 0E绕过**仅适用于弱类型比较**(`==`),严格比较(`===`)会校验类型和值。 - 需结合具体场景选择字符串(如`ffifdyop`用于SQL注入,`QNKCDZO`用于哈希比较)。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

士别三日wyx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值